Skip to content

Commit 68d00fd

Browse files
committed
Merge branch 'jn/show-normalized-refs'
* jn/show-normalized-refs: check-ref-format: simplify --print implementation git check-ref-format --print Add tests for git check-ref-format Conflicts: Documentation/git-check-ref-format.txt
2 parents 97d484b + 1ba447b commit 68d00fd

File tree

3 files changed

+111
-6
lines changed

3 files changed

+111
-6
lines changed

Documentation/git-check-ref-format.txt

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ SYNOPSIS
99
--------
1010
[verse]
1111
'git check-ref-format' <refname>
12+
'git check-ref-format' --print <refname>
1213
'git check-ref-format' --branch <branchname-shorthand>
1314

1415
DESCRIPTION
@@ -63,19 +64,31 @@ reference name expressions (see linkgit:git-rev-parse[1]):
6364

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

67+
With the `--print` option, if 'refname' is acceptable, it prints the
68+
canonicalized name of a hypothetical reference with that name. That is,
69+
it prints 'refname' with any extra `/` characters removed.
70+
6671
With the `--branch` option, it expands the ``previous branch syntax''
6772
`@{-n}`. For example, `@{-1}` is a way to refer the last branch you
6873
were on. This option should be used by porcelains to accept this
6974
syntax anywhere a branch name is expected, so they can act as if you
7075
typed the branch name.
7176

72-
EXAMPLE
73-
-------
74-
75-
git check-ref-format --branch @{-1}::
76-
77-
Print the name of the previous branch.
77+
EXAMPLES
78+
--------
7879

80+
* Print the name of the previous branch:
81+
+
82+
------------
83+
$ git check-ref-format --branch @{-1}
84+
------------
85+
86+
* Determine the reference name to use for a new branch:
87+
+
88+
------------
89+
$ ref=$(git check-ref-format --print "refs/heads/$newbranch") ||
90+
die "we do not like '$newbranch' as a branch name."
91+
------------
7992

8093
GIT
8194
---

builtin-check-ref-format.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,28 @@
77
#include "builtin.h"
88
#include "strbuf.h"
99

10+
/*
11+
* Replace each run of adjacent slashes in src with a single slash,
12+
* and write the result to dst.
13+
*
14+
* This function is similar to normalize_path_copy(), but stripped down
15+
* to meet check_ref_format's simpler needs.
16+
*/
17+
static void collapse_slashes(char *dst, const char *src)
18+
{
19+
char ch;
20+
char prev = '\0';
21+
22+
while ((ch = *src++) != '\0') {
23+
if (prev == '/' && ch == prev)
24+
continue;
25+
26+
*dst++ = ch;
27+
prev = ch;
28+
}
29+
*dst = '\0';
30+
}
31+
1032
int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
1133
{
1234
if (argc == 3 && !strcmp(argv[1], "--branch")) {
@@ -17,6 +39,15 @@ int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
1739
printf("%s\n", sb.buf + 11);
1840
exit(0);
1941
}
42+
if (argc == 3 && !strcmp(argv[1], "--print")) {
43+
char *refname = xmalloc(strlen(argv[2]) + 1);
44+
45+
if (check_ref_format(argv[2]))
46+
exit(1);
47+
collapse_slashes(refname, argv[2]);
48+
printf("%s\n", refname);
49+
exit(0);
50+
}
2051
if (argc != 2)
2152
usage("git check-ref-format refname");
2253
return !!check_ref_format(argv[1]);

t/t1402-check-ref-format.sh

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#!/bin/sh
2+
3+
test_description='Test git check-ref-format'
4+
5+
. ./test-lib.sh
6+
7+
valid_ref() {
8+
test_expect_success "ref name '$1' is valid" \
9+
"git check-ref-format '$1'"
10+
}
11+
invalid_ref() {
12+
test_expect_success "ref name '$1' is not valid" \
13+
"test_must_fail git check-ref-format '$1'"
14+
}
15+
16+
valid_ref 'heads/foo'
17+
invalid_ref 'foo'
18+
valid_ref 'foo/bar/baz'
19+
valid_ref 'refs///heads/foo'
20+
invalid_ref 'heads/foo/'
21+
invalid_ref './foo'
22+
invalid_ref '.refs/foo'
23+
invalid_ref 'heads/foo..bar'
24+
invalid_ref 'heads/foo?bar'
25+
valid_ref 'foo./bar'
26+
invalid_ref 'heads/foo.lock'
27+
valid_ref 'heads/foo@bar'
28+
invalid_ref 'heads/v@{ation'
29+
invalid_ref 'heads/foo\bar'
30+
31+
test_expect_success "check-ref-format --branch @{-1}" '
32+
T=$(git write-tree) &&
33+
sha1=$(echo A | git commit-tree $T) &&
34+
git update-ref refs/heads/master $sha1 &&
35+
git update-ref refs/remotes/origin/master $sha1
36+
git checkout master &&
37+
git checkout origin/master &&
38+
git checkout master &&
39+
refname=$(git check-ref-format --branch @{-1}) &&
40+
test "$refname" = "$sha1" &&
41+
refname2=$(git check-ref-format --branch @{-2}) &&
42+
test "$refname2" = master'
43+
44+
valid_ref_normalized() {
45+
test_expect_success "ref name '$1' simplifies to '$2'" "
46+
refname=\$(git check-ref-format --print '$1') &&
47+
test \"\$refname\" = '$2'"
48+
}
49+
invalid_ref_normalized() {
50+
test_expect_success "check-ref-format --print rejects '$1'" "
51+
test_must_fail git check-ref-format --print '$1'"
52+
}
53+
54+
valid_ref_normalized 'heads/foo' 'heads/foo'
55+
valid_ref_normalized 'refs///heads/foo' 'refs/heads/foo'
56+
invalid_ref_normalized 'foo'
57+
invalid_ref_normalized 'heads/foo/../bar'
58+
invalid_ref_normalized 'heads/./foo'
59+
invalid_ref_normalized 'heads\foo'
60+
61+
test_done

0 commit comments

Comments
 (0)