summaryrefslogtreecommitdiff
path: root/refs.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2009-03-21 13:27:31 -0700
committerJunio C Hamano <gitster@pobox.com>2009-03-24 00:53:03 -0700
commitcbdffe4093be77bbb1408e54eead7865dd3bc33f (patch)
treef066c46cfac039e1187f5d491e9611bb7926f727 /refs.c
parenta2fab531bbb00ff64335906e22854365be2eb5c7 (diff)
downloadgit-cbdffe4093be77bbb1408e54eead7865dd3bc33f.tar.gz
check_ref_format(): tighten refname rules
This changes the rules for refnames to forbid: (1) a refname that contains "@{" in it. Some people and foreign SCM converter may have named their branches as frotz@24 and we still want to keep supporting it. However, "git branch frotz@{24}" is a disaster. It cannot even checked out because "git checkout frotz@{24}" will interpret it as "detach the HEAD at twenty-fourth reflog entry of the frotz branch". (2) a refname that ends with a dot. We already reject a path component that begins with a dot, primarily to avoid ambiguous range interpretation. If we allowed ".B" as a valid ref, it is unclear if "A...B" means "in dot-B but not in A" or "either in A or B but not in both". But for this to be complete, we need also to forbid "A." to avoid "in B but not in A-dot". This was not a problem in the original range notation, but we should have added this restriction when three-dot notation was introduced. Unlike "no dot at the beginning of any path component" rule, this rule does not have to be "no dot at the end of any path component", because you cannot abbreviate the tail end away, similar to you can say "dot-B" to mean "refs/heads/dot-B". For these reasons, it is not likely people created branches with these names on purpose, but we have allowed such names to be used for quite some time, and it is possible that people created such branches by mistake or by accident. To help people with branches with such unfortunate names to recover, we still allow "branch -d 'bad.'" to delete such branches, and also allow "branch -m bad. good" to rename them. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'refs.c')
-rw-r--r--refs.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/refs.c b/refs.c
index 8d3c502a15..e355489e51 100644
--- a/refs.c
+++ b/refs.c
@@ -693,7 +693,7 @@ static inline int bad_ref_char(int ch)
int check_ref_format(const char *ref)
{
- int ch, level, bad_type;
+ int ch, level, bad_type, last;
int ret = CHECK_REF_FORMAT_OK;
const char *cp = ref;
@@ -717,19 +717,24 @@ int check_ref_format(const char *ref)
return CHECK_REF_FORMAT_ERROR;
}
+ last = ch;
/* scan the rest of the path component */
while ((ch = *cp++) != 0) {
bad_type = bad_ref_char(ch);
- if (bad_type) {
+ if (bad_type)
return CHECK_REF_FORMAT_ERROR;
- }
if (ch == '/')
break;
- if (ch == '.' && *cp == '.')
+ if (last == '.' && ch == '.')
+ return CHECK_REF_FORMAT_ERROR;
+ if (last == '@' && ch == '{')
return CHECK_REF_FORMAT_ERROR;
+ last = ch;
}
level++;
if (!ch) {
+ if (ref <= cp - 2 && cp[-2] == '.')
+ return CHECK_REF_FORMAT_ERROR;
if (level < 2)
return CHECK_REF_FORMAT_ONELEVEL;
return ret;