зеркало из https://github.com/microsoft/git.git
Support '*' in the middle of a refspec
In order to keep the requirements strict, each * has to be a full path component, and there may only be one * per side. This requirement is enforced entirely by check_ref_format(); the matching implementation will substitute the whatever matches the * in the lhs for the * in the rhs. Signed-off-by: Daniel Barkalow <barkalow@iabervon.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
08fbdb3043
Коммит
abd2bde78b
11
refs.c
11
refs.c
|
@ -694,6 +694,7 @@ static inline int bad_ref_char(int ch)
|
|||
int check_ref_format(const char *ref)
|
||||
{
|
||||
int ch, level, bad_type;
|
||||
int ret = CHECK_REF_FORMAT_OK;
|
||||
const char *cp = ref;
|
||||
|
||||
level = 0;
|
||||
|
@ -709,9 +710,11 @@ int check_ref_format(const char *ref)
|
|||
return CHECK_REF_FORMAT_ERROR;
|
||||
bad_type = bad_ref_char(ch);
|
||||
if (bad_type) {
|
||||
return (bad_type == 2 && !*cp)
|
||||
? CHECK_REF_FORMAT_WILDCARD
|
||||
: CHECK_REF_FORMAT_ERROR;
|
||||
if (bad_type == 2 && (!*cp || *cp == '/') &&
|
||||
ret == CHECK_REF_FORMAT_OK)
|
||||
ret = CHECK_REF_FORMAT_WILDCARD;
|
||||
else
|
||||
return CHECK_REF_FORMAT_ERROR;
|
||||
}
|
||||
|
||||
/* scan the rest of the path component */
|
||||
|
@ -729,7 +732,7 @@ int check_ref_format(const char *ref)
|
|||
if (!ch) {
|
||||
if (level < 2)
|
||||
return CHECK_REF_FORMAT_ONELEVEL;
|
||||
return CHECK_REF_FORMAT_OK;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
24
remote.c
24
remote.c
|
@ -511,12 +511,12 @@ static struct refspec *parse_refspec_internal(int nr_refspec, const char **refsp
|
|||
|
||||
if (rhs) {
|
||||
size_t rlen = strlen(++rhs);
|
||||
is_glob = (2 <= rlen && !strcmp(rhs + rlen - 2, "/*"));
|
||||
is_glob = (1 <= rlen && strchr(rhs, '*'));
|
||||
rs[i].dst = xstrndup(rhs, rlen);
|
||||
}
|
||||
|
||||
llen = (rhs ? (rhs - lhs - 1) : strlen(lhs));
|
||||
if (2 <= llen && !memcmp(lhs + llen - 2, "/*", 2)) {
|
||||
if (1 <= llen && memchr(lhs, '*', llen)) {
|
||||
if ((rhs && !is_glob) || (!rhs && fetch))
|
||||
goto invalid;
|
||||
is_glob = 1;
|
||||
|
@ -718,22 +718,32 @@ static int match_name_with_pattern(const char *key, const char *name,
|
|||
{
|
||||
const char *kstar = strchr(key, '*');
|
||||
size_t klen;
|
||||
size_t ksuffixlen;
|
||||
size_t namelen;
|
||||
int ret;
|
||||
if (!kstar)
|
||||
die("Key '%s' of pattern had no '*'", key);
|
||||
klen = kstar - key;
|
||||
ret = !strncmp(key, name, klen);
|
||||
ksuffixlen = strlen(kstar + 1);
|
||||
namelen = strlen(name);
|
||||
ret = !strncmp(name, key, klen) && namelen >= klen + ksuffixlen &&
|
||||
!memcmp(name + namelen - ksuffixlen, kstar + 1, ksuffixlen);
|
||||
if (ret && value) {
|
||||
const char *vstar = strchr(value, '*');
|
||||
size_t vlen;
|
||||
size_t vsuffixlen;
|
||||
if (!vstar)
|
||||
die("Value '%s' of pattern has no '*'", value);
|
||||
vlen = vstar - value;
|
||||
*result = xmalloc(vlen +
|
||||
vsuffixlen = strlen(vstar + 1);
|
||||
*result = xmalloc(vlen + vsuffixlen +
|
||||
strlen(name) -
|
||||
klen + 1);
|
||||
strcpy(*result, value);
|
||||
strcpy(*result + vlen, name + klen);
|
||||
klen - ksuffixlen + 1);
|
||||
strncpy(*result, value, vlen);
|
||||
strncpy(*result + vlen,
|
||||
name + klen, namelen - klen - ksuffixlen);
|
||||
strcpy(*result + vlen + namelen - klen - ksuffixlen,
|
||||
vstar + 1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -72,4 +72,16 @@ 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/*' invalid
|
||||
test_refspec push 'refs/heads*/for-linus:refs/remotes/mine/*' invalid
|
||||
|
||||
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_done
|
||||
|
|
Загрузка…
Ссылка в новой задаче