diff options
author | Junio C Hamano <gitster@pobox.com> | 2020-10-05 14:01:54 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2020-10-05 14:01:54 -0700 |
commit | 8e3ec76a20d6abf5dd8ceb3f5f2c157000e4c13e (patch) | |
tree | 816c5dc42c7dc8cac732c804b8e99775806bb5dc /refspec.c | |
parent | f6b06b459092520bd90e5a191589e2d4371ef7d1 (diff) | |
parent | c0192df6306d4d9ad77f6015a053925b13155834 (diff) | |
download | git-8e3ec76a20d6abf5dd8ceb3f5f2c157000e4c13e.tar.gz |
Merge branch 'jk/refspecs-negative'
"git fetch" and "git push" support negative refspecs.
* jk/refspecs-negative:
refspec: add support for negative refspecs
Diffstat (limited to 'refspec.c')
-rw-r--r-- | refspec.c | 34 |
1 files changed, 32 insertions, 2 deletions
@@ -8,6 +8,7 @@ static struct refspec_item s_tag_refspec = { 1, 0, 0, + 0, "refs/tags/*", "refs/tags/*" }; @@ -32,10 +33,17 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet if (*lhs == '+') { item->force = 1; lhs++; + } else if (*lhs == '^') { + item->negative = 1; + lhs++; } rhs = strrchr(lhs, ':'); + /* negative refspecs only have one side */ + if (item->negative && rhs) + return 0; + /* * Before going on, special case ":" (or "+:") as a refspec * for pushing matching refs. @@ -55,7 +63,7 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet llen = (rhs ? (rhs - lhs - 1) : strlen(lhs)); if (1 <= llen && memchr(lhs, '*', llen)) { - if ((rhs && !is_glob) || (!rhs && fetch)) + if ((rhs && !is_glob) || (!rhs && !item->negative && fetch)) return 0; is_glob = 1; } else if (rhs && is_glob) { @@ -66,6 +74,28 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet item->src = xstrndup(lhs, llen); flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0); + if (item->negative) { + struct object_id unused; + + /* + * Negative refspecs only have a LHS, which indicates a ref + * (or pattern of refs) to exclude from other matches. This + * can either be a simple ref, or a glob pattern. Exact sha1 + * match is not currently supported. + */ + if (!*item->src) + return 0; /* negative refspecs must not be empty */ + else if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused)) + return 0; /* negative refpsecs cannot be exact sha1 */ + else if (!check_refname_format(item->src, flags)) + ; /* valid looking ref is ok */ + else + return 0; + + /* the other rules below do not apply to negative refspecs */ + return 1; + } + if (fetch) { struct object_id unused; @@ -223,7 +253,7 @@ void refspec_ref_prefixes(const struct refspec *rs, const struct refspec_item *item = &rs->items[i]; const char *prefix = NULL; - if (item->exact_sha1) + if (item->exact_sha1 || item->negative) continue; if (rs->fetch == REFSPEC_FETCH) prefix = item->src; |