Skip to content

Commit a40e6fb

Browse files
mhaggergitster
authored andcommitted
Change check_refname_format() to reject unnormalized refnames
Since much of the infrastructure does not work correctly with unnormalized refnames, change check_refname_format() to reject them. Similarly, change "git check-ref-format" to reject unnormalized refnames by default. But add an option --normalize, which causes "git check-ref-format" to normalize the refname before checking its format, and print the normalized refname. This is exactly the behavior of the old --print option, which is retained but deprecated. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent a5e4ec0 commit a40e6fb

File tree

5 files changed

+49
-28
lines changed

5 files changed

+49
-28
lines changed

Documentation/git-check-ref-format.txt

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ git-check-ref-format - Ensures that a reference name is well formed
88
SYNOPSIS
99
--------
1010
[verse]
11-
'git check-ref-format' [--print]
12-
[--[no-]allow-onelevel] [--refspec-pattern] <refname>
11+
'git check-ref-format' [--normalize]
12+
[--[no-]allow-onelevel] [--refspec-pattern]
13+
<refname>
1314
'git check-ref-format' --branch <branchname-shorthand>
1415

1516
DESCRIPTION
@@ -45,7 +46,11 @@ git imposes the following rules on how references are named:
4546
bracket `[` anywhere. See the `--refspec-pattern` option below for
4647
an exception to this rule.
4748

48-
. They cannot end with a slash `/` nor a dot `.`.
49+
. They cannot begin or end with a slash `/` or contain multiple
50+
consecutive slashes (see the `--normalize` option below for an
51+
exception to this rule)
52+
53+
. They cannot end with a dot `.`.
4954

5055
. They cannot contain a sequence `@{`.
5156

@@ -70,10 +75,6 @@ reference name expressions (see linkgit:gitrevisions[7]):
7075

7176
. at-open-brace `@{` is used as a notation to access a reflog entry.
7277

73-
With the `--print` option, if 'refname' is acceptable, it prints the
74-
canonicalized name of a hypothetical reference with that name. That is,
75-
it prints 'refname' with any extra `/` characters removed.
76-
7778
With the `--branch` option, it expands the ``previous branch syntax''
7879
`@{-n}`. For example, `@{-1}` is a way to refer the last branch you
7980
were on. This option should be used by porcelains to accept this
@@ -95,6 +96,15 @@ OPTIONS
9596
in place of a one full pathname component (e.g.,
9697
`foo/{asterisk}/bar` but not `foo/bar{asterisk}`).
9798

99+
--normalize::
100+
Normalize 'refname' by removing any leading slash (`/`)
101+
characters and collapsing runs of adjacent slashes between
102+
name components into a single slash. Iff the normalized
103+
refname is valid then print it to standard output and exit
104+
with a status of 0. (`--print` is a deprecated way to spell
105+
`--normalize`.)
106+
107+
98108
EXAMPLES
99109
--------
100110

@@ -107,7 +117,7 @@ $ git check-ref-format --branch @{-1}
107117
* Determine the reference name to use for a new branch:
108118
+
109119
------------
110-
$ ref=$(git check-ref-format --print "refs/heads/$newbranch") ||
120+
$ ref=$(git check-ref-format --normalize "refs/heads/$newbranch") ||
111121
die "we do not like '$newbranch' as a branch name."
112122
------------
113123

builtin/check-ref-format.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include "strbuf.h"
99

1010
static const char builtin_check_ref_format_usage[] =
11-
"git check-ref-format [--print] [options] <refname>\n"
11+
"git check-ref-format [--normalize] [options] <refname>\n"
1212
" or: git check-ref-format --branch <branchname-shorthand>";
1313

1414
/*
@@ -51,7 +51,7 @@ static int check_ref_format_branch(const char *arg)
5151
int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
5252
{
5353
int i;
54-
int print = 0;
54+
int normalize = 0;
5555
int flags = 0;
5656
const char *refname;
5757

@@ -62,8 +62,8 @@ int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
6262
return check_ref_format_branch(argv[2]);
6363

6464
for (i = 1; i < argc && argv[i][0] == '-'; i++) {
65-
if (!strcmp(argv[i], "--print"))
66-
print = 1;
65+
if (!strcmp(argv[i], "--normalize") || !strcmp(argv[i], "--print"))
66+
normalize = 1;
6767
else if (!strcmp(argv[i], "--allow-onelevel"))
6868
flags |= REFNAME_ALLOW_ONELEVEL;
6969
else if (!strcmp(argv[i], "--no-allow-onelevel"))
@@ -77,13 +77,12 @@ int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
7777
usage(builtin_check_ref_format_usage);
7878

7979
refname = argv[i];
80+
if (normalize)
81+
refname = collapse_slashes(refname);
8082
if (check_refname_format(refname, flags))
8183
return 1;
82-
83-
if (print) {
84-
refname = collapse_slashes(refname);
84+
if (normalize)
8585
printf("%s\n", refname);
86-
}
8786

8887
return 0;
8988
}

refs.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -908,9 +908,6 @@ int check_refname_format(const char *ref, int flags)
908908
int component_len, component_count = 0;
909909

910910
while (1) {
911-
while (*ref == '/')
912-
ref++; /* tolerate leading and repeated slashes */
913-
914911
/* We are at the start of a path component. */
915912
component_len = check_refname_component(ref);
916913
if (component_len < 0) {

refs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ extern int for_each_reflog(each_ref_fn, void *);
106106
* REFNAME_ALLOW_ONELEVEL is set in flags, then accept one-level
107107
* reference names. If REFNAME_REFSPEC_PATTERN is set in flags, then
108108
* allow a "*" wildcard character in place of one of the name
109-
* components.
109+
* components. No leading or repeated slashes are accepted.
110110
*/
111111
extern int check_refname_format(const char *ref, int flags);
112112

t/t1402-check-ref-format.sh

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,17 @@ invalid_ref() {
2828
invalid_ref ''
2929
invalid_ref '/'
3030
invalid_ref '/' --allow-onelevel
31+
invalid_ref '/' --normalize
32+
invalid_ref '/' '--allow-onelevel --normalize'
3133
valid_ref 'foo/bar/baz'
32-
valid_ref 'refs///heads/foo'
34+
valid_ref 'foo/bar/baz' --normalize
35+
invalid_ref 'refs///heads/foo'
36+
valid_ref 'refs///heads/foo' --normalize
3337
invalid_ref 'heads/foo/'
34-
valid_ref '/heads/foo'
35-
valid_ref '///heads/foo'
38+
invalid_ref '/heads/foo'
39+
valid_ref '/heads/foo' --normalize
40+
invalid_ref '///heads/foo'
41+
valid_ref '///heads/foo' --normalize
3642
invalid_ref './foo'
3743
invalid_ref './foo/bar'
3844
invalid_ref 'foo/./bar'
@@ -60,12 +66,15 @@ invalid_ref "$ref"
6066
valid_ref "$ref" --allow-onelevel
6167
invalid_ref "$ref" --refspec-pattern
6268
valid_ref "$ref" '--refspec-pattern --allow-onelevel'
69+
invalid_ref "$ref" --normalize
70+
valid_ref "$ref" '--allow-onelevel --normalize'
6371

6472
ref='foo/bar'
6573
valid_ref "$ref"
6674
valid_ref "$ref" --allow-onelevel
6775
valid_ref "$ref" --refspec-pattern
6876
valid_ref "$ref" '--refspec-pattern --allow-onelevel'
77+
valid_ref "$ref" --normalize
6978

7079
ref='foo/*'
7180
invalid_ref "$ref"
@@ -78,6 +87,8 @@ invalid_ref "$ref"
7887
invalid_ref "$ref" --allow-onelevel
7988
valid_ref "$ref" --refspec-pattern
8089
valid_ref "$ref" '--refspec-pattern --allow-onelevel'
90+
invalid_ref "$ref" --normalize
91+
valid_ref "$ref" '--refspec-pattern --normalize'
8192

8293
ref='foo/*/bar'
8394
invalid_ref "$ref"
@@ -105,9 +116,13 @@ invalid_ref "$ref" '--refspec-pattern --allow-onelevel'
105116

106117
ref='/foo'
107118
invalid_ref "$ref"
108-
valid_ref "$ref" --allow-onelevel
119+
invalid_ref "$ref" --allow-onelevel
109120
invalid_ref "$ref" --refspec-pattern
110-
valid_ref "$ref" '--refspec-pattern --allow-onelevel'
121+
invalid_ref "$ref" '--refspec-pattern --allow-onelevel'
122+
invalid_ref "$ref" --normalize
123+
valid_ref "$ref" '--allow-onelevel --normalize'
124+
invalid_ref "$ref" '--refspec-pattern --normalize'
125+
valid_ref "$ref" '--refspec-pattern --allow-onelevel --normalize'
111126

112127
test_expect_success "check-ref-format --branch @{-1}" '
113128
T=$(git write-tree) &&
@@ -141,12 +156,12 @@ test_expect_success 'check-ref-format --branch from subdir' '
141156

142157
valid_ref_normalized() {
143158
test_expect_success "ref name '$1' simplifies to '$2'" "
144-
refname=\$(git check-ref-format --print '$1') &&
159+
refname=\$(git check-ref-format --normalize '$1') &&
145160
test \"\$refname\" = '$2'"
146161
}
147162
invalid_ref_normalized() {
148-
test_expect_success "check-ref-format --print rejects '$1'" "
149-
test_must_fail git check-ref-format --print '$1'"
163+
test_expect_success "check-ref-format --normalize rejects '$1'" "
164+
test_must_fail git check-ref-format --normalize '$1'"
150165
}
151166

152167
valid_ref_normalized 'heads/foo' 'heads/foo'

0 commit comments

Comments
 (0)