Handle global git config $XDG_CONFIG_HOME/git/config
C git uses this alternate fallback location if the file exists and ~/.gitconfig does not. Implement this also for JGit. If both files exist, reading behavior is as if the XDG config was inserted between the HOME config and the system config. Writing behaviour is different: all changes will be applied only in the HOME config. Updates will occur in the XDG config only if the HOME config does not exist. This is consistent with the behavior of C git; compare [1], especially the sections on FILES and SCOPES, and the description of the --global option. [1] https://git-scm.com/docs/git-config Bug: 581875 Change-Id: I2460b9aa963fd2811ed8a5b77b05107d916f2b44 Signed-off-by: Thomas Wolf <twolf@apache.org>
This commit is contained in:
parent
0d5e017612
commit
a2f326b762
|
@ -0,0 +1,301 @@
|
|||
/*
|
||||
* Copyright (C) 2023, Thomas Wolf <twolf@apache.org> and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
package org.eclipse.jgit.storage.file;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.eclipse.jgit.util.FS;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
public class UserConfigFileTest {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder tmp = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
public void testParentOnlyLoad() throws Exception {
|
||||
Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg");
|
||||
Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor");
|
||||
Path user = tmp.getRoot().toPath().resolve("user.cfg");
|
||||
UserConfigFile config = new UserConfigFile(null, user.toFile(),
|
||||
xdg.toFile(), FS.DETECTED);
|
||||
config.load();
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config.getString("user", null, "name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadBoth() throws Exception {
|
||||
Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg");
|
||||
Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor");
|
||||
Path user = tmp.getRoot().toPath().resolve("user.cfg");
|
||||
Files.writeString(user, "[user]\n\temail = a.u.thor@example.com");
|
||||
UserConfigFile config = new UserConfigFile(null, user.toFile(),
|
||||
xdg.toFile(), FS.DETECTED);
|
||||
config.load();
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config.getString("user", null, "name"));
|
||||
assertEquals("a.u.thor@example.com",
|
||||
config.getString("user", null, "email"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverwriteChild() throws Exception {
|
||||
Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg");
|
||||
Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor");
|
||||
Path user = tmp.getRoot().toPath().resolve("user.cfg");
|
||||
Files.writeString(user, "[user]\n\temail = a.u.thor@example.com");
|
||||
UserConfigFile config = new UserConfigFile(null, user.toFile(),
|
||||
xdg.toFile(), FS.DETECTED);
|
||||
config.load();
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config.getString("user", null, "name"));
|
||||
assertEquals("a.u.thor@example.com",
|
||||
config.getString("user", null, "email"));
|
||||
config.setString("user", null, "name", "A U Thor");
|
||||
assertEquals("A U Thor", config.getString("user", null, "name"));
|
||||
config.save();
|
||||
UserConfigFile config2 = new UserConfigFile(null, user.toFile(),
|
||||
xdg.toFile(), FS.DETECTED);
|
||||
config2.load();
|
||||
assertEquals("A U Thor", config2.getString("user", null, "name"));
|
||||
assertEquals("a.u.thor@example.com",
|
||||
config.getString("user", null, "email"));
|
||||
FileBasedConfig cfg = new FileBasedConfig(null, xdg.toFile(),
|
||||
FS.DETECTED);
|
||||
cfg.load();
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
cfg.getString("user", null, "name"));
|
||||
assertNull(cfg.getString("user", null, "email"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnset() throws Exception {
|
||||
Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg");
|
||||
Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor");
|
||||
Path user = tmp.getRoot().toPath().resolve("user.cfg");
|
||||
Files.writeString(user, "[user]\n\temail = a.u.thor@example.com");
|
||||
UserConfigFile config = new UserConfigFile(null, user.toFile(),
|
||||
xdg.toFile(), FS.DETECTED);
|
||||
config.load();
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config.getString("user", null, "name"));
|
||||
assertEquals("a.u.thor@example.com",
|
||||
config.getString("user", null, "email"));
|
||||
config.setString("user", null, "name", "A U Thor");
|
||||
assertEquals("A U Thor", config.getString("user", null, "name"));
|
||||
config.unset("user", null, "name");
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config.getString("user", null, "name"));
|
||||
assertEquals("a.u.thor@example.com",
|
||||
config.getString("user", null, "email"));
|
||||
config.save();
|
||||
UserConfigFile config2 = new UserConfigFile(null, user.toFile(),
|
||||
xdg.toFile(), FS.DETECTED);
|
||||
config2.load();
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config2.getString("user", null, "name"));
|
||||
assertEquals("a.u.thor@example.com",
|
||||
config.getString("user", null, "email"));
|
||||
FileBasedConfig cfg = new FileBasedConfig(null, user.toFile(),
|
||||
FS.DETECTED);
|
||||
cfg.load();
|
||||
assertNull(cfg.getString("user", null, "name"));
|
||||
assertEquals("a.u.thor@example.com",
|
||||
cfg.getString("user", null, "email"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnsetSection() throws Exception {
|
||||
Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg");
|
||||
Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor");
|
||||
Path user = tmp.getRoot().toPath().resolve("user.cfg");
|
||||
Files.writeString(user, "[user]\n\temail = a.u.thor@example.com");
|
||||
UserConfigFile config = new UserConfigFile(null, user.toFile(),
|
||||
xdg.toFile(), FS.DETECTED);
|
||||
config.load();
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config.getString("user", null, "name"));
|
||||
assertEquals("a.u.thor@example.com",
|
||||
config.getString("user", null, "email"));
|
||||
config.unsetSection("user", null);
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config.getString("user", null, "name"));
|
||||
config.save();
|
||||
assertTrue(Files.readString(user).strip().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoChild() throws Exception {
|
||||
Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg");
|
||||
Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor");
|
||||
Path user = tmp.getRoot().toPath().resolve("user.cfg");
|
||||
UserConfigFile config = new UserConfigFile(null, user.toFile(),
|
||||
xdg.toFile(), FS.DETECTED);
|
||||
config.load();
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config.getString("user", null, "name"));
|
||||
assertNull(config.getString("user", null, "email"));
|
||||
config.setString("user", null, "email", "a.u.thor@example.com");
|
||||
assertEquals("a.u.thor@example.com",
|
||||
config.getString("user", null, "email"));
|
||||
config.save();
|
||||
assertFalse(Files.exists(user));
|
||||
UserConfigFile config2 = new UserConfigFile(null, user.toFile(),
|
||||
xdg.toFile(), FS.DETECTED);
|
||||
config2.load();
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config2.getString("user", null, "name"));
|
||||
assertEquals("a.u.thor@example.com",
|
||||
config2.getString("user", null, "email"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoFiles() throws Exception {
|
||||
Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg");
|
||||
Path user = tmp.getRoot().toPath().resolve("user.cfg");
|
||||
UserConfigFile config = new UserConfigFile(null, user.toFile(),
|
||||
xdg.toFile(), FS.DETECTED);
|
||||
config.load();
|
||||
assertNull(config.getString("user", null, "name"));
|
||||
assertNull(config.getString("user", null, "email"));
|
||||
config.setString("user", null, "name", "Archibald Ulysses Thor");
|
||||
config.setString("user", null, "email", "a.u.thor@example.com");
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config.getString("user", null, "name"));
|
||||
assertEquals("a.u.thor@example.com",
|
||||
config.getString("user", null, "email"));
|
||||
config.save();
|
||||
assertTrue(Files.exists(user));
|
||||
assertFalse(Files.exists(xdg));
|
||||
UserConfigFile config2 = new UserConfigFile(null, user.toFile(),
|
||||
xdg.toFile(), FS.DETECTED);
|
||||
config2.load();
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config2.getString("user", null, "name"));
|
||||
assertEquals("a.u.thor@example.com",
|
||||
config2.getString("user", null, "email"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetInXdg() throws Exception {
|
||||
Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg");
|
||||
Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor");
|
||||
Path user = tmp.getRoot().toPath().resolve("user.cfg");
|
||||
UserConfigFile config = new UserConfigFile(null, user.toFile(),
|
||||
xdg.toFile(), FS.DETECTED);
|
||||
config.load();
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config.getString("user", null, "name"));
|
||||
config.setString("user", null, "email", "a.u.thor@example.com");
|
||||
config.save();
|
||||
assertFalse(Files.exists(user));
|
||||
FileBasedConfig cfg = new FileBasedConfig(null, xdg.toFile(),
|
||||
FS.DETECTED);
|
||||
cfg.load();
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
cfg.getString("user", null, "name"));
|
||||
assertEquals("a.u.thor@example.com",
|
||||
cfg.getString("user", null, "email"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserConfigCreated() throws Exception {
|
||||
Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg");
|
||||
Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor");
|
||||
Path user = tmp.getRoot().toPath().resolve("user.cfg");
|
||||
Thread.sleep(3000); // Avoid racily clean isOutdated() below.
|
||||
UserConfigFile config = new UserConfigFile(null, user.toFile(),
|
||||
xdg.toFile(), FS.DETECTED);
|
||||
config.load();
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config.getString("user", null, "name"));
|
||||
Files.writeString(user,
|
||||
"[user]\n\temail = a.u.thor@example.com\n\tname = A U Thor");
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config.getString("user", null, "name"));
|
||||
assertTrue(config.isOutdated());
|
||||
config.load();
|
||||
assertEquals("A U Thor", config.getString("user", null, "name"));
|
||||
assertEquals("a.u.thor@example.com",
|
||||
config.getString("user", null, "email"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserConfigDeleted() throws Exception {
|
||||
Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg");
|
||||
Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor");
|
||||
Path user = tmp.getRoot().toPath().resolve("user.cfg");
|
||||
Files.writeString(user,
|
||||
"[user]\n\temail = a.u.thor@example.com\n\tname = A U Thor");
|
||||
Thread.sleep(3000); // Avoid racily clean isOutdated() below.
|
||||
UserConfigFile config = new UserConfigFile(null, user.toFile(),
|
||||
xdg.toFile(), FS.DETECTED);
|
||||
config.load();
|
||||
assertEquals("A U Thor", config.getString("user", null, "name"));
|
||||
assertEquals("a.u.thor@example.com",
|
||||
config.getString("user", null, "email"));
|
||||
Files.delete(user);
|
||||
assertEquals("A U Thor", config.getString("user", null, "name"));
|
||||
assertEquals("a.u.thor@example.com",
|
||||
config.getString("user", null, "email"));
|
||||
assertTrue(config.isOutdated());
|
||||
config.load();
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config.getString("user", null, "name"));
|
||||
assertNull(config.getString("user", null, "email"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testXdgConfigDeleted() throws Exception {
|
||||
Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg");
|
||||
Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor");
|
||||
Path user = tmp.getRoot().toPath().resolve("user.cfg");
|
||||
Thread.sleep(3000); // Avoid racily clean isOutdated() below.
|
||||
UserConfigFile config = new UserConfigFile(null, user.toFile(),
|
||||
xdg.toFile(), FS.DETECTED);
|
||||
config.load();
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config.getString("user", null, "name"));
|
||||
Files.delete(xdg);
|
||||
assertEquals("Archibald Ulysses Thor",
|
||||
config.getString("user", null, "name"));
|
||||
assertTrue(config.isOutdated());
|
||||
config.load();
|
||||
assertNull(config.getString("user", null, "name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testXdgConfigDeletedUserConfigExists() throws Exception {
|
||||
Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg");
|
||||
Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor");
|
||||
Path user = tmp.getRoot().toPath().resolve("user.cfg");
|
||||
Files.writeString(user,
|
||||
"[user]\n\temail = a.u.thor@example.com\n\tname = A U Thor");
|
||||
Thread.sleep(3000); // Avoid racily clean isOutdated() below.
|
||||
UserConfigFile config = new UserConfigFile(null, user.toFile(),
|
||||
xdg.toFile(), FS.DETECTED);
|
||||
config.load();
|
||||
assertEquals("A U Thor", config.getString("user", null, "name"));
|
||||
Files.delete(xdg);
|
||||
assertTrue(config.isOutdated());
|
||||
config.load();
|
||||
assertEquals("A U Thor", config.getString("user", null, "name"));
|
||||
}
|
||||
|
||||
}
|
|
@ -739,7 +739,7 @@ protected void fireConfigChangedEvent() {
|
|||
listeners.dispatch(new ConfigChangedEvent());
|
||||
}
|
||||
|
||||
String getRawString(final String section, final String subsection,
|
||||
private String getRawString(final String section, final String subsection,
|
||||
final String name) {
|
||||
String[] lst = getRawStringList(section, subsection, name);
|
||||
if (lst != null) {
|
||||
|
|
|
@ -34,7 +34,7 @@ public class DefaultTypedConfigGetter implements TypedConfigGetter {
|
|||
@Override
|
||||
public boolean getBoolean(Config config, String section, String subsection,
|
||||
String name, boolean defaultValue) {
|
||||
String n = config.getRawString(section, subsection, name);
|
||||
String n = config.getString(section, subsection, name);
|
||||
if (n == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.eclipse.jgit.errors.ConfigInvalidException;
|
||||
import org.eclipse.jgit.errors.LockFailedException;
|
||||
|
@ -52,6 +54,8 @@ public class FileBasedConfig extends StoredConfig {
|
|||
|
||||
private volatile ObjectId hash;
|
||||
|
||||
private AtomicBoolean exists = new AtomicBoolean();
|
||||
|
||||
/**
|
||||
* Create a configuration with no default fallback.
|
||||
*
|
||||
|
@ -99,6 +103,21 @@ public final File getFile() {
|
|||
return configFile;
|
||||
}
|
||||
|
||||
boolean exists() {
|
||||
return exists.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStringList(String section, String subsection, String name,
|
||||
List<String> values) {
|
||||
super.setStringList(section, subsection, name, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsetSection(String section, String subsection) {
|
||||
super.unsetSection(section, subsection);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
|
@ -144,6 +163,7 @@ public void load() throws IOException, ConfigInvalidException {
|
|||
clear();
|
||||
snapshot = lastSnapshot[0];
|
||||
}
|
||||
exists.set(wasRead != null);
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (C) 2023, Thomas Wolf <twolf@apache.org> and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
package org.eclipse.jgit.storage.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jgit.annotations.NonNull;
|
||||
import org.eclipse.jgit.errors.ConfigInvalidException;
|
||||
import org.eclipse.jgit.lib.Config;
|
||||
import org.eclipse.jgit.util.FS;
|
||||
|
||||
/**
|
||||
* User (global) git config based on two possible locations,
|
||||
* {@code ~/.gitconfig} and {@code $XDG_CONFIG_HOME/git/config}.
|
||||
* <p>
|
||||
* For reading, both locations are considered, first the XDG file, then the file
|
||||
* in the home directory. All updates occur in the last file read that exists,
|
||||
* or in the home directory file if neither exists. In other words: if only the
|
||||
* XDG file exists, it is updated, otherwise the home directory file is updated.
|
||||
* </p>
|
||||
*
|
||||
* @since 6.7
|
||||
*/
|
||||
public class UserConfigFile extends FileBasedConfig {
|
||||
|
||||
private final FileBasedConfig parent;
|
||||
|
||||
/**
|
||||
* Creates a new {@link UserConfigFile}.
|
||||
*
|
||||
* @param parent
|
||||
* parent {@link Config}; may be {@code null}
|
||||
* @param config
|
||||
* {@link File} for {@code ~/.gitconfig}
|
||||
* @param xdgConfig
|
||||
* {@link File} for {@code $XDG_CONFIG_HOME/.gitconfig}
|
||||
* @param fileSystem
|
||||
* {@link FS} to use for the two files; normally
|
||||
* {@link FS#DETECTED}
|
||||
*/
|
||||
public UserConfigFile(Config parent, @NonNull File config,
|
||||
@NonNull File xdgConfig, @NonNull FS fileSystem) {
|
||||
super(new FileBasedConfig(parent, xdgConfig, fileSystem), config,
|
||||
fileSystem);
|
||||
this.parent = (FileBasedConfig) getBaseConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStringList(String section, String subsection, String name,
|
||||
List<String> values) {
|
||||
if (exists() || !parent.exists()) {
|
||||
super.setStringList(section, subsection, name, values);
|
||||
} else {
|
||||
parent.setStringList(section, subsection, name, values);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unset(String section, String subsection, String name) {
|
||||
if (exists() || !parent.exists()) {
|
||||
super.unset(section, subsection, name);
|
||||
} else {
|
||||
parent.unset(section, subsection, name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsetSection(String section, String subsection) {
|
||||
if (exists() || !parent.exists()) {
|
||||
super.unsetSection(section, subsection);
|
||||
} else {
|
||||
parent.unsetSection(section, subsection);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOutdated() {
|
||||
return super.isOutdated() || parent.isOutdated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() throws IOException, ConfigInvalidException {
|
||||
if (super.isOutdated()) {
|
||||
super.load();
|
||||
}
|
||||
if (parent.isOutdated()) {
|
||||
parent.load();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() throws IOException {
|
||||
if (exists() || !parent.exists()) {
|
||||
if (exists() || !toText().strip().isEmpty()) {
|
||||
super.save();
|
||||
}
|
||||
} else {
|
||||
parent.save();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -39,6 +39,7 @@
|
|||
import org.eclipse.jgit.lib.ObjectChecker;
|
||||
import org.eclipse.jgit.lib.StoredConfig;
|
||||
import org.eclipse.jgit.storage.file.FileBasedConfig;
|
||||
import org.eclipse.jgit.storage.file.UserConfigFile;
|
||||
import org.eclipse.jgit.util.time.MonotonicClock;
|
||||
import org.eclipse.jgit.util.time.MonotonicSystemClock;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -124,8 +125,15 @@ public boolean isOutdated() {
|
|||
|
||||
@Override
|
||||
public FileBasedConfig openUserConfig(Config parent, FS fs) {
|
||||
return new FileBasedConfig(parent, new File(fs.userHome(), ".gitconfig"), //$NON-NLS-1$
|
||||
fs);
|
||||
File homeFile = new File(fs.userHome(), ".gitconfig"); //$NON-NLS-1$
|
||||
Path xdgPath = getXdgConfigDirectory(fs);
|
||||
if (xdgPath != null) {
|
||||
Path configPath = xdgPath.resolve("git") //$NON-NLS-1$
|
||||
.resolve(Constants.CONFIG);
|
||||
return new UserConfigFile(parent, homeFile, configPath.toFile(),
|
||||
fs);
|
||||
}
|
||||
return new FileBasedConfig(parent, homeFile, fs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue