org.hamcrest;version="[1.1.0,2.0.0)",
org.junit;version="[4.4.0,5.0.0)",
org.junit.experimental.theories;version="[4.4.0,5.0.0)",
+ org.junit.rules;version="[4.11.0,5.0.0)",
org.junit.runner;version="[4.4.0,5.0.0)",
org.junit.runners;version="[4.11.0,5.0.0)",
org.slf4j;version="[1.7.2,2.0.0)"
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Iterator;
import org.eclipse.jgit.api.MergeCommand.FastForwardMode;
import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.junit.MockSystemReader;
import org.eclipse.jgit.merge.MergeConfig;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.SystemReader;
import org.junit.After;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
/**
* Test reading of git config
*/
public class ConfigTest {
+ @Rule
+ public ExpectedException expectedEx = ExpectedException.none();
+
+ @Rule
+ public TemporaryFolder tmp = new TemporaryFolder();
+
@After
public void tearDown() {
SystemReader.setInstance(null);
assertTrue(c.getBoolean("foo", "bar", false));
}
+ @Test
+ public void testIncludeInvalidName() throws ConfigInvalidException {
+ expectedEx.expect(ConfigInvalidException.class);
+ expectedEx.expectMessage(JGitText.get().invalidLineInConfigFile);
+ parse("[include]\nbar\n");
+ }
+
+ @Test
+ public void testIncludeNoValue() throws ConfigInvalidException {
+ expectedEx.expect(ConfigInvalidException.class);
+ expectedEx.expectMessage(JGitText.get().invalidLineInConfigFile);
+ parse("[include]\npath\n");
+ }
+
+ @Test
+ public void testIncludeEmptyValue() throws ConfigInvalidException {
+ expectedEx.expect(ConfigInvalidException.class);
+ expectedEx.expectMessage(JGitText.get().invalidLineInConfigFile);
+ parse("[include]\npath=\n");
+ }
+
+ @Test
+ public void testIncludeValuePathNotFound() throws ConfigInvalidException {
+ String notFound = "/not/found";
+ expectedEx.expect(ConfigInvalidException.class);
+ expectedEx.expectMessage(notFound);
+ parse("[include]\npath=" + notFound + "\n");
+ }
+
+ @Test
+ public void testIncludeTooManyRecursions() throws IOException {
+ File config = tmp.newFile("config");
+ String include = "[include]\npath=" + config.toPath() + "\n";
+ Files.write(config.toPath(), include.getBytes());
+ FileBasedConfig fbConfig = new FileBasedConfig(null, config,
+ FS.DETECTED);
+ try {
+ fbConfig.load();
+ fail();
+ } catch (ConfigInvalidException cie) {
+ assertEquals(JGitText.get().tooManyIncludeRecursions,
+ cie.getCause().getMessage());
+ }
+ }
+
+ @Test
+ public void testInclude() throws IOException, ConfigInvalidException {
+ File config = tmp.newFile("config");
+ File more = tmp.newFile("config.more");
+ File other = tmp.newFile("config.other");
+
+ String fooBar = "[foo]\nbar=true\n";
+ String includeMore = "[include]\npath=" + more.toPath() + "\n";
+ String includeOther = "path=" + other.toPath() + "\n";
+ String fooPlus = fooBar + includeMore + includeOther;
+ Files.write(config.toPath(), fooPlus.getBytes());
+
+ String fooMore = "[foo]\nmore=bar\n";
+ Files.write(more.toPath(), fooMore.getBytes());
+
+ String otherMore = "[other]\nmore=bar\n";
+ Files.write(other.toPath(), otherMore.getBytes());
+
+ Config parsed = parse("[include]\npath=" + config.toPath() + "\n");
+ assertTrue(parsed.getBoolean("foo", "bar", false));
+ assertEquals("bar", parsed.getString("foo", null, "more"));
+ assertEquals("bar", parsed.getString("other", null, "more"));
+ }
+
private static void assertReadLong(long exp) throws ConfigInvalidException {
assertReadLong(exp, String.valueOf(exp));
}
invalidIdLength=Invalid id length {0}; should be {1}
invalidIgnoreParamSubmodule=Found invalid ignore param for submodule {0}.
invalidIgnoreRule=Exception caught while parsing ignore rule ''{0}''.
+invalidIncludedPathInConfigFile=Invalid included path in config file: {0}
invalidIntegerValue=Invalid integer value: {0}.{1}={2}
invalidKey=Invalid key: {0}
invalidLineInConfigFile=Invalid line in config file
tagOnRepoWithoutHEADCurrentlyNotSupported=Tag on repository without HEAD currently not supported
theFactoryMustNotBeNull=The factory must not be null
timerAlreadyTerminated=Timer already terminated
+tooManyIncludeRecursions=Too many recursions; circular includes in config file(s)?
topologicalSortRequired=Topological sort required.
transactionAborted=transaction aborted
transportExceptionBadRef=Empty ref: {0}: {1}
/***/ public String invalidIdLength;
/***/ public String invalidIgnoreParamSubmodule;
/***/ public String invalidIgnoreRule;
+ /***/ public String invalidIncludedPathInConfigFile;
/***/ public String invalidIntegerValue;
/***/ public String invalidKey;
/***/ public String invalidLineInConfigFile;
/***/ public String transactionAborted;
/***/ public String theFactoryMustNotBeNull;
/***/ public String timerAlreadyTerminated;
+ /***/ public String tooManyIncludeRecursions;
/***/ public String topologicalSortRequired;
/***/ public String transportExceptionBadRef;
/***/ public String transportExceptionEmptyRef;
package org.eclipse.jgit.lib;
+import java.io.File;
+import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import org.eclipse.jgit.events.ListenerHandle;
import org.eclipse.jgit.events.ListenerList;
import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.util.IO;
+import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.StringUtils;
private static final long KiB = 1024;
private static final long MiB = 1024 * KiB;
private static final long GiB = 1024 * MiB;
+ private static final int MAX_DEPTH = 999;
/** the change listeners */
private final ListenerList listeners = new ListenerList();
* made to {@code this}.
*/
public void fromText(final String text) throws ConfigInvalidException {
+ state.set(newState(fromTextRecurse(text, 1)));
+ }
+
+ private List<ConfigLine> fromTextRecurse(final String text, int depth)
+ throws ConfigInvalidException {
+ if (depth > MAX_DEPTH) {
+ throw new ConfigInvalidException(
+ JGitText.get().tooManyIncludeRecursions);
+ }
final List<ConfigLine> newEntries = new ArrayList<ConfigLine>();
final StringReader in = new StringReader(text);
ConfigLine last = null;
} else
e.value = readValue(in, false, -1);
+ if (e.section.equals("include")) { //$NON-NLS-1$
+ addIncludedConfig(newEntries, e, depth);
+ }
} else
throw new ConfigInvalidException(JGitText.get().invalidLineInConfigFile);
}
- state.set(newState(newEntries));
+ return newEntries;
+ }
+
+ private void addIncludedConfig(final List<ConfigLine> newEntries,
+ ConfigLine line, int depth) throws ConfigInvalidException {
+ if (!line.name.equals("path") || //$NON-NLS-1$
+ line.value == null || line.value.equals(MAGIC_EMPTY_VALUE)) {
+ throw new ConfigInvalidException(
+ JGitText.get().invalidLineInConfigFile);
+ }
+ File path = new File(line.value);
+ try {
+ byte[] bytes = IO.readFully(path);
+ String decoded;
+ if (isUtf8(bytes)) {
+ decoded = RawParseUtils.decode(RawParseUtils.UTF8_CHARSET,
+ bytes, 3, bytes.length);
+ } else {
+ decoded = RawParseUtils.decode(bytes);
+ }
+ newEntries.addAll(fromTextRecurse(decoded, depth + 1));
+ } catch (IOException ioe) {
+ throw new ConfigInvalidException(MessageFormat.format(
+ JGitText.get().invalidIncludedPathInConfigFile, path));
+ }
}
private ConfigSnapshot newState() {