Merge branch 'jk/refspec-parse-wildcard'

Allow an asterisk as a substring (as opposed to the entirety) of
a path component for both side of a refspec, e.g.
"refs/heads/o*:refs/remotes/heads/i*".

* jk/refspec-parse-wildcard:
  refs: loosen restriction on wildcard "*" refspecs
  refs: cleanup comments regarding check_refname_component()
This commit is contained in:
Junio C Hamano 2015-08-03 11:01:31 -07:00
Родитель 7a06e63f82 cd377f45c9
Коммит 8d3981ccbe
5 изменённых файлов: 41 добавлений и 30 удалений

Просмотреть файл

@ -94,8 +94,8 @@ OPTIONS
Interpret <refname> as a reference name pattern for a refspec
(as used with remote repositories). If this option is
enabled, <refname> is allowed to contain a single `*`
in place of a one full pathname component (e.g.,
`foo/*/bar` but not `foo/bar*`).
in the refspec (e.g., `foo/bar*/baz` or `foo/bar*baz/`
but not `foo/bar*/baz*`).
--normalize::
Normalize 'refname' by removing any leading slash (`/`)

44
refs.c
Просмотреть файл

@ -19,12 +19,14 @@ struct ref_lock {
* 1: End-of-component
* 2: ., look for a preceding . to reject .. in refs
* 3: {, look for a preceding @ to reject @{ in refs
* 4: A bad character: ASCII control characters, "~", "^", ":" or SP
* 4: A bad character: ASCII control characters, and
* ":", "?", "[", "\", "^", "~", SP, or TAB
* 5: *, reject unless REFNAME_REFSPEC_PATTERN is set
*/
static unsigned char refname_disposition[256] = {
1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 2, 1,
4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 4, 0,
@ -75,12 +77,14 @@ static unsigned char refname_disposition[256] = {
*
* - any path component of it begins with ".", or
* - it has double dots "..", or
* - it has ASCII control character, "~", "^", ":" or SP, anywhere, or
* - it ends with a "/".
* - it ends with ".lock"
* - it contains a "\" (backslash)
* - it has ASCII control characters, or
* - it has ":", "?", "[", "\", "^", "~", SP, or TAB anywhere, or
* - it has "*" anywhere unless REFNAME_REFSPEC_PATTERN is set, or
* - it ends with a "/", or
* - it ends with ".lock", or
* - it contains a "@{" portion
*/
static int check_refname_component(const char *refname, int flags)
static int check_refname_component(const char *refname, int *flags)
{
const char *cp;
char last = '\0';
@ -101,6 +105,16 @@ static int check_refname_component(const char *refname, int flags)
break;
case 4:
return -1;
case 5:
if (!(*flags & REFNAME_REFSPEC_PATTERN))
return -1; /* refspec can't be a pattern */
/*
* Unset the pattern flag so that we only accept
* a single asterisk for one side of refspec.
*/
*flags &= ~ REFNAME_REFSPEC_PATTERN;
break;
}
last = ch;
}
@ -125,18 +139,10 @@ int check_refname_format(const char *refname, int flags)
while (1) {
/* We are at the start of a path component. */
component_len = check_refname_component(refname, flags);
if (component_len <= 0) {
if ((flags & REFNAME_REFSPEC_PATTERN) &&
refname[0] == '*' &&
(refname[1] == '\0' || refname[1] == '/')) {
/* Accept one wildcard as a full refname component. */
flags &= ~REFNAME_REFSPEC_PATTERN;
component_len = 1;
} else {
return -1;
}
}
component_len = check_refname_component(refname, &flags);
if (component_len <= 0)
return -1;
component_count++;
if (refname[component_len] == '\0')
break;

4
refs.h
Просмотреть файл

@ -279,8 +279,8 @@ extern int for_each_reflog(each_ref_fn, void *);
* to the rules described in Documentation/git-check-ref-format.txt.
* If REFNAME_ALLOW_ONELEVEL is set in flags, then accept one-level
* reference names. If REFNAME_REFSPEC_PATTERN is set in flags, then
* allow a "*" wildcard character in place of one of the name
* components. No leading or repeated slashes are accepted.
* allow a single "*" wildcard character in the refspec. No leading or
* repeated slashes are accepted.
*/
extern int check_refname_format(const char *refname, int flags);

Просмотреть файл

@ -62,9 +62,11 @@ invalid_ref 'heads/foo\bar'
invalid_ref "$(printf 'heads/foo\t')"
invalid_ref "$(printf 'heads/foo\177')"
valid_ref "$(printf 'heads/fu\303\237')"
invalid_ref 'heads/*foo/bar' --refspec-pattern
invalid_ref 'heads/foo*/bar' --refspec-pattern
invalid_ref 'heads/f*o/bar' --refspec-pattern
valid_ref 'heads/*foo/bar' --refspec-pattern
valid_ref 'heads/foo*/bar' --refspec-pattern
valid_ref 'heads/f*o/bar' --refspec-pattern
invalid_ref 'heads/f*o*/bar' --refspec-pattern
invalid_ref 'heads/foo*/bar*' --refspec-pattern
ref='foo'
invalid_ref "$ref"

Просмотреть файл

@ -71,15 +71,18 @@ test_refspec fetch ':refs/remotes/frotz/HEAD-to-me'
test_refspec push ':refs/remotes/frotz/delete me' invalid
test_refspec fetch ':refs/remotes/frotz/HEAD to me' invalid
test_refspec fetch 'refs/heads/*/for-linus:refs/remotes/mine/*-blah' invalid
test_refspec push 'refs/heads/*/for-linus:refs/remotes/mine/*-blah' invalid
test_refspec fetch 'refs/heads/*/for-linus:refs/remotes/mine/*-blah'
test_refspec push 'refs/heads/*/for-linus:refs/remotes/mine/*-blah'
test_refspec fetch 'refs/heads*/for-linus:refs/remotes/mine/*' invalid
test_refspec push 'refs/heads*/for-linus:refs/remotes/mine/*' invalid
test_refspec fetch 'refs/heads*/for-linus:refs/remotes/mine/*'
test_refspec push 'refs/heads*/for-linus:refs/remotes/mine/*'
test_refspec fetch 'refs/heads/*/*/for-linus:refs/remotes/mine/*' invalid
test_refspec push 'refs/heads/*/*/for-linus:refs/remotes/mine/*' invalid
test_refspec fetch 'refs/heads/*g*/for-linus:refs/remotes/mine/*' invalid
test_refspec push 'refs/heads/*g*/for-linus:refs/remotes/mine/*' invalid
test_refspec fetch 'refs/heads/*/for-linus:refs/remotes/mine/*'
test_refspec push 'refs/heads/*/for-linus:refs/remotes/mine/*'