{"thread":{"id":"19231","subject":"[JGIT PATCH 1/2] Add support for boolean config values \"yes\", \"no\"","startedAt":"2009-05-07T15:05:13Z","lastAt":"2009-05-08T14:34:36Z","messageCount":18,"participants":["Shawn O. Pearce","Brandon Casey","Robin Rosenberg","Linus Torvalds","Junio C Hamano","Alex Riesen","Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"113225","messageId":"1241708714-20326-1-git-send-email-spearce@spearce.org","threadId":"19231","inReplyTo":null,"subject":"[JGIT PATCH 1/2] Add support for boolean config values \"yes\", \"no\"","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2009-05-07T15:05:13Z","receivedAt":"2009-05-07T15:05:13Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"In 8f8c6fafd92f (shipped in 1.6.3) Linus taught C Git how to read\nboolean configuration values set to \"yes\" as true and \"no\" as false.\nAdd support for these values, and some test cases.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n\n This little 2 patch series is to adjust some cases in JGit to\n match Git 1.6.3 semantics.\n\n .../org/spearce/jgit/lib/RepositoryConfigTest.java |   70 ++++++++++++++++++--\n .../src/org/spearce/jgit/lib/RepositoryConfig.java |   13 +++-\n 2 files changed, 74 insertions(+), 9 deletions(-)\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java\nindex 4b5314c..ed573e1 100644\n--- a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java\n@@ -57,9 +57,7 @@\n \t * @throws IOException\n \t */\n \tpublic void test001_ReadBareKey() throws IOException {\n-\t\tfinal File path = writeTrashFile(\"config_001\", \"[foo]\\nbar\\n\");\n-\t\tRepositoryConfig repositoryConfig = new RepositoryConfig(null, path);\n-\t\tSystem.out.println(repositoryConfig.getString(\"foo\", null, \"bar\"));\n+\t\tfinal RepositoryConfig repositoryConfig = read(\"[foo]\\nbar\\n\");\n \t\tassertEquals(true, repositoryConfig.getBoolean(\"foo\", null, \"bar\", false));\n \t\tassertEquals(\"\", repositoryConfig.getString(\"foo\", null, \"bar\"));\n \t}\n@@ -70,8 +68,7 @@ public void test001_ReadBareKey() throws IOException {\n \t * @throws IOException\n \t */\n \tpublic void test002_ReadWithSubsection() throws IOException {\n-\t\tfinal File path = writeTrashFile(\"config_002\", \"[foo \\\"zip\\\"]\\nbar\\n[foo \\\"zap\\\"]\\nbar=false\\nn=3\\n\");\n-\t\tRepositoryConfig repositoryConfig = new RepositoryConfig(null, path);\n+\t\tfinal RepositoryConfig repositoryConfig = read(\"[foo \\\"zip\\\"]\\nbar\\n[foo \\\"zap\\\"]\\nbar=false\\nn=3\\n\");\n \t\tassertEquals(true, repositoryConfig.getBoolean(\"foo\", \"zip\", \"bar\", false));\n \t\tassertEquals(\"\", repositoryConfig.getString(\"foo\",\"zip\", \"bar\"));\n \t\tassertEquals(false, repositoryConfig.getBoolean(\"foo\", \"zap\", \"bar\", true));\n@@ -113,8 +110,7 @@ assertTrue(Arrays.equals(values.toArray(), repositoryConfig\n \t}\n \n \tpublic void test006_readCaseInsensitive() throws IOException {\n-\t\tfinal File path = writeTrashFile(\"config_001\", \"[Foo]\\nBar\\n\");\n-\t\tRepositoryConfig repositoryConfig = new RepositoryConfig(null, path);\n+\t\tfinal RepositoryConfig repositoryConfig = read(\"[Foo]\\nBar\\n\");\n \t\tassertEquals(true, repositoryConfig.getBoolean(\"foo\", null, \"bar\", false));\n \t\tassertEquals(\"\", repositoryConfig.getString(\"foo\", null, \"bar\"));\n \t}\n@@ -182,4 +178,64 @@ public void test007_readUserInfos() throws IOException {\n \t\tassertEquals(\"local username\", authorName);\n \t\tassertEquals(\"author@localemail\", authorEmail);\n \t}\n+\n+\tpublic void testReadBoolean_TrueFalse1() throws IOException {\n+\t\tfinal RepositoryConfig c = read(\"[s]\\na = true\\nb = false\\n\");\n+\t\tassertEquals(\"true\", c.getString(\"s\", null, \"a\"));\n+\t\tassertEquals(\"false\", c.getString(\"s\", null, \"b\"));\n+\n+\t\tassertTrue(c.getBoolean(\"s\", \"a\", false));\n+\t\tassertFalse(c.getBoolean(\"s\", \"b\", true));\n+\t}\n+\n+\tpublic void testReadBoolean_TrueFalse2() throws IOException {\n+\t\tfinal RepositoryConfig c = read(\"[s]\\na = TrUe\\nb = fAlSe\\n\");\n+\t\tassertEquals(\"TrUe\", c.getString(\"s\", null, \"a\"));\n+\t\tassertEquals(\"fAlSe\", c.getString(\"s\", null, \"b\"));\n+\n+\t\tassertTrue(c.getBoolean(\"s\", \"a\", false));\n+\t\tassertFalse(c.getBoolean(\"s\", \"b\", true));\n+\t}\n+\n+\tpublic void testReadBoolean_YesNo1() throws IOException {\n+\t\tfinal RepositoryConfig c = read(\"[s]\\na = yes\\nb = no\\n\");\n+\t\tassertEquals(\"yes\", c.getString(\"s\", null, \"a\"));\n+\t\tassertEquals(\"no\", c.getString(\"s\", null, \"b\"));\n+\n+\t\tassertTrue(c.getBoolean(\"s\", \"a\", false));\n+\t\tassertFalse(c.getBoolean(\"s\", \"b\", true));\n+\t}\n+\n+\tpublic void testReadBoolean_YesNo2() throws IOException {\n+\t\tfinal RepositoryConfig c = read(\"[s]\\na = yEs\\nb = NO\\n\");\n+\t\tassertEquals(\"yEs\", c.getString(\"s\", null, \"a\"));\n+\t\tassertEquals(\"NO\", c.getString(\"s\", null, \"b\"));\n+\n+\t\tassertTrue(c.getBoolean(\"s\", \"a\", false));\n+\t\tassertFalse(c.getBoolean(\"s\", \"b\", true));\n+\t}\n+\n+\tpublic void testReadBoolean_OnOff1() throws IOException {\n+\t\tfinal RepositoryConfig c = read(\"[s]\\na = on\\nb = off\\n\");\n+\t\tassertEquals(\"on\", c.getString(\"s\", null, \"a\"));\n+\t\tassertEquals(\"off\", c.getString(\"s\", null, \"b\"));\n+\n+\t\tassertTrue(c.getBoolean(\"s\", \"a\", false));\n+\t\tassertFalse(c.getBoolean(\"s\", \"b\", true));\n+\t}\n+\n+\tpublic void testReadBoolean_OnOff2() throws IOException {\n+\t\tfinal RepositoryConfig c = read(\"[s]\\na = ON\\nb = OFF\\n\");\n+\t\tassertEquals(\"ON\", c.getString(\"s\", null, \"a\"));\n+\t\tassertEquals(\"OFF\", c.getString(\"s\", null, \"b\"));\n+\n+\t\tassertTrue(c.getBoolean(\"s\", \"a\", false));\n+\t\tassertFalse(c.getBoolean(\"s\", \"b\", true));\n+\t}\n+\n+\tprivate RepositoryConfig read(final String content) throws IOException {\n+\t\tfinal File p = writeTrashFile(getName() + \".config\", content);\n+\t\tfinal RepositoryConfig c = new RepositoryConfig(null, p);\n+\t\treturn c;\n+\t}\n }\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java\nindex cb287ee..e3a303f 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java\n@@ -254,10 +254,19 @@ public boolean getBoolean(final String section, String subsection,\n \t\t\treturn defaultValue;\n \n \t\tn = n.toLowerCase();\n-\t\tif (MAGIC_EMPTY_VALUE.equals(n) || \"yes\".equalsIgnoreCase(n) || \"true\".equalsIgnoreCase(n) || \"1\".equals(n)) {\n+\t\tif (MAGIC_EMPTY_VALUE.equals(n)\n+\t\t\t\t|| \"yes\".equalsIgnoreCase(n)\n+\t\t\t\t|| \"true\".equalsIgnoreCase(n)\n+\t\t\t\t|| \"1\".equals(n)\n+\t\t\t\t|| \"on\".equals(n)) {\n \t\t\treturn true;\n-\t\t} else if (\"no\".equalsIgnoreCase(n) || \"false\".equalsIgnoreCase(n) || \"0\".equalsIgnoreCase(n)) {\n+\n+\t\t} else if (\"no\".equalsIgnoreCase(n)\n+\t\t\t\t|| \"false\".equalsIgnoreCase(n)\n+\t\t\t\t|| \"0\".equalsIgnoreCase(n)\n+\t\t\t\t|| \"off\".equalsIgnoreCase(n)) {\n \t\t\treturn false;\n+\n \t\t} else {\n \t\t\tthrow new IllegalArgumentException(\"Invalid boolean value: \"\n \t\t\t\t\t+ section + \".\" + name + \"=\" + n);\n-- \n1.6.3.195.gad81\n"},{"id":"113226","messageId":"1241708714-20326-2-git-send-email-spearce@spearce.org","threadId":"19231","inReplyTo":"1241708714-20326-1-git-send-email-spearce@spearce.org","subject":"[JGIT PATCH 2/2] Make Repository.isValidRefName compatible with Git 1.6.3","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2009-05-07T15:05:14Z","receivedAt":"2009-05-07T15:05:14Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"In 3e262b95c509 I taught C Git to disallow refs whose names end in\n\".lock\".  This suffix is used by the atomic update mechanism as a\nsignal that the ref is being modified.  When reading a loose ref\ndirectory both JGit and C Git skip over any files whose names end\nwith this suffix, as the file is assumed to be one of these magic\nlocking files from another concurrent process.  Consequently, any\nref that ends with this name will become invisible once created.\n\nWe also add a suite of tests for the isValidRefName function, fix\nits formatting to better conform to current style conventions, and\ncorrect the result for \"master\"; this is not a valid ref name as it\nhas only 1 path component.  At least 2 path components is required.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../tst/org/spearce/jgit/lib/ValidRefNameTest.java |  168 ++++++++++++++++++++\n .../src/org/spearce/jgit/lib/Repository.java       |   28 ++--\n 2 files changed, 181 insertions(+), 15 deletions(-)\n create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/lib/ValidRefNameTest.java\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ValidRefNameTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ValidRefNameTest.java\nnew file mode 100644\nindex 0000000..5cca682\n--- /dev/null\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ValidRefNameTest.java\n@@ -0,0 +1,168 @@\n+/*\n+ * Copyright (C) 2009, Google Inc.\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.lib;\n+\n+import junit.framework.TestCase;\n+\n+public class ValidRefNameTest extends TestCase {\n+\tprivate static void assertValid(final boolean exp, final String name) {\n+\t\tassertEquals(\"\\\"\" + name + \"\\\"\", exp, Repository.isValidRefName(name));\n+\t}\n+\n+\tpublic void testEmptyString() {\n+\t\tassertValid(false, \"\");\n+\t\tassertValid(false, \"/\");\n+\t}\n+\n+\tpublic void testMustHaveTwoComponents() {\n+\t\tassertValid(false, \"master\");\n+\t\tassertValid(true, \"heads/master\");\n+\t}\n+\n+\tpublic void testValidHead() {\n+\t\tassertValid(true, \"refs/heads/master\");\n+\t\tassertValid(true, \"refs/heads/pu\");\n+\t\tassertValid(true, \"refs/heads/z\");\n+\t\tassertValid(true, \"refs/heads/FoO\");\n+\t}\n+\n+\tpublic void testValidTag() {\n+\t\tassertValid(true, \"refs/tags/v1.0\");\n+\t}\n+\n+\tpublic void testNoLockSuffix() {\n+\t\tassertValid(false, \"refs/heads/master.lock\");\n+\t}\n+\n+\tpublic void testNoDirectorySuffix() {\n+\t\tassertValid(false, \"refs/heads/master/\");\n+\t}\n+\n+\tpublic void testNoSpace() {\n+\t\tassertValid(false, \"refs/heads/i haz space\");\n+\t}\n+\n+\tpublic void testNoAsciiControlCharacters() {\n+\t\tfor (char c = '\\0'; c < ' '; c++)\n+\t\t\tassertValid(false, \"refs/heads/mast\" + c + \"er\");\n+\t}\n+\n+\tpublic void testNoBareDot() {\n+\t\tassertValid(false, \"refs/heads/.\");\n+\t\tassertValid(false, \"refs/heads/..\");\n+\t\tassertValid(false, \"refs/heads/./master\");\n+\t\tassertValid(false, \"refs/heads/../master\");\n+\t}\n+\n+\tpublic void testNoLeadingDot() {\n+\t\tassertValid(false, \".\");\n+\t\tassertValid(false, \"refs/heads/.bar\");\n+\t\tassertValid(false, \"refs/heads/..bar\");\n+\t}\n+\n+\tpublic void testContainsDot() {\n+\t\tassertValid(true, \"refs/heads/m.a.s.t.e.r\");\n+\t\tassertValid(false, \"refs/heads/master..pu\");\n+\t}\n+\n+\tpublic void testNoMagicRefCharacters() {\n+\t\tassertValid(false, \"refs/heads/master^\");\n+\t\tassertValid(false, \"refs/heads/^master\");\n+\t\tassertValid(false, \"^refs/heads/master\");\n+\n+\t\tassertValid(false, \"refs/heads/master~\");\n+\t\tassertValid(false, \"refs/heads/~master\");\n+\t\tassertValid(false, \"~refs/heads/master\");\n+\n+\t\tassertValid(false, \"refs/heads/master:\");\n+\t\tassertValid(false, \"refs/heads/:master\");\n+\t\tassertValid(false, \":refs/heads/master\");\n+\t}\n+\n+\tpublic void testShellGlob() {\n+\t\tassertValid(false, \"refs/heads/master?\");\n+\t\tassertValid(false, \"refs/heads/?master\");\n+\t\tassertValid(false, \"?refs/heads/master\");\n+\n+\t\tassertValid(false, \"refs/heads/master[\");\n+\t\tassertValid(false, \"refs/heads/[master\");\n+\t\tassertValid(false, \"[refs/heads/master\");\n+\n+\t\tassertValid(false, \"refs/heads/master*\");\n+\t\tassertValid(false, \"refs/heads/*master\");\n+\t\tassertValid(false, \"*refs/heads/master\");\n+\t}\n+\n+\tpublic void testValidSpecialCharacters() {\n+\t\tassertValid(true, \"refs/heads/!\");\n+\t\tassertValid(true, \"refs/heads/\\\"\");\n+\t\tassertValid(true, \"refs/heads/#\");\n+\t\tassertValid(true, \"refs/heads/$\");\n+\t\tassertValid(true, \"refs/heads/%\");\n+\t\tassertValid(true, \"refs/heads/&\");\n+\t\tassertValid(true, \"refs/heads/'\");\n+\t\tassertValid(true, \"refs/heads/(\");\n+\t\tassertValid(true, \"refs/heads/)\");\n+\t\tassertValid(true, \"refs/heads/+\");\n+\t\tassertValid(true, \"refs/heads/,\");\n+\t\tassertValid(true, \"refs/heads/-\");\n+\t\tassertValid(true, \"refs/heads/;\");\n+\t\tassertValid(true, \"refs/heads/<\");\n+\t\tassertValid(true, \"refs/heads/=\");\n+\t\tassertValid(true, \"refs/heads/>\");\n+\t\tassertValid(true, \"refs/heads/@\");\n+\t\tassertValid(true, \"refs/heads/]\");\n+\t\tassertValid(true, \"refs/heads/_\");\n+\t\tassertValid(true, \"refs/heads/`\");\n+\t\tassertValid(true, \"refs/heads/{\");\n+\t\tassertValid(true, \"refs/heads/|\");\n+\t\tassertValid(true, \"refs/heads/}\");\n+\n+\t\t// This is valid on UNIX, but not on Windows.\n+\t\t//\n+\t\tassertValid(true, \"refs/heads/\\\\\");\n+\t}\n+\n+\tpublic void testRefLogQueryIsValidRef() {\n+\t\t// Yes, these are actually ambiguous. You can create a ref\n+\t\t// that also looks like a reflog query.\n+\t\t//\n+\t\tassertValid(true, \"refs/heads/master@{1}\");\n+\t\tassertValid(true, \"refs/heads/master@{1.hour.ago}\");\n+\t}\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\nindex 5baa7a0..66dcd46 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\n@@ -939,36 +939,34 @@ public static boolean isValidRefName(final String refName) {\n \t\tfinal int len = refName.length();\n \t\tif (len == 0)\n \t\t\treturn false;\n+\t\tif (refName.endsWith(\".lock\"))\n+\t\t\treturn false;\n \n+\t\tint components = 1;\n \t\tchar p = '\\0';\n-\t\tfor (int i=0; i<len; ++i) {\n-\t\t\tchar c = refName.charAt(i);\n+\t\tfor (int i = 0; i < len; i++) {\n+\t\t\tfinal char c = refName.charAt(i);\n \t\t\tif (c <= ' ')\n \t\t\t\treturn false;\n-\t\t\tswitch(c) {\n+\t\t\tswitch (c) {\n \t\t\tcase '.':\n-\t\t\t\tif (i == 0)\n-\t\t\t\t\treturn false;\n-\t\t\t\tif (p == '/')\n-\t\t\t\t\treturn false;\n-\t\t\t\tif (p == '.')\n+\t\t\t\tswitch (p) {\n+\t\t\t\tcase '\\0': case '/': case '.':\n \t\t\t\t\treturn false;\n+\t\t\t\t}\n \t\t\t\tbreak;\n \t\t\tcase '/':\n-\t\t\t\tif (i == 0)\n-\t\t\t\t\treturn false;\n-\t\t\t\tif (i == len -1)\n+\t\t\t\tif (i == 0 || i == len - 1)\n \t\t\t\t\treturn false;\n+\t\t\t\tcomponents++;\n \t\t\t\tbreak;\n \t\t\tcase '~': case '^': case ':':\n-\t\t\tcase '?': case '[':\n-\t\t\t\treturn false;\n-\t\t\tcase '*':\n+\t\t\tcase '?': case '[': case '*':\n \t\t\t\treturn false;\n \t\t\t}\n \t\t\tp = c;\n \t\t}\n-\t\treturn true;\n+\t\treturn components > 1;\n \t}\n \n \t/**\n-- \n1.6.3.195.gad81\n"},{"id":"113240","messageId":"eOxTQ_L3wmawK8rFbXMLnksiI7lh8eiyptpquFGaI28e3RO7dN9GMw@cipher.nrlssc.navy.mil","threadId":"19231","inReplyTo":"1241708714-20326-1-git-send-email-spearce@spearce.org","subject":"Re: [JGIT PATCH 1/2] Add support for boolean config values \"yes\", \"no\"","fromName":"Brandon Casey","fromEmail":"casey@nrlssc.navy.mil","sentAt":"2009-05-07T17:56:15Z","receivedAt":"2009-05-07T17:56:15Z","isPatch":true,"sender":{"key":"drafnel@gmail.com","avatar":"https://avatars.githubusercontent.com/u/921167?v=4"},"body":"Shawn O. Pearce wrote:\n> In 8f8c6fafd92f (shipped in 1.6.3) Linus taught C Git how to read\n> boolean configuration values set to \"yes\" as true and \"no\" as false.\n> Add support for these values, and some test cases.\n\nLinus added support for \"on\" and \"off\" in that commit as it appears\nyour commit is also doing. :)\n\nI was about to point out that you are not ignoring case for \"on\", but\nusing equalsIgnoreCase() appears to be unnecessary since above that\nyou are already doing n = n.toLowerCase().\n\n-brandon\n\n\n> diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java\n> index cb287ee..e3a303f 100644\n> --- a/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java\n> +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java\n> @@ -254,10 +254,19 @@ public boolean getBoolean(final String section, String subsection,\n>  \t\t\treturn defaultValue;\n>  \n>  \t\tn = n.toLowerCase();\n> -\t\tif (MAGIC_EMPTY_VALUE.equals(n) || \"yes\".equalsIgnoreCase(n) || \"true\".equalsIgnoreCase(n) || \"1\".equals(n)) {\n> +\t\tif (MAGIC_EMPTY_VALUE.equals(n)\n> +\t\t\t\t|| \"yes\".equalsIgnoreCase(n)\n> +\t\t\t\t|| \"true\".equalsIgnoreCase(n)\n> +\t\t\t\t|| \"1\".equals(n)\n> +\t\t\t\t|| \"on\".equals(n)) {\n>  \t\t\treturn true;\n> -\t\t} else if (\"no\".equalsIgnoreCase(n) || \"false\".equalsIgnoreCase(n) || \"0\".equalsIgnoreCase(n)) {\n> +\n> +\t\t} else if (\"no\".equalsIgnoreCase(n)\n> +\t\t\t\t|| \"false\".equalsIgnoreCase(n)\n> +\t\t\t\t|| \"0\".equalsIgnoreCase(n)\n> +\t\t\t\t|| \"off\".equalsIgnoreCase(n)) {\n>  \t\t\treturn false;\n> +\n>  \t\t} else {\n>  \t\t\tthrow new IllegalArgumentException(\"Invalid boolean value: \"\n>  \t\t\t\t\t+ section + \".\" + name + \"=\" + n);\n"},{"id":"113241","messageId":"20090507180147.GT30527@spearce.org","threadId":"19231","inReplyTo":"eOxTQ_L3wmawK8rFbXMLnksiI7lh8eiyptpquFGaI28e3RO7dN9GMw@cipher.nrlssc.navy.mil","subject":"[JGIT PATCH v2 1/2] Add support for boolean config values \"on\", \"off\"","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2009-05-07T18:01:47Z","receivedAt":"2009-05-07T18:01:47Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"In 8f8c6fafd92f (shipped in 1.6.3) Linus taught C Git how to read\nboolean configuration values set to \"on\" as true and \"off\" as false.\nAdd support for these values, and some test cases.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n  Brandon Casey <casey@nrlssc.navy.mil> wrote:\n  > Shawn O. Pearce wrote:\n  > > In 8f8c6fafd92f (shipped in 1.6.3) Linus taught C Git how to read\n  > > boolean configuration values set to \"yes\" as true and \"no\" as false.\n  > > Add support for these values, and some test cases.\n  > \n  > Linus added support for \"on\" and \"off\" in that commit as it appears\n  > your commit is also doing. :)\n\n  Whoops, good catch, thanks.\n\n  > I was about to point out that you are not ignoring case for \"on\", but\n  > using equalsIgnoreCase() appears to be unnecessary since above that\n  > you are already doing n = n.toLowerCase().\n\n  I dropped the toLowerCase and used equalsIgnoreCase instead.\n  There is no reason to be allocating a copy of the string when\n  equalsIgnorCase is sufficient.\n  \n .../org/spearce/jgit/lib/RepositoryConfigTest.java |   70 ++++++++++++++++++--\n .../src/org/spearce/jgit/lib/RepositoryConfig.java |   14 +++-\n 2 files changed, 74 insertions(+), 10 deletions(-)\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java\nindex 4b5314c..ed573e1 100644\n--- a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java\n@@ -57,9 +57,7 @@\n \t * @throws IOException\n \t */\n \tpublic void test001_ReadBareKey() throws IOException {\n-\t\tfinal File path = writeTrashFile(\"config_001\", \"[foo]\\nbar\\n\");\n-\t\tRepositoryConfig repositoryConfig = new RepositoryConfig(null, path);\n-\t\tSystem.out.println(repositoryConfig.getString(\"foo\", null, \"bar\"));\n+\t\tfinal RepositoryConfig repositoryConfig = read(\"[foo]\\nbar\\n\");\n \t\tassertEquals(true, repositoryConfig.getBoolean(\"foo\", null, \"bar\", false));\n \t\tassertEquals(\"\", repositoryConfig.getString(\"foo\", null, \"bar\"));\n \t}\n@@ -70,8 +68,7 @@ public void test001_ReadBareKey() throws IOException {\n \t * @throws IOException\n \t */\n \tpublic void test002_ReadWithSubsection() throws IOException {\n-\t\tfinal File path = writeTrashFile(\"config_002\", \"[foo \\\"zip\\\"]\\nbar\\n[foo \\\"zap\\\"]\\nbar=false\\nn=3\\n\");\n-\t\tRepositoryConfig repositoryConfig = new RepositoryConfig(null, path);\n+\t\tfinal RepositoryConfig repositoryConfig = read(\"[foo \\\"zip\\\"]\\nbar\\n[foo \\\"zap\\\"]\\nbar=false\\nn=3\\n\");\n \t\tassertEquals(true, repositoryConfig.getBoolean(\"foo\", \"zip\", \"bar\", false));\n \t\tassertEquals(\"\", repositoryConfig.getString(\"foo\",\"zip\", \"bar\"));\n \t\tassertEquals(false, repositoryConfig.getBoolean(\"foo\", \"zap\", \"bar\", true));\n@@ -113,8 +110,7 @@ assertTrue(Arrays.equals(values.toArray(), repositoryConfig\n \t}\n \n \tpublic void test006_readCaseInsensitive() throws IOException {\n-\t\tfinal File path = writeTrashFile(\"config_001\", \"[Foo]\\nBar\\n\");\n-\t\tRepositoryConfig repositoryConfig = new RepositoryConfig(null, path);\n+\t\tfinal RepositoryConfig repositoryConfig = read(\"[Foo]\\nBar\\n\");\n \t\tassertEquals(true, repositoryConfig.getBoolean(\"foo\", null, \"bar\", false));\n \t\tassertEquals(\"\", repositoryConfig.getString(\"foo\", null, \"bar\"));\n \t}\n@@ -182,4 +178,64 @@ public void test007_readUserInfos() throws IOException {\n \t\tassertEquals(\"local username\", authorName);\n \t\tassertEquals(\"author@localemail\", authorEmail);\n \t}\n+\n+\tpublic void testReadBoolean_TrueFalse1() throws IOException {\n+\t\tfinal RepositoryConfig c = read(\"[s]\\na = true\\nb = false\\n\");\n+\t\tassertEquals(\"true\", c.getString(\"s\", null, \"a\"));\n+\t\tassertEquals(\"false\", c.getString(\"s\", null, \"b\"));\n+\n+\t\tassertTrue(c.getBoolean(\"s\", \"a\", false));\n+\t\tassertFalse(c.getBoolean(\"s\", \"b\", true));\n+\t}\n+\n+\tpublic void testReadBoolean_TrueFalse2() throws IOException {\n+\t\tfinal RepositoryConfig c = read(\"[s]\\na = TrUe\\nb = fAlSe\\n\");\n+\t\tassertEquals(\"TrUe\", c.getString(\"s\", null, \"a\"));\n+\t\tassertEquals(\"fAlSe\", c.getString(\"s\", null, \"b\"));\n+\n+\t\tassertTrue(c.getBoolean(\"s\", \"a\", false));\n+\t\tassertFalse(c.getBoolean(\"s\", \"b\", true));\n+\t}\n+\n+\tpublic void testReadBoolean_YesNo1() throws IOException {\n+\t\tfinal RepositoryConfig c = read(\"[s]\\na = yes\\nb = no\\n\");\n+\t\tassertEquals(\"yes\", c.getString(\"s\", null, \"a\"));\n+\t\tassertEquals(\"no\", c.getString(\"s\", null, \"b\"));\n+\n+\t\tassertTrue(c.getBoolean(\"s\", \"a\", false));\n+\t\tassertFalse(c.getBoolean(\"s\", \"b\", true));\n+\t}\n+\n+\tpublic void testReadBoolean_YesNo2() throws IOException {\n+\t\tfinal RepositoryConfig c = read(\"[s]\\na = yEs\\nb = NO\\n\");\n+\t\tassertEquals(\"yEs\", c.getString(\"s\", null, \"a\"));\n+\t\tassertEquals(\"NO\", c.getString(\"s\", null, \"b\"));\n+\n+\t\tassertTrue(c.getBoolean(\"s\", \"a\", false));\n+\t\tassertFalse(c.getBoolean(\"s\", \"b\", true));\n+\t}\n+\n+\tpublic void testReadBoolean_OnOff1() throws IOException {\n+\t\tfinal RepositoryConfig c = read(\"[s]\\na = on\\nb = off\\n\");\n+\t\tassertEquals(\"on\", c.getString(\"s\", null, \"a\"));\n+\t\tassertEquals(\"off\", c.getString(\"s\", null, \"b\"));\n+\n+\t\tassertTrue(c.getBoolean(\"s\", \"a\", false));\n+\t\tassertFalse(c.getBoolean(\"s\", \"b\", true));\n+\t}\n+\n+\tpublic void testReadBoolean_OnOff2() throws IOException {\n+\t\tfinal RepositoryConfig c = read(\"[s]\\na = ON\\nb = OFF\\n\");\n+\t\tassertEquals(\"ON\", c.getString(\"s\", null, \"a\"));\n+\t\tassertEquals(\"OFF\", c.getString(\"s\", null, \"b\"));\n+\n+\t\tassertTrue(c.getBoolean(\"s\", \"a\", false));\n+\t\tassertFalse(c.getBoolean(\"s\", \"b\", true));\n+\t}\n+\n+\tprivate RepositoryConfig read(final String content) throws IOException {\n+\t\tfinal File p = writeTrashFile(getName() + \".config\", content);\n+\t\tfinal RepositoryConfig c = new RepositoryConfig(null, p);\n+\t\treturn c;\n+\t}\n }\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java\nindex cb287ee..b816604 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java\n@@ -253,11 +253,19 @@ public boolean getBoolean(final String section, String subsection,\n \t\tif (n == null)\n \t\t\treturn defaultValue;\n \n-\t\tn = n.toLowerCase();\n-\t\tif (MAGIC_EMPTY_VALUE.equals(n) || \"yes\".equalsIgnoreCase(n) || \"true\".equalsIgnoreCase(n) || \"1\".equals(n)) {\n+\t\tif (MAGIC_EMPTY_VALUE.equals(n)\n+\t\t\t\t|| \"yes\".equalsIgnoreCase(n)\n+\t\t\t\t|| \"true\".equalsIgnoreCase(n)\n+\t\t\t\t|| \"1\".equals(n)\n+\t\t\t\t|| \"on\".equalsIgnoreCase(n)) {\n \t\t\treturn true;\n-\t\t} else if (\"no\".equalsIgnoreCase(n) || \"false\".equalsIgnoreCase(n) || \"0\".equalsIgnoreCase(n)) {\n+\n+\t\t} else if (\"no\".equalsIgnoreCase(n)\n+\t\t\t\t|| \"false\".equalsIgnoreCase(n)\n+\t\t\t\t|| \"0\".equals(n)\n+\t\t\t\t|| \"off\".equalsIgnoreCase(n)) {\n \t\t\treturn false;\n+\n \t\t} else {\n \t\t\tthrow new IllegalArgumentException(\"Invalid boolean value: \"\n \t\t\t\t\t+ section + \".\" + name + \"=\" + n);\n-- \n1.6.3.195.gad81\n"},{"id":"113276","messageId":"200905080102.44053.robin.rosenberg@dewire.com","threadId":"19231","inReplyTo":"1241708714-20326-2-git-send-email-spearce@spearce.org","subject":"Re: [JGIT PATCH 2/2] Make Repository.isValidRefName compatible with Git 1.6.3","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2009-05-07T23:02:43Z","receivedAt":"2009-05-07T23:02:43Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"NAK, ammended patch follows.\n\nDisallows @{, names that end with '.', '\\' (that's the \"almost\" part) plus explicitly\nallows unicode names.\n\n-- robin\n\n>From 0854d96e2774bd084cc673ab16cf61c489f0562e Mon Sep 17 00:00:00 2001\nFrom: Shawn O. Pearce <spearce@spearce.org>\nDate: Thu, 7 May 2009 08:05:14 -0700\nSubject: [EGIT PATCH] Make Repository.isValidRefName almost compatible with Git 1.6.3\n\nIn 3e262b95c509 I taught C Git to disallow refs whose names end in\n\".lock\".  This suffix is used by the atomic update mechanism as a\nsignal that the ref is being modified.  When reading a loose ref\ndirectory both JGit and C Git skip over any files whose names end\nwith this suffix, as the file is assumed to be one of these magic\nlocking files from another concurrent process.  Consequently, any\nref that ends with this name will become invisible once created.\n\nIn cbdffe4093be Junio disallows names that looks like reflog queries\nas well as names that ends with periods.\n\nWe also add a suite of tests for the isValidRefName function, fix\nits formatting to better conform to current style conventions, and\ncorrect the result for \"master\"; this is not a valid ref name as it\nhas only 1 path component.  At least 2 path components is required.\n\nIn addition to 1.6.3 we disallow names with a '\\' (backslash) since\nthat is a directory separator in Windows. Allowing JGit users to\ncreate such names is just asking for trouble. This does not necessarily\nprevent JGit from working with such refs in other situations.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../tst/org/spearce/jgit/lib/ValidRefNameTest.java |  171 ++++++++++++++++++++\n .../src/org/spearce/jgit/lib/Repository.java       |   33 +++--\n 2 files changed, 191 insertions(+), 13 deletions(-)\n create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/lib/ValidRefNameTest.java\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ValidRefNameTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ValidRefNameTest.java\nnew file mode 100644\nindex 0000000..cb6b9a7\n--- /dev/null\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ValidRefNameTest.java\n@@ -0,0 +1,171 @@\n+/*\n+ * Copyright (C) 2009, Google Inc.\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.lib;\n+\n+import junit.framework.TestCase;\n+\n+public class ValidRefNameTest extends TestCase {\n+\tprivate static void assertValid(final boolean exp, final String name) {\n+\t\tassertEquals(\"\\\"\" + name + \"\\\"\", exp, Repository.isValidRefName(name));\n+\t}\n+\n+\tpublic void testEmptyString() {\n+\t\tassertValid(false, \"\");\n+\t\tassertValid(false, \"/\");\n+\t}\n+\n+\tpublic void testMustHaveTwoComponents() {\n+\t\tassertValid(false, \"master\");\n+\t\tassertValid(true, \"heads/master\");\n+\t}\n+\n+\tpublic void testValidHead() {\n+\t\tassertValid(true, \"refs/heads/master\");\n+\t\tassertValid(true, \"refs/heads/pu\");\n+\t\tassertValid(true, \"refs/heads/z\");\n+\t\tassertValid(true, \"refs/heads/FoO\");\n+\t}\n+\n+\tpublic void testValidTag() {\n+\t\tassertValid(true, \"refs/tags/v1.0\");\n+\t}\n+\n+\tpublic void testNoLockSuffix() {\n+\t\tassertValid(false, \"refs/heads/master.lock\");\n+\t}\n+\n+\tpublic void testNoDirectorySuffix() {\n+\t\tassertValid(false, \"refs/heads/master/\");\n+\t}\n+\n+\tpublic void testNoSpace() {\n+\t\tassertValid(false, \"refs/heads/i haz space\");\n+\t}\n+\n+\tpublic void testNoAsciiControlCharacters() {\n+\t\tfor (char c = '\\0'; c < ' '; c++)\n+\t\t\tassertValid(false, \"refs/heads/mast\" + c + \"er\");\n+\t}\n+\n+\tpublic void testNoBareDot() {\n+\t\tassertValid(false, \"refs/heads/.\");\n+\t\tassertValid(false, \"refs/heads/..\");\n+\t\tassertValid(false, \"refs/heads/./master\");\n+\t\tassertValid(false, \"refs/heads/../master\");\n+\t}\n+\n+\tpublic void testNoLeadingOrTrailingDot() {\n+\t\tassertValid(false, \".\");\n+\t\tassertValid(false, \"refs/heads/.bar\");\n+\t\tassertValid(false, \"refs/heads/..bar\");\n+\t\tassertValid(false, \"refs/heads/bar.\");\n+\t}\n+\n+\tpublic void testContainsDot() {\n+\t\tassertValid(true, \"refs/heads/m.a.s.t.e.r\");\n+\t\tassertValid(false, \"refs/heads/master..pu\");\n+\t}\n+\n+\tpublic void testNoMagicRefCharacters() {\n+\t\tassertValid(false, \"refs/heads/master^\");\n+\t\tassertValid(false, \"refs/heads/^master\");\n+\t\tassertValid(false, \"^refs/heads/master\");\n+\n+\t\tassertValid(false, \"refs/heads/master~\");\n+\t\tassertValid(false, \"refs/heads/~master\");\n+\t\tassertValid(false, \"~refs/heads/master\");\n+\n+\t\tassertValid(false, \"refs/heads/master:\");\n+\t\tassertValid(false, \"refs/heads/:master\");\n+\t\tassertValid(false, \":refs/heads/master\");\n+\t}\n+\n+\tpublic void testShellGlob() {\n+\t\tassertValid(false, \"refs/heads/master?\");\n+\t\tassertValid(false, \"refs/heads/?master\");\n+\t\tassertValid(false, \"?refs/heads/master\");\n+\n+\t\tassertValid(false, \"refs/heads/master[\");\n+\t\tassertValid(false, \"refs/heads/[master\");\n+\t\tassertValid(false, \"[refs/heads/master\");\n+\n+\t\tassertValid(false, \"refs/heads/master*\");\n+\t\tassertValid(false, \"refs/heads/*master\");\n+\t\tassertValid(false, \"*refs/heads/master\");\n+\t}\n+\n+\tpublic void testValidSpecialCharacters() {\n+\t\tassertValid(true, \"refs/heads/!\");\n+\t\tassertValid(true, \"refs/heads/\\\"\");\n+\t\tassertValid(true, \"refs/heads/#\");\n+\t\tassertValid(true, \"refs/heads/$\");\n+\t\tassertValid(true, \"refs/heads/%\");\n+\t\tassertValid(true, \"refs/heads/&\");\n+\t\tassertValid(true, \"refs/heads/'\");\n+\t\tassertValid(true, \"refs/heads/(\");\n+\t\tassertValid(true, \"refs/heads/)\");\n+\t\tassertValid(true, \"refs/heads/+\");\n+\t\tassertValid(true, \"refs/heads/,\");\n+\t\tassertValid(true, \"refs/heads/-\");\n+\t\tassertValid(true, \"refs/heads/;\");\n+\t\tassertValid(true, \"refs/heads/<\");\n+\t\tassertValid(true, \"refs/heads/=\");\n+\t\tassertValid(true, \"refs/heads/>\");\n+\t\tassertValid(true, \"refs/heads/@\");\n+\t\tassertValid(true, \"refs/heads/]\");\n+\t\tassertValid(true, \"refs/heads/_\");\n+\t\tassertValid(true, \"refs/heads/`\");\n+\t\tassertValid(true, \"refs/heads/{\");\n+\t\tassertValid(true, \"refs/heads/|\");\n+\t\tassertValid(true, \"refs/heads/}\");\n+\n+\t\t// This is valid on UNIX, but not on Windows\n+\t\t// hence we make in invalid due to non-portability\n+\t\t//\n+\t\tassertValid(false, \"refs/heads/\\\\\");\n+\t}\n+\n+\tpublic void testUnicodeNames() {\n+\t\tassertValid(true, \"refs/heads/\\u00e5ngstr\\u00f6m\");\n+\t}\n+\n+\tpublic void testRefLogQueryIsValidRef() {\n+\t\tassertValid(false, \"refs/heads/master@{1}\");\n+\t\tassertValid(false, \"refs/heads/master@{1.hour.ago}\");\n+\t}\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\nindex 5baa7a0..a47207d 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\n@@ -931,6 +931,8 @@ public RepositoryState getRepositoryState() {\n \t * a special meaning in a Git object reference expression. Some other\n \t * dangerous characters are also excluded.\n \t *\n+\t * For portability reasons '\\' is excluded\n+\t *\n \t * @param refName\n \t *\n \t * @return true if refName is a valid ref name\n@@ -939,36 +941,41 @@ public static boolean isValidRefName(final String refName) {\n \t\tfinal int len = refName.length();\n \t\tif (len == 0)\n \t\t\treturn false;\n+\t\tif (refName.endsWith(\".lock\"))\n+\t\t\treturn false;\n \n+\t\tint components = 1;\n \t\tchar p = '\\0';\n-\t\tfor (int i=0; i<len; ++i) {\n-\t\t\tchar c = refName.charAt(i);\n+\t\tfor (int i = 0; i < len; i++) {\n+\t\t\tfinal char c = refName.charAt(i);\n \t\t\tif (c <= ' ')\n \t\t\t\treturn false;\n-\t\t\tswitch(c) {\n+\t\t\tswitch (c) {\n \t\t\tcase '.':\n-\t\t\t\tif (i == 0)\n-\t\t\t\t\treturn false;\n-\t\t\t\tif (p == '/')\n+\t\t\t\tswitch (p) {\n+\t\t\t\tcase '\\0': case '/': case '.':\n \t\t\t\t\treturn false;\n-\t\t\t\tif (p == '.')\n+\t\t\t\t}\n+\t\t\t\tif (i == len -1)\n \t\t\t\t\treturn false;\n \t\t\t\tbreak;\n \t\t\tcase '/':\n-\t\t\t\tif (i == 0)\n+\t\t\t\tif (i == 0 || i == len - 1)\n \t\t\t\t\treturn false;\n-\t\t\t\tif (i == len -1)\n+\t\t\t\tcomponents++;\n+\t\t\t\tbreak;\n+\t\t\tcase '@':\n+\t\t\t\tif (p == '{')\n \t\t\t\t\treturn false;\n \t\t\t\tbreak;\n \t\t\tcase '~': case '^': case ':':\n-\t\t\tcase '?': case '[':\n-\t\t\t\treturn false;\n-\t\t\tcase '*':\n+\t\t\tcase '?': case '[': case '*':\n+\t\t\tcase '\\\\':\n \t\t\t\treturn false;\n \t\t\t}\n \t\t\tp = c;\n \t\t}\n-\t\treturn true;\n+\t\treturn components > 1;\n \t}\n \n \t/**\n-- \n1.6.3\n"},{"id":"113282","messageId":"alpine.LFD.2.01.0905071620240.4983@localhost.localdomain","threadId":"19231","inReplyTo":"200905080102.44053.robin.rosenberg@dewire.com","subject":"Re: [JGIT PATCH 2/2] Make Repository.isValidRefName compatible with Git 1.6.3","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2009-05-07T23:29:21Z","receivedAt":"2009-05-07T23:29:21Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 8 May 2009, Robin Rosenberg wrote:\n> \n> In 3e262b95c509 I taught C Git to disallow refs whose names end in\n> \".lock\".\n\nBtw, I think we should revert that, and instead change our naming for \nlock-files.\n\nIt's a silly limitation, and for a stupid reason, I think. I can well \nimagine people using a branch naming policy of using '.' instead of \nspaces, and then It makes perfect sense to call a branch \"fix.vm.lock\" \nwhen you have a VM locking issue you want to fix.\n\nSo I think we should remove that stupid \"*.lock\" rule from the C version \n(and then obviously from the JGIT one too).\n\nNow, that leaves what we _should_ call the lock-files, and the only sane \nthing to do is to pick a sequence that is already invalid for other \nreasons. We could make the lockfile end in \"..lock\", for example (\"..\" is \nnot legal in names due to the confusion with the \"a..b\" range notation), \nor just end or begin with a \".\" (same issue, except \"...\" now).\n\nOr just make it end in '~' which is also invalid for similar reasons.\n\n\t\tLinus\n"},{"id":"113290","messageId":"7vprekbfik.fsf@alter.siamese.dyndns.org","threadId":"19231","inReplyTo":"alpine.LFD.2.01.0905071620240.4983@localhost.localdomain","subject":"Re: [JGIT PATCH 2/2] Make Repository.isValidRefName compatible with Git 1.6.3","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-05-08T00:32:51Z","receivedAt":"2009-05-08T00:32:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> On Fri, 8 May 2009, Robin Rosenberg wrote:\n>> \n>> In 3e262b95c509 I taught C Git to disallow refs whose names end in\n>> \".lock\".\n>\n> Btw, I think we should revert that, and instead change our naming for \n> lock-files.\n>\n> It's a silly limitation, and for a stupid reason, I think. I can well \n> imagine people using a branch naming policy of using '.' instead of \n> spaces, and then It makes perfect sense to call a branch \"fix.vm.lock\" \n> when you have a VM locking issue you want to fix.\n>\n> So I think we should remove that stupid \"*.lock\" rule from the C version \n> (and then obviously from the JGIT one too).\n>\n> Now, that leaves what we _should_ call the lock-files, and the only sane \n> thing to do is to pick a sequence that is already invalid for other \n> reasons. We could make the lockfile end in \"..lock\", for example (\"..\" is \n> not legal in names due to the confusion with the \"a..b\" range notation), \n> or just end or begin with a \".\" (same issue, except \"...\" now).\n>\n> Or just make it end in '~' which is also invalid for similar reasons.\n\nI was tempted to go for the tilde, but then realized that\n\n\t.git/config~\n\nis a common thing to have in a repository owned by an Emacs user, and we\ndo create with O_CREAT, so it is not such a good idea.\n\n'..lck' may be a good name to use here.\n"},{"id":"113291","messageId":"20090508004741.GU30527@spearce.org","threadId":"19231","inReplyTo":"7vprekbfik.fsf@alter.siamese.dyndns.org","subject":"Re: [JGIT PATCH 2/2] Make Repository.isValidRefName compatible with Git 1.6.3","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2009-05-08T00:47:41Z","receivedAt":"2009-05-08T00:47:41Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Junio C Hamano <gitster@pobox.com> wrote:\n> Linus Torvalds <torvalds@linux-foundation.org> writes:\n> >> \n> >> In 3e262b95c509 I taught C Git to disallow refs whose names end in\n> >> \".lock\".\n> >\n> > Btw, I think we should revert that, and instead change our naming for \n> > lock-files.\n> \n> '..lck' may be a good name to use here.\n\nI agree.  So much so that I wrote a patch for you.\n\n--8<--\nChange .lock suffix to ..lck\n\nIn 3e262b95c509 I taught Git to deny creation of refs whose name\nends in \".lock\", as the loose ref scanner skips over these under\nthe assumption that they are refs being modified by a concurrent\nprocess operating on the same repository.\n\nLinus pointed out that the name \"fix.vm.lock\" is an otherwise\nperfectly valid branch name, except the \".lock\" suffix conflicts\nwith the internal implementation detail of how Git manages doing\nan atomic update.\n\nInstead, change the name to \"..lck\", as suggested by Junio.\n\nThis uses the same storage space in memory as \".lock\", so we can do\na fairly dumb search-replace to make the change, but the \"..\" prefix\nhas been forbidden in a ref name for ages, to prevent \"a..b\" from\nbeing ambiguous as a single ref name, or as the pair \"^a b\".\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n Documentation/git-check-ref-format.txt   |    2 --\n Documentation/technical/api-lockfile.txt |    4 ++--\n builtin-reflog.c                         |    2 +-\n config.c                                 |    2 +-\n lockfile.c                               |   10 +++++-----\n refs.c                                   |   11 ++++-------\n t/t3505-cherry-pick-empty.sh             |    2 +-\n t/t3600-rm.sh                            |    4 ++--\n t/t4123-apply-shrink.sh                  |    2 +-\n t/t7001-mv.sh                            |    4 ++--\n t/t7502-commit.sh                        |    2 +-\n t/test-lib.sh                            |    6 +++---\n 12 files changed, 23 insertions(+), 28 deletions(-)\n\ndiff --git a/Documentation/git-check-ref-format.txt b/Documentation/git-check-ref-format.txt\nindex c1ce268..7c0f0ea 100644\n--- a/Documentation/git-check-ref-format.txt\n+++ b/Documentation/git-check-ref-format.txt\n@@ -34,8 +34,6 @@ imposes the following rules on how references are named:\n \n . They cannot end with a slash `/` nor a dot `.`.\n \n-. They cannot end with the sequence `.lock`.\n-\n . They cannot contain a sequence `@{`.\n \n These rules make it easy for shell script based tools to parse\ndiff --git a/Documentation/technical/api-lockfile.txt b/Documentation/technical/api-lockfile.txt\nindex dd89404..982984f 100644\n--- a/Documentation/technical/api-lockfile.txt\n+++ b/Documentation/technical/api-lockfile.txt\n@@ -4,9 +4,9 @@ lockfile API\n The lockfile API serves two purposes:\n \n * Mutual exclusion.  When we write out a new index file, first\n-  we create a new file `$GIT_DIR/index.lock`, write the new\n+  we create a new file `$GIT_DIR/index..lck`, write the new\n   contents into it, and rename it to the final destination\n-  `$GIT_DIR/index`.  We try to create the `$GIT_DIR/index.lock`\n+  `$GIT_DIR/index`.  We try to create the `$GIT_DIR/index..lck`\n   file with O_EXCL so that we can notice and fail when somebody\n   else is already trying to update the index file.\n \ndiff --git a/builtin-reflog.c b/builtin-reflog.c\nindex ddfdf5a..19baf07 100644\n--- a/builtin-reflog.c\n+++ b/builtin-reflog.c\n@@ -341,7 +341,7 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,\n \tif (!file_exists(log_file))\n \t\tgoto finish;\n \tif (!cmd->dry_run) {\n-\t\tnewlog_path = git_pathdup(\"logs/%s.lock\", ref);\n+\t\tnewlog_path = git_pathdup(\"logs/%s..lck\", ref);\n \t\tcb.newlog = fopen(newlog_path, \"w\");\n \t}\n \ndiff --git a/config.c b/config.c\nindex 1682273..50ecc1e 100644\n--- a/config.c\n+++ b/config.c\n@@ -925,7 +925,7 @@ int git_config_set(const char *key, const char *value)\n  *\n  * This function does this:\n  *\n- * - it locks the config file by creating \".git/config.lock\"\n+ * - it locks the config file by creating \".git/config..lck\"\n  *\n  * - it then parses the config using store_aux() as validator to find\n  *   the position on the key/value pair to replace. If it is to be unset,\ndiff --git a/lockfile.c b/lockfile.c\nindex 828d19f..61ff5cb 100644\n--- a/lockfile.c\n+++ b/lockfile.c\n@@ -129,11 +129,11 @@ static int lock_file(struct lock_file *lk, const char *path, int flags)\n \tstrcpy(lk->filename, path);\n \t/*\n \t * subtract 5 from size to make sure there's room for adding\n-\t * \".lock\" for the lock file name\n+\t * \"..lck\" for the lock file name\n \t */\n \tif (!(flags & LOCK_NODEREF))\n \t\tresolve_symlink(lk->filename, sizeof(lk->filename)-5);\n-\tstrcat(lk->filename, \".lock\");\n+\tstrcat(lk->filename, \"..lck\");\n \tlk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);\n \tif (0 <= lk->fd) {\n \t\tif (!lock_file_list) {\n@@ -159,13 +159,13 @@ static int lock_file(struct lock_file *lk, const char *path, int flags)\n NORETURN void unable_to_lock_index_die(const char *path, int err)\n {\n \tif (err == EEXIST) {\n-\t\tdie(\"Unable to create '%s.lock': %s.\\n\\n\"\n+\t\tdie(\"Unable to create '%s..lck': %s.\\n\\n\"\n \t\t    \"If no other git process is currently running, this probably means a\\n\"\n \t\t    \"git process crashed in this repository earlier. Make sure no other git\\n\"\n \t\t    \"process is running and remove the file manually to continue.\",\n \t\t    path, strerror(err));\n \t} else {\n-\t\tdie(\"Unable to create '%s.lock': %s\", path, strerror(err));\n+\t\tdie(\"Unable to create '%s..lck': %s\", path, strerror(err));\n \t}\n }\n \n@@ -219,7 +219,7 @@ int commit_lock_file(struct lock_file *lk)\n \tif (lk->fd >= 0 && close_lock_file(lk))\n \t\treturn -1;\n \tstrcpy(result_file, lk->filename);\n-\ti = strlen(result_file) - 5; /* .lock */\n+\ti = strlen(result_file) - 5; /* ..lck */\n \tresult_file[i] = 0;\n \tif (rename(lk->filename, result_file))\n \t\treturn -1;\ndiff --git a/refs.c b/refs.c\nindex e65a3b4..b4ca305 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -266,7 +266,7 @@ static struct ref_list *get_ref_dir(const char *base, struct ref_list *list)\n \t\t\tnamelen = strlen(de->d_name);\n \t\t\tif (namelen > 255)\n \t\t\t\tcontinue;\n-\t\t\tif (has_extension(de->d_name, \".lock\"))\n+\t\t\tif (has_extension(de->d_name, \"..lck\"))\n \t\t\t\tcontinue;\n \t\t\tmemcpy(ref + baselen, de->d_name, namelen+1);\n \t\t\tif (stat(git_path(\"%s\", ref), &st) < 0)\n@@ -681,7 +681,6 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)\n  * - it has double dots \"..\", or\n  * - it has ASCII control character, \"~\", \"^\", \":\" or SP, anywhere, or\n  * - it ends with a \"/\".\n- * - it ends with \".lock\"\n  */\n \n static inline int bad_ref_char(int ch)\n@@ -743,8 +742,6 @@ int check_ref_format(const char *ref)\n \t\t\t\treturn CHECK_REF_FORMAT_ERROR;\n \t\t\tif (level < 2)\n \t\t\t\treturn CHECK_REF_FORMAT_ONELEVEL;\n-\t\t\tif (has_extension(ref, \".lock\"))\n-\t\t\t\treturn CHECK_REF_FORMAT_ERROR;\n \t\t\treturn ret;\n \t\t}\n \t}\n@@ -996,7 +993,7 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)\n \t\tconst char *path;\n \n \t\tif (!(delopt & REF_NODEREF)) {\n-\t\t\ti = strlen(lock->lk->filename) - 5; /* .lock */\n+\t\t\ti = strlen(lock->lk->filename) - 5; /* ..lck */\n \t\t\tlock->lk->filename[i] = 0;\n \t\t\tpath = lock->lk->filename;\n \t\t} else {\n@@ -1363,7 +1360,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master,\n \t\terror(\"refname too long: %s\", refs_heads_master);\n \t\tgoto error_free_return;\n \t}\n-\tlockpath = mkpath(\"%s.lock\", git_HEAD);\n+\tlockpath = mkpath(\"%s..lck\", git_HEAD);\n \tfd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666);\n \tif (fd < 0) {\n \t\terror(\"Unable to open %s for writing\", lockpath);\n@@ -1593,7 +1590,7 @@ static int do_for_each_reflog(const char *base, each_ref_fn fn, void *cb_data)\n \t\t\tnamelen = strlen(de->d_name);\n \t\t\tif (namelen > 255)\n \t\t\t\tcontinue;\n-\t\t\tif (has_extension(de->d_name, \".lock\"))\n+\t\t\tif (has_extension(de->d_name, \"..lck\"))\n \t\t\t\tcontinue;\n \t\t\tmemcpy(log + baselen, de->d_name, namelen+1);\n \t\t\tif (stat(git_path(\"logs/%s\", log), &st) < 0)\ndiff --git a/t/t3505-cherry-pick-empty.sh b/t/t3505-cherry-pick-empty.sh\nindex 9aaeabd..3b7aa6d 100755\n--- a/t/t3505-cherry-pick-empty.sh\n+++ b/t/t3505-cherry-pick-empty.sh\n@@ -26,7 +26,7 @@ test_expect_code 1 'cherry-pick an empty commit' '\n \n test_expect_success 'index lockfile was removed' '\n \n-\ttest ! -f .git/index.lock\n+\ttest ! -f .git/index..lck\n \n '\n \ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex 76b1bb4..e437cf7 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -264,9 +264,9 @@ test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n \t    i=$(( $i + 1 ))\n \tdone | git update-index --index-info &&\n \tgit rm -n \"some-file-*\" | :;\n-\ttest -f .git/index.lock\n+\ttest -f .git/index..lck\n \tstatus=$?\n-\trm -f .git/index.lock\n+\trm -f .git/index..lck\n \tgit reset -q --hard\n \ttest \"$status\" != 0\n '\ndiff --git a/t/t4123-apply-shrink.sh b/t/t4123-apply-shrink.sh\nindex 984157f..fcd6a67 100755\n--- a/t/t4123-apply-shrink.sh\n+++ b/t/t4123-apply-shrink.sh\n@@ -47,7 +47,7 @@ test_expect_success 'apply should fail gracefully' '\n \telse\n \t\tstatus=$?\n \t\techo \"Status was $status\"\n-\t\tif test -f .git/index.lock\n+\t\tif test -f .git/index..lck\n \t\tthen\n \t\t\techo Oops, should not have crashed\n \t\t\tfalse\ndiff --git a/t/t7001-mv.sh b/t/t7001-mv.sh\nindex 10b8f8c..afe8240 100755\n--- a/t/t7001-mv.sh\n+++ b/t/t7001-mv.sh\n@@ -62,14 +62,14 @@ test_expect_success \\\n     'checking -f on untracked file with existing target' \\\n     'touch path0/untracked1 &&\n      git mv -f untracked1 path0\n-     test ! -f .git/index.lock &&\n+     test ! -f .git/index..lck &&\n      test -f untracked1 &&\n      test -f path0/untracked1'\n \n # clean up the mess in case bad things happen\n rm -f idontexist untracked1 untracked2 \\\n      path0/idontexist path0/untracked1 path0/untracked2 \\\n-     .git/index.lock\n+     .git/index..lck\n \n test_expect_success \\\n     'adding another file' \\\ndiff --git a/t/t7502-commit.sh b/t/t7502-commit.sh\nindex 56cd866..100da27 100755\n--- a/t/t7502-commit.sh\n+++ b/t/t7502-commit.sh\n@@ -241,7 +241,7 @@ test_expect_success EXECKEEPSPID 'a SIGTERM should break locks' '\n \t  GIT_EDITOR=.git/FAKE_EDITOR\n \t  export GIT_EDITOR\n \t  exec git commit -a'\\'' &&\n-\ttest ! -f .git/index.lock\n+\ttest ! -f .git/index..lck\n '\n \n rm -f .git/MERGE_MSG .git/COMMIT_EDITMSG\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex dad1437..ecce338 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -558,13 +558,13 @@ else\n \t\ttest -h \"$2\" &&\n \t\ttest \"$1\" = \"$(readlink \"$2\")\" || {\n \t\t\t# be super paranoid\n-\t\t\tif mkdir \"$2\".lock\n+\t\t\tif mkdir \"$2\"..lck\n \t\t\tthen\n \t\t\t\trm -f \"$2\" &&\n \t\t\t\tln -s \"$1\" \"$2\" &&\n-\t\t\t\trm -r \"$2\".lock\n+\t\t\t\trm -r \"$2\"..lck\n \t\t\telse\n-\t\t\t\twhile test -d \"$2\".lock\n+\t\t\t\twhile test -d \"$2\"..lck\n \t\t\t\tdo\n \t\t\t\t\tsay \"Waiting for lock on $2.\"\n \t\t\t\t\tsleep 1\n-- \n1.6.3.195.gad81\n\n\n-- \nShawn.\n"},{"id":"113292","messageId":"20090508005417.GV30527@spearce.org","threadId":"19231","inReplyTo":"7viqkcbenb.fsf_-_@alter.siamese.dyndns.org","subject":"Re: [PATCH] Allow branch names that end with \".lock\"","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2009-05-08T00:54:17Z","receivedAt":"2009-05-08T00:54:17Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Junio C Hamano <gitster@pobox.com> wrote:\n> A project policy for naming branches could be to use a dot as a word\n> separator (instead of '-' which is often done by existing projects), and\n> \"fix.vm.lock\" could be a very valid name for a branch to address a VM\n> locking issues.\n\nI think we sent the same patch... except...\n \n>  git-gui/lib/index.tcl                    |    2 +-\n\nDon't do that.  I'll patch git-gui and send you a pull request.\n\n-- \nShawn.\n"},{"id":"113293","messageId":"7veiv0bee2.fsf@alter.siamese.dyndns.org","threadId":"19231","inReplyTo":"20090508005417.GV30527@spearce.org","subject":"Re: [PATCH] Allow branch names that end with \".lock\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-05-08T00:57:09Z","receivedAt":"2009-05-08T00:57:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Shawn O. Pearce\" <spearce@spearce.org> writes:\n\n> Junio C Hamano <gitster@pobox.com> wrote:\n>> A project policy for naming branches could be to use a dot as a word\n>> separator (instead of '-' which is often done by existing projects), and\n>> \"fix.vm.lock\" could be a very valid name for a branch to address a VM\n>> locking issues.\n>\n> I think we sent the same patch... except...\n>\n>>  git-gui/lib/index.tcl                    |    2 +-\n>\n> Don't do that.  I'll patch git-gui and send you a pull request.\n\nWhy not?  I never commit my \"how about this\" weatherbaloon patches\ndirectly ;-)\n\nIf you found that ours match identically except for that one line, that is\na very good indication.  I didn't check.\n"},{"id":"113294","messageId":"20090508010110.GW30527@spearce.org","threadId":"19231","inReplyTo":"7veiv0bee2.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] Allow branch names that end with \".lock\"","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2009-05-08T01:01:10Z","receivedAt":"2009-05-08T01:01:10Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Junio C Hamano <gitster@pobox.com> wrote:\n> \"Shawn O. Pearce\" <spearce@spearce.org> writes:\n> \n> > Junio C Hamano <gitster@pobox.com> wrote:\n> >> A project policy for naming branches could be to use a dot as a word\n> >> separator (instead of '-' which is often done by existing projects), and\n> >> \"fix.vm.lock\" could be a very valid name for a branch to address a VM\n> >> locking issues.\n> >\n> > I think we sent the same patch... except...\n> >\n> >>  git-gui/lib/index.tcl                    |    2 +-\n> >\n> > Don't do that.  I'll patch git-gui and send you a pull request.\n> \n> Why not?  I never commit my \"how about this\" weatherbaloon patches\n> directly ;-)\n\nI know.  I was saying, \"don't patch git-gui in the same commit\nas git.git\".  I would have spun that as two different commits.\n\n> If you found that ours match identically except for that one line, that is\n> a very good indication.  I didn't check.\n\nHere's `git diff yours mine`, we were really close:\n\ndiff --git a/Documentation/technical/api-lockfile.txt b/Documentation/technical/api-lockfile.txt\nindex 31e1141..982984f 100644\n--- a/Documentation/technical/api-lockfile.txt\n+++ b/Documentation/technical/api-lockfile.txt\n@@ -4,7 +4,7 @@ lockfile API\n The lockfile API serves two purposes:\n \n * Mutual exclusion.  When we write out a new index file, first\n-  we create a new \"lock\" file `$GIT_DIR/index..lck`, write the new\n+  we create a new file `$GIT_DIR/index..lck`, write the new\n   contents into it, and rename it to the final destination\n   `$GIT_DIR/index`.  We try to create the `$GIT_DIR/index..lck`\n   file with O_EXCL so that we can notice and fail when somebody\n\nACK, I like your version better than mine.\n\ndiff --git a/refs.c b/refs.c\nindex 03aded9..b4ca305 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -742,8 +742,6 @@ int check_ref_format(const char *ref)\n \t\t\t\treturn CHECK_REF_FORMAT_ERROR;\n \t\t\tif (level < 2)\n \t\t\t\treturn CHECK_REF_FORMAT_ONELEVEL;\n-\t\t\tif (has_extension(ref, \"..lck\"))\n-\t\t\t\treturn CHECK_REF_FORMAT_ERROR;\n \t\t\treturn ret;\n \t\t}\n \t}\n\nNAK, I like how I removed this block.  It can't happen anymore,\nthe no \"..\" in name earlier should have caught the condition.\n\n-- \nShawn.\n"},{"id":"113297","messageId":"7vab5obd39.fsf@alter.siamese.dyndns.org","threadId":"19231","inReplyTo":"20090508010110.GW30527@spearce.org","subject":"Re: [PATCH] Allow branch names that end with \".lock\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-05-08T01:25:14Z","receivedAt":"2009-05-08T01:25:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Shawn O. Pearce\" <spearce@spearce.org> writes:\n\n> diff --git a/refs.c b/refs.c\n> index 03aded9..b4ca305 100644\n> --- a/refs.c\n> +++ b/refs.c\n> @@ -742,8 +742,6 @@ int check_ref_format(const char *ref)\n>  \t\t\t\treturn CHECK_REF_FORMAT_ERROR;\n>  \t\t\tif (level < 2)\n>  \t\t\t\treturn CHECK_REF_FORMAT_ONELEVEL;\n> -\t\t\tif (has_extension(ref, \"..lck\"))\n> -\t\t\t\treturn CHECK_REF_FORMAT_ERROR;\n>  \t\t\treturn ret;\n>  \t\t}\n>  \t}\n>\n> NAK, I like how I removed this block.  It can't happen anymore,\n> the no \"..\" in name earlier should have caught the condition.\n\nVery true.  Thanks.\n"},{"id":"113314","messageId":"81b0412b0905080024r211864bfhe7f70acabe0880c6@mail.gmail.com","threadId":"19231","inReplyTo":"20090508004741.GU30527@spearce.org","subject":"Re: [JGIT PATCH 2/2] Make Repository.isValidRefName compatible with Git 1.6.3","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2009-05-08T07:24:02Z","receivedAt":"2009-05-08T07:24:02Z","isPatch":true,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"2009/5/8 Shawn O. Pearce <spearce@spearce.org>:\n> --- a/lockfile.c\n> +++ b/lockfile.c\n> @@ -129,11 +129,11 @@ static int lock_file(struct lock_file *lk, const char *path, int flags)\n>        strcpy(lk->filename, path);\n>        /*\n>         * subtract 5 from size to make sure there's room for adding\n> -        * \".lock\" for the lock file name\n> +        * \"..lck\" for the lock file name\n>         */\n>        if (!(flags & LOCK_NODEREF))\n>                resolve_symlink(lk->filename, sizeof(lk->filename)-5);\n> -       strcat(lk->filename, \".lock\");\n> +       strcat(lk->filename, \"..lck\");\n>        lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);\n\nThere must be at least some deprecation period during which\nalso the old .lock lockfiles are considered and created.\nJust imagine someone modifying the ref with an older version,\nwhich knows nothing about ..lck.\n"},{"id":"113322","messageId":"alpine.DEB.1.00.0905081003460.18521@pacific.mpi-cbg.de","threadId":"19231","inReplyTo":"81b0412b0905080024r211864bfhe7f70acabe0880c6@mail.gmail.com","subject":"Re: [JGIT PATCH 2/2] Make Repository.isValidRefName compatible with Git 1.6.3","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-05-08T08:04:35Z","receivedAt":"2009-05-08T08:04:35Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 8 May 2009, Alex Riesen wrote:\n\n> 2009/5/8 Shawn O. Pearce <spearce@spearce.org>:\n> > --- a/lockfile.c\n> > +++ b/lockfile.c\n> > @@ -129,11 +129,11 @@ static int lock_file(struct lock_file *lk, const char *path, int flags)\n> >        strcpy(lk->filename, path);\n> >        /*\n> >         * subtract 5 from size to make sure there's room for adding\n> > -        * \".lock\" for the lock file name\n> > +        * \"..lck\" for the lock file name\n> >         */\n> >        if (!(flags & LOCK_NODEREF))\n> >                resolve_symlink(lk->filename, sizeof(lk->filename)-5);\n> > -       strcat(lk->filename, \".lock\");\n> > +       strcat(lk->filename, \"..lck\");\n> >        lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);\n> \n> There must be at least some deprecation period during which\n> also the old .lock lockfiles are considered and created.\n> Just imagine someone modifying the ref with an older version,\n> which knows nothing about ..lck.\n\nAs lock files are only supposed to be created by Git itself, and have a \nmaximum lifetime until the end of the process, I think we do not need a \ngrace period at all.\n\nCiao,\nDscho\n"},{"id":"113330","messageId":"7vljp80yt4.fsf@alter.siamese.dyndns.org","threadId":"19231","inReplyTo":"alpine.DEB.1.00.0905081003460.18521@pacific.mpi-cbg.de","subject":"Re: [JGIT PATCH 2/2] Make Repository.isValidRefName compatible with Git 1.6.3","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-05-08T08:43:51Z","receivedAt":"2009-05-08T08:43:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n>> There must be at least some deprecation period during which\n>> also the old .lock lockfiles are considered and created.\n>> Just imagine someone modifying the ref with an older version,\n>> which knows nothing about ..lck.\n>\n> As lock files are only supposed to be created by Git itself, and have a \n> maximum lifetime until the end of the process, I think we do not need a \n> grace period at all.\n\nCould there be people with slightly older git and shiny new jgit (or the\nother combination) working on the same repository?\n"},{"id":"113337","messageId":"alpine.DEB.1.00.0905081153050.4601@intel-tinevez-2-302","threadId":"19231","inReplyTo":"7vljp80yt4.fsf@alter.siamese.dyndns.org","subject":"Re: [JGIT PATCH 2/2] Make Repository.isValidRefName compatible with Git 1.6.3","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-05-08T09:54:08Z","receivedAt":"2009-05-08T09:54:08Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 8 May 2009, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> >> There must be at least some deprecation period during which also the \n> >> old .lock lockfiles are considered and created. Just imagine someone \n> >> modifying the ref with an older version, which knows nothing about \n> >> ..lck.\n> >\n> > As lock files are only supposed to be created by Git itself, and have \n> > a maximum lifetime until the end of the process, I think we do not \n> > need a grace period at all.\n> \n> Could there be people with slightly older git and shiny new jgit (or the \n> other combination) working on the same repository?\n\nYou mean concurrently?  Sure, but do we have to care?  People doing this \ncertainly know what they are doing, and live happily even with a 0.5\" \nhole in their foot.\n\nCiao,\nDscho\n"},{"id":"113342","messageId":"81b0412b0905080445j6d91f05jb13169ebd0245935@mail.gmail.com","threadId":"19231","inReplyTo":"alpine.DEB.1.00.0905081153050.4601@intel-tinevez-2-302","subject":"Re: [JGIT PATCH 2/2] Make Repository.isValidRefName compatible with Git 1.6.3","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2009-05-08T11:45:05Z","receivedAt":"2009-05-08T11:45:05Z","isPatch":true,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"2009/5/8 Johannes Schindelin <Johannes.Schindelin@gmx.de>:\n> On Fri, 8 May 2009, Junio C Hamano wrote:\n>> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n>>\n>> >> There must be at least some deprecation period during which also the\n>> >> old .lock lockfiles are considered and created. Just imagine someone\n>> >> modifying the ref with an older version, which knows nothing about\n>> >> ..lck.\n>> >\n>> > As lock files are only supposed to be created by Git itself, and have\n>> > a maximum lifetime until the end of the process, I think we do not\n>> > need a grace period at all.\n>>\n>> Could there be people with slightly older git and shiny new jgit (or the\n>> other combination) working on the same repository?\n>\n> You mean concurrently?  Sure, but do we have to care?  People doing this\n> certainly know what they are doing, and live happily even with a 0.5\"\n> hole in their foot.\n\nI certainly hope that'll be you, one day.\n\nOf course people run git concurrently on the same repo. Even from different\nmachines.\n\nThat's _why_ we have the locking in the first place.\n\nAnd of course there will be different versions of git installed on\nthese machines.\nAnd most certainly the people will not know what they were doing, blame the\nhole on Git (and maybe even shoot you in return, after they'll find that stupid\nmessage of yours in archives).\n"},{"id":"113348","messageId":"20090508143436.GX30527@spearce.org","threadId":"19231","inReplyTo":"81b0412b0905080445j6d91f05jb13169ebd0245935@mail.gmail.com","subject":"Re: [JGIT PATCH 2/2] Make Repository.isValidRefName compatible with Git 1.6.3","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2009-05-08T14:34:36Z","receivedAt":"2009-05-08T14:34:36Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Alex Riesen <raa.lkml@gmail.com> wrote:\n> 2009/5/8 Johannes Schindelin <Johannes.Schindelin@gmx.de>:\n> > On Fri, 8 May 2009, Junio C Hamano wrote:\n> >>\n> >> Could there be people with slightly older git and shiny new jgit (or the\n> >> other combination) working on the same repository?\n\nYes, Gerrit Code Review runs a JGit daemon 24/7.  I have a lot\nof folks running Gerrit servers inside their company networks,\nand two running them on the public internet.  Gerrit runs bleeding\nedge JGit, and would most certainly pick up a \"..lck\" patch there\nbefore they upgrade their git-core package.\n\nThis is one of those cases where the locking is really important,\nbecause you should be able to concurrently access the same git\nrepository from the command line with git-core utilities while\nGerrit's daemon process is servicing network based user requests.\n\n> > You mean concurrently? ??Sure, but do we have to care? ??People doing this\n> > certainly know what they are doing, and live happily even with a 0.5\"\n> > hole in their foot.\n\nYes, dammit, we should care.\n\n> Of course people run git concurrently on the same repo. Even from different\n> machines.\n\nEven ignoring JGit and Gerrit's daemon process entirely as \"useless\nstupid projects that never should have happened\", _this_ is enough\nof a reason to care.  People use Git on NFS all of the time.\nWith different machines.  Accessing the same repo.  Those different\nmachines most likely have different versions of Git installed.\n\n> That's _why_ we have the locking in the first place.\n\nYes.\n\nI've actually thought about this \"fix.vm.lock\" being invalid for\nquite a while now, and wanted to change lockfile.c to use another\npattern that was already an invalid ref name, like Junio's \"..lck\"\nproposal does.  But I've never been able to come up with a sane way\nto deal with the transition.  So I never brought the topic up before.\n\nI still don't have a sane way to deal with the transition.\n\nThe only thing I can think of is:\n\n  - grab \".lock\"\n  - grab \"..lck\"\n  - do stuff\n  - commit by link(\"..lck\", orig)\n  - ulink \".lock\"\n\nAnd maybe in a year we stop writing \".lock\".\n\nBut, here's news for you, *#@!#@@!$@!*&@! distributions are still\nshipping 1.5.0-1.5.0.3.  In particular I've spent the better part\nof this past two weeks telling new Git users to upgrade off of these\nversions due to the pread() bug introduced in [1] and fixed in [2].\n\nI've seen WAAAAY too many \"fatal: cannot pread pack file:\" errors.\nEnough for a lifetime.\n\n[1] http://repo.or.cz/w/git.git?a=commit;h=6d2fa7f1b489c65e677c18eda5c144dbc5d614ab\n[2] http://repo.or.cz/w/git.git?a=commit;h=a91d49cd369ac5fc8e1a17357a975d09cf6c8cb3\n\n-- \nShawn.\n"}]}