aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn O. Pearce <spearce@spearce.org>2010-09-07 17:14:27 -0700
committerShawn O. Pearce <spearce@spearce.org>2010-09-07 17:14:27 -0700
commit9f61c615e858c038a754dc512476ccf215385d8f (patch)
treed60be279c7615e01ac56549dde4b2ca561d17ae5
parent67263e2056108e471d684c3cef9e719724b51220 (diff)
downloadjgit-9f61c615e858c038a754dc512476ccf215385d8f.tar.gz
jgit-9f61c615e858c038a754dc512476ccf215385d8f.zip
Support core.autocrlf = input
The core.autocrlf variable can take on three values: false, true, and input. Parsing it as a boolean is wrong, we instead need to parse a tri-state enumeration. Add support for parsing and setting enum values from Java from and to the text based configuration file, and use that to handle the autocrlf variable. Bug: 301775 Change-Id: I81b9e33087a33d2ef2eac89ba93b9e83b7ecc223 Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java32
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/AbstractTreeIteratorTest.java3
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorWithTimeControl.java3
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java115
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java18
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java10
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeOptions.java11
9 files changed, 187 insertions, 11 deletions
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 e12e869ec5..eb9f03c550 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
@@ -229,6 +229,38 @@ public class ConfigTest extends TestCase {
assertFalse(c.getBoolean("s", "b", true));
}
+ static enum TestEnum {
+ ONE_TWO;
+ }
+
+ public void testGetEnum() throws ConfigInvalidException {
+ Config c = parse("[s]\na = ON\nb = input\nc = true\nd = off\n");
+ assertSame(CoreConfig.AutoCRLF.TRUE, c.getEnum("s", null, "a",
+ CoreConfig.AutoCRLF.FALSE));
+
+ assertSame(CoreConfig.AutoCRLF.INPUT, c.getEnum("s", null, "b",
+ CoreConfig.AutoCRLF.FALSE));
+
+ assertSame(CoreConfig.AutoCRLF.TRUE, c.getEnum("s", null, "c",
+ CoreConfig.AutoCRLF.FALSE));
+
+ assertSame(CoreConfig.AutoCRLF.FALSE, c.getEnum("s", null, "d",
+ CoreConfig.AutoCRLF.TRUE));
+
+ c = new Config();
+ assertSame(CoreConfig.AutoCRLF.FALSE, c.getEnum("s", null, "d",
+ CoreConfig.AutoCRLF.FALSE));
+
+ c = parse("[s \"b\"]\n\tc = one two\n");
+ assertSame(TestEnum.ONE_TWO, c.getEnum("s", "b", "c", TestEnum.ONE_TWO));
+ }
+
+ public void testSetEnum() {
+ final Config c = new Config();
+ c.setEnum("s", "b", "c", TestEnum.ONE_TWO);
+ assertEquals("[s \"b\"]\n\tc = one two\n", c.toText());
+ }
+
public void testReadLong() throws ConfigInvalidException {
assertReadLong(1L);
assertReadLong(-1L);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/AbstractTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/AbstractTreeIteratorTest.java
index 72354e4e95..cc7d0ad9ef 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/AbstractTreeIteratorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/AbstractTreeIteratorTest.java
@@ -52,6 +52,7 @@ import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.lib.CoreConfig.AutoCRLF;
public class AbstractTreeIteratorTest extends TestCase {
@@ -62,7 +63,7 @@ public class AbstractTreeIteratorTest extends TestCase {
public class FakeTreeIterator extends WorkingTreeIterator {
public FakeTreeIterator(String pathName, FileMode fileMode) {
- super(prefix(pathName), new WorkingTreeOptions(false));
+ super(prefix(pathName), new WorkingTreeOptions(AutoCRLF.FALSE));
mode = fileMode.getBits();
final int s = pathName.lastIndexOf('/');
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorWithTimeControl.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorWithTimeControl.java
index 58fb5297a2..f15454ba07 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorWithTimeControl.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorWithTimeControl.java
@@ -48,6 +48,7 @@ import java.util.TreeSet;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.CoreConfig.AutoCRLF;
import org.eclipse.jgit.util.FS;
/**
@@ -87,7 +88,7 @@ public class FileTreeIteratorWithTimeControl extends FileTreeIterator {
public FileTreeIteratorWithTimeControl(File f, FS fs,
TreeSet<Long> modTimes) {
- super(f, fs, new WorkingTreeOptions(false));
+ super(f, fs, new WorkingTreeOptions(AutoCRLF.FALSE));
this.modTimes = modTimes;
}
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
index cd932c6d83..e8ec148bdd 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
@@ -136,6 +136,9 @@ emptyPathNotPermitted=Empty path not permitted.
encryptionError=Encryption error: {0}
endOfFileInEscape=End of file in escape
entryNotFoundByPath=Entry not found by path: {0}
+enumValueNotSupported2=Invalid value: {0}.{1}={2}
+enumValueNotSupported3=Invalid value: {0}.{1}.{2}={3}
+enumValuesNotAvailable=Enumerated values of type {0} not available
errorDecodingFromFile=Error decoding from file {0}
errorEncodingFromFile=Error encoding from file {0}
errorInBase64CodeReadingStream=Error in Base64 code reading stream.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
index 7fa265847b..c7b5a9ee63 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
@@ -196,6 +196,9 @@ public class JGitText extends TranslationBundle {
/***/ public String encryptionError;
/***/ public String endOfFileInEscape;
/***/ public String entryNotFoundByPath;
+ /***/ public String enumValueNotSupported2;
+ /***/ public String enumValueNotSupported3;
+ /***/ public String enumValuesNotAvailable;
/***/ public String errorDecodingFromFile;
/***/ public String errorEncodingFromFile;
/***/ public String errorInBase64CodeReadingStream;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
index 884f49845c..daad67e29c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
@@ -334,6 +334,95 @@ public class Config {
}
/**
+ * Parse an enumeration from the configuration.
+ *
+ * @param <T>
+ * type of the enumeration object.
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @param defaultValue
+ * default value to return if no value was present.
+ * @return the selected enumeration value, or {@code defaultValue}.
+ */
+ public <T extends Enum<?>> T getEnum(final String section,
+ final String subsection, final String name, final T defaultValue) {
+ final T[] all = allValuesOf(defaultValue);
+ return getEnum(all, section, subsection, name, defaultValue);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> T[] allValuesOf(final T value) {
+ try {
+ return (T[]) value.getClass().getMethod("values").invoke(null);
+ } catch (Exception err) {
+ String typeName = value.getClass().getName();
+ String msg = MessageFormat.format(
+ JGitText.get().enumValuesNotAvailable, typeName);
+ throw new IllegalArgumentException(msg, err);
+ }
+ }
+
+ /**
+ * Parse an enumeration from the configuration.
+ *
+ * @param <T>
+ * type of the enumeration object.
+ * @param all
+ * all possible values in the enumeration which should be
+ * recognized. Typically {@code EnumType.values()}.
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @param defaultValue
+ * default value to return if no value was present.
+ * @return the selected enumeration value, or {@code defaultValue}.
+ */
+ public <T extends Enum<?>> T getEnum(final T[] all, final String section,
+ final String subsection, final String name, final T defaultValue) {
+ String value = getString(section, subsection, name);
+ if (value == null)
+ return defaultValue;
+
+ String n = value.replace(' ', '_');
+ T trueState = null;
+ T falseState = null;
+ for (T e : all) {
+ if (StringUtils.equalsIgnoreCase(e.name(), n))
+ return e;
+ else if (StringUtils.equalsIgnoreCase(e.name(), "TRUE"))
+ trueState = e;
+ else if (StringUtils.equalsIgnoreCase(e.name(), "FALSE"))
+ falseState = e;
+ }
+
+ // This is an odd little fallback. C Git sometimes allows boolean
+ // values in a tri-state with other things. If we have both a true
+ // and a false value in our enumeration, assume its one of those.
+ //
+ if (trueState != null && falseState != null) {
+ try {
+ return StringUtils.toBoolean(n) ? trueState : falseState;
+ } catch (IllegalArgumentException err) {
+ // Fall through and use our custom error below.
+ }
+ }
+
+ if (subsection != null)
+ throw new IllegalArgumentException(MessageFormat.format(JGitText
+ .get().enumValueNotSupported3, section, name, value));
+ else
+ throw new IllegalArgumentException(MessageFormat.format(JGitText
+ .get().enumValueNotSupported2, section, name, value));
+ }
+
+ /**
* Get string value
*
* @param section
@@ -634,6 +723,32 @@ public class Config {
* name = value
* </pre>
*
+ * @param <T>
+ * type of the enumeration object.
+ * @param section
+ * section name, e.g "branch"
+ * @param subsection
+ * optional subsection value, e.g. a branch name
+ * @param name
+ * parameter name, e.g. "filemode"
+ * @param value
+ * parameter value
+ */
+ public <T extends Enum<?>> void setEnum(final String section,
+ final String subsection, final String name, final T value) {
+ String n = value.name().toLowerCase().replace('_', ' ');
+ setString(section, subsection, name, n);
+ }
+
+ /**
+ * Add or modify a configuration value. The parameters will result in a
+ * configuration entry like this.
+ *
+ * <pre>
+ * [section &quot;subsection&quot;]
+ * name = value
+ * </pre>
+ *
* @param section
* section name, e.g "branch"
* @param subsection
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java
index 249b95ec3c..f644d2c697 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java
@@ -61,19 +61,31 @@ public class CoreConfig {
}
};
+ /** Permissible values for {@code core.autocrlf}. */
+ public static enum AutoCRLF {
+ /** Automatic CRLF->LF conversion is disabled. */
+ FALSE,
+
+ /** Automatic CRLF->LF conversion is enabled. */
+ TRUE,
+
+ /** CRLF->LF performed, but no LF->CRLF. */
+ INPUT;
+ }
+
private final int compression;
private final int packIndexVersion;
private final boolean logAllRefUpdates;
- private final boolean autoCRLF;
+ private final AutoCRLF autoCRLF;
private CoreConfig(final Config rc) {
compression = rc.getInt("core", "compression", DEFAULT_COMPRESSION);
packIndexVersion = rc.getInt("pack", "indexversion", 2);
logAllRefUpdates = rc.getBoolean("core", "logallrefupdates", true);
- autoCRLF = rc.getBoolean("core", "autocrlf", false);
+ autoCRLF = rc.getEnum("core", null, "autocrlf", AutoCRLF.FALSE);
}
/**
@@ -101,7 +113,7 @@ public class CoreConfig {
/**
* @return whether automatic CRLF conversion has been configured
*/
- public boolean isAutoCRLF() {
+ public AutoCRLF getAutoCRLF() {
return autoCRLF;
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
index 5cc061bbb4..b292c3cdd3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
@@ -299,7 +299,15 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
}
private boolean mightNeedCleaning(Entry entry) {
- return options.isAutoCRLF();
+ switch (options.getAutoCRLF()) {
+ case FALSE:
+ default:
+ return false;
+
+ case TRUE:
+ case INPUT:
+ return true;
+ }
}
private boolean isBinary(Entry entry, byte[] content, int sz) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeOptions.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeOptions.java
index 50da3302d6..6929046c25 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeOptions.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeOptions.java
@@ -44,6 +44,7 @@ package org.eclipse.jgit.treewalk;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.CoreConfig;
+import org.eclipse.jgit.lib.CoreConfig.AutoCRLF;
/**
* Contains options used by the WorkingTreeIterator.
@@ -57,7 +58,7 @@ public class WorkingTreeOptions {
* @return created working tree options
*/
public static WorkingTreeOptions createDefaultInstance() {
- return new WorkingTreeOptions(false);
+ return new WorkingTreeOptions(AutoCRLF.FALSE);
}
/**
@@ -69,14 +70,14 @@ public class WorkingTreeOptions {
* @return created working tree options
*/
public static WorkingTreeOptions createConfigurationInstance(Config config) {
- return new WorkingTreeOptions(config.get(CoreConfig.KEY).isAutoCRLF());
+ return new WorkingTreeOptions(config.get(CoreConfig.KEY).getAutoCRLF());
}
/**
* Indicates whether EOLs of text files should be converted to '\n' before
* calculating the blob ID.
**/
- private final boolean autoCRLF;
+ private final AutoCRLF autoCRLF;
/**
* Creates new options.
@@ -85,7 +86,7 @@ public class WorkingTreeOptions {
* indicates whether EOLs of text files should be converted to
* '\n' before calculating the blob ID.
*/
- public WorkingTreeOptions(boolean autoCRLF) {
+ public WorkingTreeOptions(AutoCRLF autoCRLF) {
this.autoCRLF = autoCRLF;
}
@@ -95,7 +96,7 @@ public class WorkingTreeOptions {
*
* @return true if EOLs should be canonicalized.
*/
- public boolean isAutoCRLF() {
+ public AutoCRLF getAutoCRLF() {
return autoCRLF;
}
}