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 /remote.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 'remote.c')
-rw-r--r-- | remote.c | 108 |
1 files changed, 104 insertions, 4 deletions
@@ -682,6 +682,91 @@ static int match_name_with_pattern(const char *key, const char *name, return ret; } +static int refspec_match(const struct refspec_item *refspec, + const char *name) +{ + if (refspec->pattern) + return match_name_with_pattern(refspec->src, name, NULL, NULL); + + return !strcmp(refspec->src, name); +} + +static int omit_name_by_refspec(const char *name, struct refspec *rs) +{ + int i; + + for (i = 0; i < rs->nr; i++) { + if (rs->items[i].negative && refspec_match(&rs->items[i], name)) + return 1; + } + return 0; +} + +struct ref *apply_negative_refspecs(struct ref *ref_map, struct refspec *rs) +{ + struct ref **tail; + + for (tail = &ref_map; *tail; ) { + struct ref *ref = *tail; + + if (omit_name_by_refspec(ref->name, rs)) { + *tail = ref->next; + free(ref->peer_ref); + free(ref); + } else + tail = &ref->next; + } + + return ref_map; +} + +static int query_matches_negative_refspec(struct refspec *rs, struct refspec_item *query) +{ + int i, matched_negative = 0; + int find_src = !query->src; + struct string_list reversed = STRING_LIST_INIT_NODUP; + const char *needle = find_src ? query->dst : query->src; + + /* + * Check whether the queried ref matches any negative refpsec. If so, + * then we should ultimately treat this as not matching the query at + * all. + * + * Note that negative refspecs always match the source, but the query + * item uses the destination. To handle this, we apply pattern + * refspecs in reverse to figure out if the query source matches any + * of the negative refspecs. + */ + for (i = 0; i < rs->nr; i++) { + struct refspec_item *refspec = &rs->items[i]; + char *expn_name; + + if (refspec->negative) + continue; + + /* Note the reversal of src and dst */ + if (refspec->pattern) { + const char *key = refspec->dst ? refspec->dst : refspec->src; + const char *value = refspec->src; + + if (match_name_with_pattern(key, needle, value, &expn_name)) + string_list_append_nodup(&reversed, expn_name); + } else { + if (!strcmp(needle, refspec->src)) + string_list_append(&reversed, refspec->src); + } + } + + for (i = 0; !matched_negative && i < reversed.nr; i++) { + if (omit_name_by_refspec(reversed.items[i].string, rs)) + matched_negative = 1; + } + + string_list_clear(&reversed, 0); + + return matched_negative; +} + static void query_refspecs_multiple(struct refspec *rs, struct refspec_item *query, struct string_list *results) @@ -692,6 +777,9 @@ static void query_refspecs_multiple(struct refspec *rs, if (find_src && !query->dst) BUG("query_refspecs_multiple: need either src or dst"); + if (query_matches_negative_refspec(rs, query)) + return; + for (i = 0; i < rs->nr; i++) { struct refspec_item *refspec = &rs->items[i]; const char *key = find_src ? refspec->dst : refspec->src; @@ -699,7 +787,7 @@ static void query_refspecs_multiple(struct refspec *rs, const char *needle = find_src ? query->dst : query->src; char **result = find_src ? &query->src : &query->dst; - if (!refspec->dst) + if (!refspec->dst || refspec->negative) continue; if (refspec->pattern) { if (match_name_with_pattern(key, needle, value, result)) @@ -720,12 +808,15 @@ int query_refspecs(struct refspec *rs, struct refspec_item *query) if (find_src && !query->dst) BUG("query_refspecs: need either src or dst"); + if (query_matches_negative_refspec(rs, query)) + return -1; + for (i = 0; i < rs->nr; i++) { struct refspec_item *refspec = &rs->items[i]; const char *key = find_src ? refspec->dst : refspec->src; const char *value = find_src ? refspec->src : refspec->dst; - if (!refspec->dst) + if (!refspec->dst || refspec->negative) continue; if (refspec->pattern) { if (match_name_with_pattern(key, needle, value, result)) { @@ -1054,7 +1145,7 @@ static int match_explicit(struct ref *src, struct ref *dst, const char *dst_value = rs->dst; char *dst_guess; - if (rs->pattern || rs->matching) + if (rs->pattern || rs->matching || rs->negative) return 0; matched_src = matched_dst = NULL; @@ -1130,6 +1221,10 @@ static char *get_ref_match(const struct refspec *rs, const struct ref *ref, int matching_refs = -1; for (i = 0; i < rs->nr; i++) { const struct refspec_item *item = &rs->items[i]; + + if (item->negative) + continue; + if (item->matching && (matching_refs == -1 || item->force)) { matching_refs = i; @@ -1335,7 +1430,7 @@ int check_push_refs(struct ref *src, struct refspec *rs) for (i = 0; i < rs->nr; i++) { struct refspec_item *item = &rs->items[i]; - if (item->pattern || item->matching) + if (item->pattern || item->matching || item->negative) continue; ret |= match_explicit_lhs(src, item, NULL, NULL); @@ -1437,6 +1532,8 @@ int match_push_refs(struct ref *src, struct ref **dst, string_list_clear(&src_ref_index, 0); } + *dst = apply_negative_refspecs(*dst, rs); + if (errs) return -1; return 0; @@ -1806,6 +1903,9 @@ int get_fetch_map(const struct ref *remote_refs, { struct ref *ref_map, **rmp; + if (refspec->negative) + return 0; + if (refspec->pattern) { ref_map = get_expanded_map(remote_refs, refspec); } else { |