rev-parse: add `--exclude-hidden=` option

Add a new `--exclude-hidden=` option that is similar to the one we just added to git-rev-list(1). Given a section name `uploadpack` or `receive` as argument, it causes us to exclude all references that would be hidden by the respective `$section.hideRefs` configuration. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Taylor Blau <me@ttaylorr.com>

Patrick Steinhardt committed Nov 17, 2022 at 06:47 UTC 5ff36c9b6bff6e0607ad50d212762ea019c85380
3 files changed +57
Documentation/git-rev-parse.txt
+7
@@ -197,6 +197,13 @@ respectively, and they must begin with `refs/` when applied to `--glob`
197 or `--all`. If a trailing '/{asterisk}' is intended, it must be given
198 explicitly.
199
200 +--exclude-hidden=[receive|uploadpack]::
201 + Do not include refs that would be hidden by `git-receive-pack` or
202 + `git-upload-pack` by consulting the appropriate `receive.hideRefs` or
203 + `uploadpack.hideRefs` configuration along with `transfer.hideRefs` (see
204 + linkgit:git-config[1]). This option affects the next pseudo-ref option
205 + `--all` or `--glob` and is cleared after processing them.
206 +
207 --disambiguate=<prefix>::
208 Show every object whose name begins with the given prefix.
209 The <prefix> must be at least 4 hexadecimal digits long to
builtin/rev-parse.c
+10
@@ -876,10 +876,14 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
876 continue;
877 }
878 if (opt_with_value(arg, "--branches", &arg)) {
879 + if (ref_excludes.hidden_refs_configured)
880 + return error(_("--exclude-hidden cannot be used together with --branches"));
881 handle_ref_opt(arg, "refs/heads/");
882 continue;
883 }
884 if (opt_with_value(arg, "--tags", &arg)) {
885 + if (ref_excludes.hidden_refs_configured)
886 + return error(_("--exclude-hidden cannot be used together with --tags"));
887 handle_ref_opt(arg, "refs/tags/");
888 continue;
889 }
@@ -888,6 +892,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
892 continue;
893 }
894 if (opt_with_value(arg, "--remotes", &arg)) {
895 + if (ref_excludes.hidden_refs_configured)
896 + return error(_("--exclude-hidden cannot be used together with --remotes"));
897 handle_ref_opt(arg, "refs/remotes/");
898 continue;
899 }
@@ -895,6 +901,10 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
901 add_ref_exclusion(&ref_excludes, arg);
902 continue;
903 }
904 + if (skip_prefix(arg, "--exclude-hidden=", &arg)) {
905 + exclude_hidden_refs(&ref_excludes, arg);
906 + continue;
907 + }
908 if (!strcmp(arg, "--show-toplevel")) {
909 const char *work_tree = get_git_work_tree();
910 if (work_tree)
t/t6018-rev-list-glob.sh
+40
@@ -187,6 +187,46 @@ test_expect_success 'rev-parse --exclude=ref with --remotes=glob' '
187 compare rev-parse "--exclude=upstream/x --remotes=upstream/*" "upstream/one upstream/two"
188 '
189
190 +for section in receive uploadpack
191 +do
192 + test_expect_success "rev-parse --exclude-hidden=$section with --all" '
193 + compare "-c transfer.hideRefs=refs/remotes/ rev-parse" "--branches --tags" "--exclude-hidden=$section --all"
194 + '
195 +
196 + test_expect_success "rev-parse --exclude-hidden=$section with --all" '
197 + compare "-c transfer.hideRefs=refs/heads/subspace/ rev-parse" "--exclude=refs/heads/subspace/* --all" "--exclude-hidden=$section --all"
198 + '
199 +
200 + test_expect_success "rev-parse --exclude-hidden=$section with --glob" '
201 + compare "-c transfer.hideRefs=refs/heads/subspace/ rev-parse" "--exclude=refs/heads/subspace/* --glob=refs/heads/*" "--exclude-hidden=$section --glob=refs/heads/*"
202 + '
203 +
204 + test_expect_success "rev-parse --exclude-hidden=$section can be passed once per pseudo-ref" '
205 + compare "-c transfer.hideRefs=refs/remotes/ rev-parse" "--branches --tags --branches --tags" "--exclude-hidden=$section --all --exclude-hidden=$section --all"
206 + '
207 +
208 + test_expect_success "rev-parse --exclude-hidden=$section can only be passed once per pseudo-ref" '
209 + echo "fatal: --exclude-hidden= passed more than once" >expected &&
210 + test_must_fail git rev-parse --exclude-hidden=$section --exclude-hidden=$section 2>err &&
211 + test_cmp expected err
212 + '
213 +
214 + for pseudoopt in branches tags remotes
215 + do
216 + test_expect_success "rev-parse --exclude-hidden=$section fails with --$pseudoopt" '
217 + echo "error: --exclude-hidden cannot be used together with --$pseudoopt" >expected &&
218 + test_must_fail git rev-parse --exclude-hidden=$section --$pseudoopt 2>err &&
219 + test_cmp expected err
220 + '
221 +
222 + test_expect_success "rev-parse --exclude-hidden=$section fails with --$pseudoopt=pattern" '
223 + echo "error: --exclude-hidden cannot be used together with --$pseudoopt" >expected &&
224 + test_must_fail git rev-parse --exclude-hidden=$section --$pseudoopt=pattern 2>err &&
225 + test_cmp expected err
226 + '
227 + done
228 +done
229 +
230 test_expect_success 'rev-list --exclude=glob with --branches=glob' '
231 compare rev-list "--exclude=subspace-* --branches=sub*" "subspace/one subspace/two"
232 '