From: Marc Strapetz Date: Sat, 18 Nov 2017 16:50:30 +0000 (+0100) Subject: FileBasedConfig: support for relative includes X-Git-Tag: v4.10.0.201712302008-r~104 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=26d78902f8843f24556ba152a38b5f89b21af107;p=jgit.git FileBasedConfig: support for relative includes Relative include.path are now resolved against the config's parent directory. include.path starting with ~/ are resolved against the user's home directory Change-Id: I91911ef404126618b1ddd3589294824a0ad919e6 Signed-off-by: Marc Strapetz --- diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java index 7902bb5303..13d546f2b7 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java @@ -855,7 +855,7 @@ public class ConfigTest { assertEquals("bar", parsed.getString("other", null, "more")); } - private static String pathToString(File file) { + public static String pathToString(File file) { final String path = file.getPath(); if (SystemReader.getInstance().isWindows()) { return path.replace('\\', '/'); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileBasedConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileBasedConfigTest.java index ee845c5325..2134e1b8dc 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileBasedConfigTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileBasedConfigTest.java @@ -52,6 +52,7 @@ import java.io.FileOutputStream; import java.io.IOException; import org.eclipse.jgit.errors.ConfigInvalidException; +import org.eclipse.jgit.lib.ConfigTest; import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FileUtils; import org.eclipse.jgit.util.IO; @@ -157,9 +158,89 @@ public class FileBasedConfigTest { assertArrayEquals(bos2.toByteArray(), IO.readFully(file)); } + @Test + public void testIncludeAbsolute() + throws IOException, ConfigInvalidException { + final File includedFile = createFile(CONTENT1.getBytes()); + final ByteArrayOutputStream bos = new ByteArrayOutputStream(); + bos.write("[include]\npath=".getBytes()); + bos.write(ConfigTest.pathToString(includedFile).getBytes()); + + final File file = createFile(bos.toByteArray()); + final FileBasedConfig config = new FileBasedConfig(file, FS.DETECTED); + config.load(); + assertEquals(ALICE, config.getString(USER, null, NAME)); + } + + @Test + public void testIncludeRelativeDot() + throws IOException, ConfigInvalidException { + final File includedFile = createFile(CONTENT1.getBytes(), "dir1"); + final ByteArrayOutputStream bos = new ByteArrayOutputStream(); + bos.write("[include]\npath=".getBytes()); + bos.write(("./" + includedFile.getName()).getBytes()); + + final File file = createFile(bos.toByteArray(), "dir1"); + final FileBasedConfig config = new FileBasedConfig(file, FS.DETECTED); + config.load(); + assertEquals(ALICE, config.getString(USER, null, NAME)); + } + + @Test + public void testIncludeRelativeDotDot() + throws IOException, ConfigInvalidException { + final File includedFile = createFile(CONTENT1.getBytes(), "dir1"); + final ByteArrayOutputStream bos = new ByteArrayOutputStream(); + bos.write("[include]\npath=".getBytes()); + bos.write(("../" + includedFile.getParentFile().getName() + "/" + + includedFile.getName()).getBytes()); + + final File file = createFile(bos.toByteArray(), "dir2"); + final FileBasedConfig config = new FileBasedConfig(file, FS.DETECTED); + config.load(); + assertEquals(ALICE, config.getString(USER, null, NAME)); + } + + @Test + public void testIncludeRelativeDotDotNotFound() + throws IOException, ConfigInvalidException { + final File includedFile = createFile(CONTENT1.getBytes()); + final ByteArrayOutputStream bos = new ByteArrayOutputStream(); + bos.write("[include]\npath=".getBytes()); + bos.write(("../" + includedFile.getName()).getBytes()); + + final File file = createFile(bos.toByteArray()); + final FileBasedConfig config = new FileBasedConfig(file, FS.DETECTED); + config.load(); + assertEquals(null, config.getString(USER, null, NAME)); + } + + @Test + public void testIncludeWithTilde() + throws IOException, ConfigInvalidException { + final File includedFile = createFile(CONTENT1.getBytes(), "home"); + final ByteArrayOutputStream bos = new ByteArrayOutputStream(); + bos.write("[include]\npath=".getBytes()); + bos.write(("~/" + includedFile.getName()).getBytes()); + + final File file = createFile(bos.toByteArray(), "repo"); + final FS fs = FS.DETECTED.newInstance(); + fs.setUserHome(includedFile.getParentFile()); + + final FileBasedConfig config = new FileBasedConfig(file, fs); + config.load(); + assertEquals(ALICE, config.getString(USER, null, NAME)); + } + private File createFile(byte[] content) throws IOException { - trash.mkdirs(); - File f = File.createTempFile(getClass().getName(), null, trash); + return createFile(content, null); + } + + private File createFile(byte[] content, String subdir) throws IOException { + File dir = subdir != null ? new File(trash, subdir) : trash; + dir.mkdirs(); + + File f = File.createTempFile(getClass().getName(), null, dir); FileOutputStream os = new FileOutputStream(f, true); try { os.write(content); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java index 6cfd352ec1..ba62418e1d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java @@ -55,6 +55,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.text.MessageFormat; +import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.errors.LockFailedException; import org.eclipse.jgit.internal.JGitText; @@ -74,6 +75,8 @@ import org.eclipse.jgit.util.RawParseUtils; public class FileBasedConfig extends StoredConfig { private final File configFile; + private final FS fs; + private boolean utf8Bom; private volatile FileSnapshot snapshot; @@ -107,6 +110,7 @@ public class FileBasedConfig extends StoredConfig { public FileBasedConfig(Config base, File cfgLocation, FS fs) { super(base); configFile = cfgLocation; + this.fs = fs; this.snapshot = FileSnapshot.DIRTY; this.hash = ObjectId.zeroId(); } @@ -240,4 +244,30 @@ public class FileBasedConfig extends StoredConfig { public boolean isOutdated() { return snapshot.isModified(getFile()); } + + /** + * @since 4.10 + */ + @Override + @Nullable + protected byte[] readIncludedConfig(String relPath) + throws ConfigInvalidException { + final File file; + if (relPath.startsWith("~/")) { //$NON-NLS-1$ + file = fs.resolve(fs.userHome(), relPath.substring(2)); + } else { + file = fs.resolve(configFile.getParentFile(), relPath); + } + + if (!file.exists()) { + return null; + } + + try { + return IO.readFully(file); + } catch (IOException ioe) { + throw new ConfigInvalidException(MessageFormat + .format(JGitText.get().cannotReadFile, relPath), ioe); + } + } }