Tighten refspec processing
This changes the pattern matching code to not store the required final / before the *, and then to require each side to be a valid ref (or empty). In particular, any refspec that looks like it should be a pattern but doesn't quite meet the requirements will be found to be invalid as a fallback non-pattern. Signed-off-by: Daniel Barkalow <barkalow@iabervon.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
parent
971f229c50
commit
ef00d150e4
47
remote.c
47
remote.c
|
@ -396,6 +396,7 @@ static void read_config(void)
|
||||||
struct refspec *parse_ref_spec(int nr_refspec, const char **refspec)
|
struct refspec *parse_ref_spec(int nr_refspec, const char **refspec)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
int st;
|
||||||
struct refspec *rs = xcalloc(sizeof(*rs), nr_refspec);
|
struct refspec *rs = xcalloc(sizeof(*rs), nr_refspec);
|
||||||
for (i = 0; i < nr_refspec; i++) {
|
for (i = 0; i < nr_refspec; i++) {
|
||||||
const char *sp, *ep, *gp;
|
const char *sp, *ep, *gp;
|
||||||
|
@ -404,13 +405,15 @@ struct refspec *parse_ref_spec(int nr_refspec, const char **refspec)
|
||||||
rs[i].force = 1;
|
rs[i].force = 1;
|
||||||
sp++;
|
sp++;
|
||||||
}
|
}
|
||||||
gp = strchr(sp, '*');
|
gp = strstr(sp, "/*");
|
||||||
ep = strchr(sp, ':');
|
ep = strchr(sp, ':');
|
||||||
if (gp && ep && gp > ep)
|
if (gp && ep && gp > ep)
|
||||||
gp = NULL;
|
gp = NULL;
|
||||||
if (ep) {
|
if (ep) {
|
||||||
if (ep[1]) {
|
if (ep[1]) {
|
||||||
const char *glob = strchr(ep + 1, '*');
|
const char *glob = strstr(ep + 1, "/*");
|
||||||
|
if (glob && glob[2])
|
||||||
|
glob = NULL;
|
||||||
if (!glob)
|
if (!glob)
|
||||||
gp = NULL;
|
gp = NULL;
|
||||||
if (gp)
|
if (gp)
|
||||||
|
@ -422,11 +425,24 @@ struct refspec *parse_ref_spec(int nr_refspec, const char **refspec)
|
||||||
} else {
|
} else {
|
||||||
ep = sp + strlen(sp);
|
ep = sp + strlen(sp);
|
||||||
}
|
}
|
||||||
|
if (gp && gp + 2 != ep)
|
||||||
|
gp = NULL;
|
||||||
if (gp) {
|
if (gp) {
|
||||||
rs[i].pattern = 1;
|
rs[i].pattern = 1;
|
||||||
ep = gp;
|
ep = gp;
|
||||||
}
|
}
|
||||||
rs[i].src = xstrndup(sp, ep - sp);
|
rs[i].src = xstrndup(sp, ep - sp);
|
||||||
|
|
||||||
|
if (*rs[i].src) {
|
||||||
|
st = check_ref_format(rs[i].src);
|
||||||
|
if (st && st != CHECK_REF_FORMAT_ONELEVEL)
|
||||||
|
die("Invalid refspec '%s'", refspec[i]);
|
||||||
|
}
|
||||||
|
if (rs[i].dst && *rs[i].dst) {
|
||||||
|
st = check_ref_format(rs[i].dst);
|
||||||
|
if (st && st != CHECK_REF_FORMAT_ONELEVEL)
|
||||||
|
die("Invalid refspec '%s'", refspec[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
@ -543,7 +559,8 @@ int remote_find_tracking(struct remote *remote, struct refspec *refspec)
|
||||||
if (!fetch->dst)
|
if (!fetch->dst)
|
||||||
continue;
|
continue;
|
||||||
if (fetch->pattern) {
|
if (fetch->pattern) {
|
||||||
if (!prefixcmp(needle, key)) {
|
if (!prefixcmp(needle, key) &&
|
||||||
|
needle[strlen(key)] == '/') {
|
||||||
*result = xmalloc(strlen(value) +
|
*result = xmalloc(strlen(value) +
|
||||||
strlen(needle) -
|
strlen(needle) -
|
||||||
strlen(key) + 1);
|
strlen(key) + 1);
|
||||||
|
@ -790,7 +807,9 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < rs_nr; i++) {
|
for (i = 0; i < rs_nr; i++) {
|
||||||
if (rs[i].pattern && !prefixcmp(src->name, rs[i].src))
|
if (rs[i].pattern &&
|
||||||
|
!prefixcmp(src->name, rs[i].src) &&
|
||||||
|
src->name[strlen(rs[i].src)] == '/')
|
||||||
return rs + i;
|
return rs + i;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -989,7 +1008,7 @@ int get_fetch_map(const struct ref *remote_refs,
|
||||||
struct ref ***tail,
|
struct ref ***tail,
|
||||||
int missing_ok)
|
int missing_ok)
|
||||||
{
|
{
|
||||||
struct ref *ref_map, *rm;
|
struct ref *ref_map, **rmp;
|
||||||
|
|
||||||
if (refspec->pattern) {
|
if (refspec->pattern) {
|
||||||
ref_map = get_expanded_map(remote_refs, refspec);
|
ref_map = get_expanded_map(remote_refs, refspec);
|
||||||
|
@ -1006,10 +1025,20 @@ int get_fetch_map(const struct ref *remote_refs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (rm = ref_map; rm; rm = rm->next) {
|
for (rmp = &ref_map; *rmp; ) {
|
||||||
if (rm->peer_ref && check_ref_format(rm->peer_ref->name + 5))
|
if ((*rmp)->peer_ref) {
|
||||||
die("* refusing to create funny ref '%s' locally",
|
int st = check_ref_format((*rmp)->peer_ref->name + 5);
|
||||||
rm->peer_ref->name);
|
if (st && st != CHECK_REF_FORMAT_ONELEVEL) {
|
||||||
|
struct ref *ignore = *rmp;
|
||||||
|
error("* Ignoring funny ref '%s' locally",
|
||||||
|
(*rmp)->peer_ref->name);
|
||||||
|
*rmp = (*rmp)->next;
|
||||||
|
free(ignore->peer_ref);
|
||||||
|
free(ignore);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rmp = &((*rmp)->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ref_map)
|
if (ref_map)
|
||||||
|
|
Loading…
Reference in New Issue