From: mhagger@alum.mit.edu
To: Junio C Hamano <gitster@pobox.com>
Cc: git@vger.kernel.org, Jeff King <peff@peff.net>,
cmn@elego.de, A Large Angry SCM <gitzilla@gmail.com>,
Daniel Barkalow <barkalow@iabervon.org>,
Sverre Rabbelier <srabbelier@gmail.com>,
Michael Haggerty <mhagger@alum.mit.edu>
Subject: [RFC 03/13] Teach check_refname_format() to check full refnames
Date: Wed, 19 Oct 2011 22:55:06 +0200 [thread overview]
Message-ID: <1319057716-28094-4-git-send-email-mhagger@alum.mit.edu> (raw)
In-Reply-To: <1319057716-28094-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
A full refname has to start with "refs/" or consist entirely of capital
letters and underscores. Add an option REFNAME_FULL that causes
check_refname_format() and parse_refname_prefix() to verify that the
refname is a valid full refname.
Add a "--full" option to "git check-ref-format" that can be used to
access the new option. Use this to add some tests involving "git
check-ref-format --full".
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
Documentation/git-check-ref-format.txt | 14 +++++++++++
builtin/check-ref-format.c | 4 +++
refs.c | 39 ++++++++++++++++++-------------
refs.h | 12 ++++++---
t/t1402-check-ref-format.sh | 31 +++++++++++++++++++++++++
5 files changed, 80 insertions(+), 20 deletions(-)
diff --git a/Documentation/git-check-ref-format.txt b/Documentation/git-check-ref-format.txt
index 103e7b1..9a8aafb 100644
--- a/Documentation/git-check-ref-format.txt
+++ b/Documentation/git-check-ref-format.txt
@@ -27,6 +27,11 @@ if refs are packed by `git gc`).
git imposes the following rules on how references are named:
+. They must either start with `refs/` (e.g., `refs/heads/master`) or
+ consist entirely of capital letters and underscores (e.g., `HEAD` or
+ `MERGE_HEAD`). This rule is enforced if the `--full` option is
+ used.
+
. They can include slash `/` for hierarchical (directory)
grouping, but no slash-separated component can begin with a
dot `.` or end with the sequence `.lock`.
@@ -83,6 +88,15 @@ typed the branch name.
OPTIONS
-------
+--full::
+--no-full::
+ Controls whether the refname must represent a full refname
+ (i.e., starting with `refs/`). If `--full` and
+ `--allow-onelevel` are both specified, then special top-level
+ refnames consisting of capital letters and underscored (like
+ `HEAD` or `MERGE_HEAD`) are also allowed. The default is
+ `--no-full`.
+
--allow-onelevel::
--no-allow-onelevel::
Controls whether one-level refnames are accepted (i.e.,
diff --git a/builtin/check-ref-format.c b/builtin/check-ref-format.c
index 28a7320..a73626d 100644
--- a/builtin/check-ref-format.c
+++ b/builtin/check-ref-format.c
@@ -64,6 +64,10 @@ int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
for (i = 1; i < argc && argv[i][0] == '-'; i++) {
if (!strcmp(argv[i], "--normalize") || !strcmp(argv[i], "--print"))
normalize = 1;
+ else if (!strcmp(argv[i], "--full"))
+ flags |= REFNAME_FULL;
+ else if (!strcmp(argv[i], "--no-full"))
+ flags &= ~REFNAME_FULL;
else if (!strcmp(argv[i], "--allow-onelevel"))
flags |= REFNAME_ALLOW_ONELEVEL;
else if (!strcmp(argv[i], "--no-allow-onelevel"))
diff --git a/refs.c b/refs.c
index 387da83..8299e51 100644
--- a/refs.c
+++ b/refs.c
@@ -980,6 +980,11 @@ static int parse_refname_prefix(const char *ref, int len, int flags)
component_count++;
if (component_len == len || p[component_len] != '/')
break;
+ if (component_count == 1 && (flags & REFNAME_FULL)) {
+ /* That was the first of multiple components */
+ if (component_len != 4 || strncmp(p, "refs", 4))
+ return -1;
+ }
/* Skip to next component. */
p += component_len + 1;
len -= component_len + 1;
@@ -989,8 +994,22 @@ static int parse_refname_prefix(const char *ref, int len, int flags)
if (ref[valid_len - 1] == '.')
return -1; /* Refname ends with '.'. */
- if (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)
- return -1; /* Refname has only one component. */
+
+ if (component_count == 1) {
+ if (!(flags & REFNAME_ALLOW_ONELEVEL))
+ return -1;
+
+ if (flags & REFNAME_FULL) {
+ /* Make sure that the refname is ALL_CAPS. */
+ int i;
+ for (i = 0; i < component_len; i++) {
+ char ch = p[i];
+ if (ch != '_' && (ch < 'A' || 'Z' < ch))
+ return -1;
+ }
+ }
+ }
+
return valid_len;
}
@@ -1028,20 +1047,8 @@ const char *ref_fetch_rules[] = {
static int refname_ok_at_root_level(const char *str, int len)
{
- if (len >= 5 && !memcmp(str, "refs/", 5))
- return 1;
-
- while (len--) {
- char ch = *str++;
-
- /*
- * Only accept likes of .git/HEAD, .git/MERGE_HEAD at
- * the root level as a ref.
- */
- if (ch != '_' && (ch < 'A' || 'Z' < ch))
- return 0;
- }
- return 1;
+ return parse_refname_prefix(str, len,
+ REFNAME_ALLOW_ONELEVEL|REFNAME_FULL) == len;
}
int refname_match(const char *abbrev_name, const char *full_name, const char **rules)
diff --git a/refs.h b/refs.h
index 0229c57..7707cda 100644
--- a/refs.h
+++ b/refs.h
@@ -97,9 +97,10 @@ int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long, voi
*/
extern int for_each_reflog(each_ref_fn, void *);
-#define REFNAME_ALLOW_ONELEVEL 1
-#define REFNAME_REFSPEC_PATTERN 2
-#define REFNAME_DOT_COMPONENT 4
+#define REFNAME_ALLOW_ONELEVEL 01
+#define REFNAME_REFSPEC_PATTERN 02
+#define REFNAME_DOT_COMPONENT 04
+#define REFNAME_FULL 010
/*
* Return 0 iff ref has the correct format for a refname according to
@@ -110,7 +111,10 @@ extern int for_each_reflog(each_ref_fn, void *);
* components. No leading or repeated slashes are accepted. If
* REFNAME_DOT_COMPONENT is set in flags, then allow refname
* components to start with "." (but not a whole component equal to
- * "." or "..").
+ * "." or ".."). If REFNAME_FULL is set in flags, then additionally
+ * verify that the refname is a valid full refname--that it either
+ * starts with "refs/" or that it consists of only capital letters and
+ * underscores (like "HEAD" or "MERGE_HEAD").
*/
extern int check_refname_format(const char *ref, int flags);
diff --git a/t/t1402-check-ref-format.sh b/t/t1402-check-ref-format.sh
index 1ae4d87..2f8a48e 100755
--- a/t/t1402-check-ref-format.sh
+++ b/t/t1402-check-ref-format.sh
@@ -70,6 +70,7 @@ invalid_ref "$ref" --refspec-pattern
valid_ref "$ref" '--refspec-pattern --allow-onelevel'
invalid_ref "$ref" --normalize
valid_ref "$ref" '--allow-onelevel --normalize'
+invalid_ref "$ref" '--full'
ref='foo/bar'
valid_ref "$ref"
@@ -77,12 +78,19 @@ valid_ref "$ref" --allow-onelevel
valid_ref "$ref" --refspec-pattern
valid_ref "$ref" '--refspec-pattern --allow-onelevel'
valid_ref "$ref" --normalize
+invalid_ref "$ref" '--full'
ref='foo/*'
invalid_ref "$ref"
invalid_ref "$ref" --allow-onelevel
valid_ref "$ref" --refspec-pattern
valid_ref "$ref" '--refspec-pattern --allow-onelevel'
+invalid_ref "$ref" '--full'
+invalid_ref "$ref" '--refspec-pattern --full'
+
+ref='refs/*'
+invalid_ref "$ref" '--full'
+valid_ref "$ref" '--refspec-pattern --full'
ref='*/foo'
invalid_ref "$ref"
@@ -91,18 +99,23 @@ valid_ref "$ref" --refspec-pattern
valid_ref "$ref" '--refspec-pattern --allow-onelevel'
invalid_ref "$ref" --normalize
valid_ref "$ref" '--refspec-pattern --normalize'
+invalid_ref "$ref" '--full'
+invalid_ref "$ref" '--refspec-pattern --full'
ref='foo/*/bar'
invalid_ref "$ref"
invalid_ref "$ref" --allow-onelevel
valid_ref "$ref" --refspec-pattern
valid_ref "$ref" '--refspec-pattern --allow-onelevel'
+invalid_ref "$ref" '--full'
ref='*'
invalid_ref "$ref"
invalid_ref "$ref" --allow-onelevel
invalid_ref "$ref" --refspec-pattern
valid_ref "$ref" '--refspec-pattern --allow-onelevel'
+invalid_ref "$ref" '--full'
+invalid_ref "$ref" '--refspec-pattern --full'
ref='foo/*/*'
invalid_ref "$ref" --refspec-pattern
@@ -126,6 +139,24 @@ valid_ref NOT_MINGW "$ref" '--allow-onelevel --normalize'
invalid_ref NOT_MINGW "$ref" '--refspec-pattern --normalize'
valid_ref NOT_MINGW "$ref" '--refspec-pattern --allow-onelevel --normalize'
+ref='HEAD'
+invalid_ref "$ref"
+valid_ref "$ref" --allow-onelevel
+invalid_ref "$ref" --full
+valid_ref "$ref" '--allow-onelevel --full'
+
+valid_ref FETCH_HEAD '--allow-onelevel --full'
+valid_ref refs/foo --full
+invalid_ref HEAD/ '--allow-onelevel --full'
+valid_ref HEAD/ '--allow-onelevel --full --normalize'
+invalid_ref refs '--full'
+invalid_ref refs '--allow-onelevel --full'
+invalid_ref refs/ '--allow-onelevel --full'
+invalid_ref HEAD/foo '--full'
+invalid_ref head '--allow-onelevel --full'
+valid_ref 'refs/foo/*' '--refspec-pattern --full'
+valid_ref 'refs/*/foo' '--refspec-pattern --full'
+
test_expect_success "check-ref-format --branch @{-1}" '
T=$(git write-tree) &&
sha1=$(echo A | git commit-tree $T) &&
--
1.7.7
next prev parent reply other threads:[~2011-10-19 20:55 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-10-19 20:55 [RFC 00/13] Checking full vs. partial refnames mhagger
2011-10-19 20:55 ` [RFC 01/13] check_refname_component(): iterate via index rather than via pointer mhagger
2011-10-19 20:55 ` [RFC 02/13] parse_refname_prefix(): new function mhagger
2011-10-19 20:55 ` mhagger [this message]
2011-10-19 20:55 ` [RFC 04/13] add_ref(): move the call of check_refname_format() to callers mhagger
2011-10-19 21:49 ` Junio C Hamano
2011-10-19 21:59 ` Michael Haggerty
2011-10-19 20:55 ` [RFC 05/13] receive-pack::update(): use check_refname_format(..., REFNAME_FULL) mhagger
2011-10-19 20:55 ` [RFC 06/13] strbuf_check_branch_ref(): " mhagger
2011-10-19 20:55 ` [RFC 07/13] one_local_ref(): " mhagger
2011-10-19 20:55 ` [RFC 08/13] expand_namespace(): the refname is full, so use REFNAME_FULL option mhagger
2011-10-19 20:55 ` [RFC 09/13] new_branch(): verify that new branch name is a valid full refname mhagger
2011-10-19 21:52 ` Junio C Hamano
2011-10-19 20:55 ` [RFC 10/13] strbuf_check_tag_ref(): the refname is full, so use REFNAME_FULL option mhagger
2011-10-19 20:55 ` [RFC 11/13] replace_object(): " mhagger
2011-10-19 20:55 ` [RFC 12/13] resolve_ref: use check_refname_format(..., REFNAME_FULL) mhagger
2011-10-19 20:55 ` [RFC 13/13] filter_refs(): the refname is full, so use REFNAME_FULL option mhagger
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=1319057716-28094-4-git-send-email-mhagger@alum.mit.edu \
--to=mhagger@alum.mit.edu \
--cc=barkalow@iabervon.org \
--cc=cmn@elego.de \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=gitzilla@gmail.com \
--cc=peff@peff.net \
--cc=srabbelier@gmail.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).