diff --git a/Documentation/config.txt b/Documentation/config.txt index 448eb9d302..a7fbd0aac2 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -2540,6 +2540,11 @@ transfer.hideRefs:: excluded, and is hidden when responding to `git push` or `git fetch`. See `receive.hideRefs` and `uploadpack.hideRefs` for program-specific versions of this config. ++ +You may also include a `!` in front of the ref name to negate the entry, +explicitly exposing it, even if an earlier entry marked it as hidden. +If you have multiple hideRefs values, later entries override earlier ones +(and entries in more-specific config files override less-specific ones). transfer.unpackLimit:: When `fetch.unpackLimit` or `receive.unpackLimit` are diff --git a/refs.c b/refs.c index 7ac05cf21a..68f2cb03c4 100644 --- a/refs.c +++ b/refs.c @@ -4159,17 +4159,25 @@ int parse_hide_refs_config(const char *var, const char *value, const char *secti int ref_is_hidden(const char *refname) { - struct string_list_item *item; + int i; if (!hide_refs) return 0; - for_each_string_list_item(item, hide_refs) { + for (i = hide_refs->nr - 1; i >= 0; i--) { + const char *match = hide_refs->items[i].string; + int neg = 0; int len; - if (!starts_with(refname, item->string)) + + if (*match == '!') { + neg = 1; + match++; + } + + if (!starts_with(refname, match)) continue; - len = strlen(item->string); + len = strlen(match); if (!refname[len] || refname[len] == '/') - return 1; + return !neg; } return 0; } diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh index 3bd9759e0f..aadaac515e 100755 --- a/t/t5512-ls-remote.sh +++ b/t/t5512-ls-remote.sh @@ -128,6 +128,11 @@ test_expect_success 'Report match with --exit-code' ' test_cmp expect actual ' +test_expect_success 'set up some extra tags for ref hiding' ' + git tag magic/one && + git tag magic/two +' + for configsection in transfer uploadpack do test_expect_success "Hide some refs with $configsection.hiderefs" ' @@ -138,6 +143,24 @@ do sed -e "/ refs\/tags\//d" >expect && test_cmp expect actual ' + + test_expect_success "Override hiding of $configsection.hiderefs" ' + test_when_finished "test_unconfig $configsection.hiderefs" && + git config --add $configsection.hiderefs refs/tags && + git config --add $configsection.hiderefs "!refs/tags/magic" && + git config --add $configsection.hiderefs refs/tags/magic/one && + git ls-remote . >actual && + grep refs/tags/magic/two actual && + ! grep refs/tags/magic/one actual + ' + done +test_expect_success 'overrides work between mixed transfer/upload-pack hideRefs' ' + test_config uploadpack.hiderefs refs/tags && + test_config transfer.hiderefs "!refs/tags/magic" && + git ls-remote . >actual && + grep refs/tags/magic actual +' + test_done