From: "Shawn O. Pearce" <spearce@spearce.org>
To: Robin Rosenberg <robin.rosenberg@dewire.com>
Cc: git@vger.kernel.org
Subject: [JGIT PATCH 2/2] Make Repository.isValidRefName compatible with Git 1.6.3
Date: Thu, 7 May 2009 08:05:14 -0700 [thread overview]
Message-ID: <1241708714-20326-2-git-send-email-spearce@spearce.org> (raw)
In-Reply-To: <1241708714-20326-1-git-send-email-spearce@spearce.org>
In 3e262b95c509 I taught C Git to disallow refs whose names end in
".lock". This suffix is used by the atomic update mechanism as a
signal that the ref is being modified. When reading a loose ref
directory both JGit and C Git skip over any files whose names end
with this suffix, as the file is assumed to be one of these magic
locking files from another concurrent process. Consequently, any
ref that ends with this name will become invisible once created.
We also add a suite of tests for the isValidRefName function, fix
its formatting to better conform to current style conventions, and
correct the result for "master"; this is not a valid ref name as it
has only 1 path component. At least 2 path components is required.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
.../tst/org/spearce/jgit/lib/ValidRefNameTest.java | 168 ++++++++++++++++++++
.../src/org/spearce/jgit/lib/Repository.java | 28 ++--
2 files changed, 181 insertions(+), 15 deletions(-)
create mode 100644 org.spearce.jgit.test/tst/org/spearce/jgit/lib/ValidRefNameTest.java
diff --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
new file mode 100644
index 0000000..5cca682
--- /dev/null
+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/ValidRefNameTest.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2009, Google Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Git Development Community nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.spearce.jgit.lib;
+
+import junit.framework.TestCase;
+
+public class ValidRefNameTest extends TestCase {
+ private static void assertValid(final boolean exp, final String name) {
+ assertEquals("\"" + name + "\"", exp, Repository.isValidRefName(name));
+ }
+
+ public void testEmptyString() {
+ assertValid(false, "");
+ assertValid(false, "/");
+ }
+
+ public void testMustHaveTwoComponents() {
+ assertValid(false, "master");
+ assertValid(true, "heads/master");
+ }
+
+ public void testValidHead() {
+ assertValid(true, "refs/heads/master");
+ assertValid(true, "refs/heads/pu");
+ assertValid(true, "refs/heads/z");
+ assertValid(true, "refs/heads/FoO");
+ }
+
+ public void testValidTag() {
+ assertValid(true, "refs/tags/v1.0");
+ }
+
+ public void testNoLockSuffix() {
+ assertValid(false, "refs/heads/master.lock");
+ }
+
+ public void testNoDirectorySuffix() {
+ assertValid(false, "refs/heads/master/");
+ }
+
+ public void testNoSpace() {
+ assertValid(false, "refs/heads/i haz space");
+ }
+
+ public void testNoAsciiControlCharacters() {
+ for (char c = '\0'; c < ' '; c++)
+ assertValid(false, "refs/heads/mast" + c + "er");
+ }
+
+ public void testNoBareDot() {
+ assertValid(false, "refs/heads/.");
+ assertValid(false, "refs/heads/..");
+ assertValid(false, "refs/heads/./master");
+ assertValid(false, "refs/heads/../master");
+ }
+
+ public void testNoLeadingDot() {
+ assertValid(false, ".");
+ assertValid(false, "refs/heads/.bar");
+ assertValid(false, "refs/heads/..bar");
+ }
+
+ public void testContainsDot() {
+ assertValid(true, "refs/heads/m.a.s.t.e.r");
+ assertValid(false, "refs/heads/master..pu");
+ }
+
+ public void testNoMagicRefCharacters() {
+ assertValid(false, "refs/heads/master^");
+ assertValid(false, "refs/heads/^master");
+ assertValid(false, "^refs/heads/master");
+
+ assertValid(false, "refs/heads/master~");
+ assertValid(false, "refs/heads/~master");
+ assertValid(false, "~refs/heads/master");
+
+ assertValid(false, "refs/heads/master:");
+ assertValid(false, "refs/heads/:master");
+ assertValid(false, ":refs/heads/master");
+ }
+
+ public void testShellGlob() {
+ assertValid(false, "refs/heads/master?");
+ assertValid(false, "refs/heads/?master");
+ assertValid(false, "?refs/heads/master");
+
+ assertValid(false, "refs/heads/master[");
+ assertValid(false, "refs/heads/[master");
+ assertValid(false, "[refs/heads/master");
+
+ assertValid(false, "refs/heads/master*");
+ assertValid(false, "refs/heads/*master");
+ assertValid(false, "*refs/heads/master");
+ }
+
+ public void testValidSpecialCharacters() {
+ assertValid(true, "refs/heads/!");
+ assertValid(true, "refs/heads/\"");
+ assertValid(true, "refs/heads/#");
+ assertValid(true, "refs/heads/$");
+ assertValid(true, "refs/heads/%");
+ assertValid(true, "refs/heads/&");
+ assertValid(true, "refs/heads/'");
+ assertValid(true, "refs/heads/(");
+ assertValid(true, "refs/heads/)");
+ assertValid(true, "refs/heads/+");
+ assertValid(true, "refs/heads/,");
+ assertValid(true, "refs/heads/-");
+ assertValid(true, "refs/heads/;");
+ assertValid(true, "refs/heads/<");
+ assertValid(true, "refs/heads/=");
+ assertValid(true, "refs/heads/>");
+ assertValid(true, "refs/heads/@");
+ assertValid(true, "refs/heads/]");
+ assertValid(true, "refs/heads/_");
+ assertValid(true, "refs/heads/`");
+ assertValid(true, "refs/heads/{");
+ assertValid(true, "refs/heads/|");
+ assertValid(true, "refs/heads/}");
+
+ // This is valid on UNIX, but not on Windows.
+ //
+ assertValid(true, "refs/heads/\\");
+ }
+
+ public void testRefLogQueryIsValidRef() {
+ // Yes, these are actually ambiguous. You can create a ref
+ // that also looks like a reflog query.
+ //
+ assertValid(true, "refs/heads/master@{1}");
+ assertValid(true, "refs/heads/master@{1.hour.ago}");
+ }
+}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
index 5baa7a0..66dcd46 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
@@ -939,36 +939,34 @@ public static boolean isValidRefName(final String refName) {
final int len = refName.length();
if (len == 0)
return false;
+ if (refName.endsWith(".lock"))
+ return false;
+ int components = 1;
char p = '\0';
- for (int i=0; i<len; ++i) {
- char c = refName.charAt(i);
+ for (int i = 0; i < len; i++) {
+ final char c = refName.charAt(i);
if (c <= ' ')
return false;
- switch(c) {
+ switch (c) {
case '.':
- if (i == 0)
- return false;
- if (p == '/')
- return false;
- if (p == '.')
+ switch (p) {
+ case '\0': case '/': case '.':
return false;
+ }
break;
case '/':
- if (i == 0)
- return false;
- if (i == len -1)
+ if (i == 0 || i == len - 1)
return false;
+ components++;
break;
case '~': case '^': case ':':
- case '?': case '[':
- return false;
- case '*':
+ case '?': case '[': case '*':
return false;
}
p = c;
}
- return true;
+ return components > 1;
}
/**
--
1.6.3.195.gad81
next prev parent reply other threads:[~2009-05-07 15:06 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-05-07 15:05 [JGIT PATCH 1/2] Add support for boolean config values "yes", "no" Shawn O. Pearce
2009-05-07 15:05 ` Shawn O. Pearce [this message]
2009-05-07 23:02 ` [JGIT PATCH 2/2] Make Repository.isValidRefName compatible with Git 1.6.3 Robin Rosenberg
2009-05-07 23:29 ` Linus Torvalds
2009-05-08 0:32 ` Junio C Hamano
2009-05-08 0:47 ` Shawn O. Pearce
2009-05-08 7:24 ` Alex Riesen
2009-05-08 8:04 ` Johannes Schindelin
2009-05-08 8:43 ` Junio C Hamano
2009-05-08 9:54 ` Johannes Schindelin
2009-05-08 11:45 ` Alex Riesen
2009-05-08 14:34 ` Shawn O. Pearce
[not found] ` <7viqkcbenb.fsf_-_@alter.siamese.dyndns.org>
2009-05-08 0:54 ` [PATCH] Allow branch names that end with ".lock" Shawn O. Pearce
2009-05-08 0:57 ` Junio C Hamano
2009-05-08 1:01 ` Shawn O. Pearce
2009-05-08 1:25 ` Junio C Hamano
2009-05-07 17:56 ` [JGIT PATCH 1/2] Add support for boolean config values "yes", "no" Brandon Casey
2009-05-07 18:01 ` [JGIT PATCH v2 1/2] Add support for boolean config values "on", "off" Shawn O. Pearce
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1241708714-20326-2-git-send-email-spearce@spearce.org \
--to=spearce@spearce.org \
--cc=git@vger.kernel.org \
--cc=robin.rosenberg@dewire.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).