]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'ds/bundle-uri-3'
authorTaylor Blau <me@ttaylorr.com>
Mon, 31 Oct 2022 01:04:43 +0000 (21:04 -0400)
committerTaylor Blau <me@ttaylorr.com>
Mon, 31 Oct 2022 01:04:44 +0000 (21:04 -0400)
Define the logical elements of a "bundle list", data structure to
store them in-core, format to transfer them, and code to parse
them.

* ds/bundle-uri-3:
  bundle-uri: suppress stderr from remote-https
  bundle-uri: quiet failed unbundlings
  bundle: add flags to verify_bundle()
  bundle-uri: fetch a list of bundles
  bundle: properly clear all revision flags
  bundle-uri: limit recursion depth for bundle lists
  bundle-uri: parse bundle list in config format
  bundle-uri: unit test "key=value" parsing
  bundle-uri: create "key=value" line parsing
  bundle-uri: create base key-value pair parsing
  bundle-uri: create bundle_list struct and helpers
  bundle-uri: use plain string in find_temp_filename()

1  2 
Documentation/config.txt
Makefile
builtin/bundle.c
bundle.h
config.c
t/helper/test-tool.c
t/helper/test-tool.h
t/test-lib-functions.sh
transport.c

diff --combined Documentation/config.txt
index 1e205831656711e898dac1c33da753066e621088,4f9002efd6db098e43c86a6b780fdf94aa34aeb7..0e93aef86264dbe5c7af33e66a13778c160b24ba
@@@ -387,6 -387,8 +387,8 @@@ include::config/branch.txt[
  
  include::config/browser.txt[]
  
+ include::config/bundle.txt[]
  include::config/checkout.txt[]
  
  include::config/clean.txt[]
@@@ -423,8 -425,6 +425,8 @@@ include::config/filter.txt[
  
  include::config/fsck.txt[]
  
 +include::config/fsmonitor--daemon.txt[]
 +
  include::config/gc.txt[]
  
  include::config/gitcvs.txt[]
diff --combined Makefile
index 7eab944a63349d799ec5c998588ca137b7274407,4a19d9cb728ebdbb9f924f38637a5fa4add39754..4927379184cf9edb7ebc883c5ef40accea130232
+++ b/Makefile
@@@ -155,6 -155,9 +155,6 @@@ include shared.ma
  # Define BLK_SHA1 environment variable to make use of the bundled
  # optimized C SHA1 routine.
  #
 -# Define PPC_SHA1 environment variable when running make to make use of
 -# a bundled SHA1 routine optimized for PowerPC.
 -#
  # Define DC_SHA1 to unconditionally enable the collision-detecting sha1
  # algorithm. This is slower, but may detect attempted collision attacks.
  # Takes priority over other *_SHA1 knobs.
@@@ -529,9 -532,8 +529,9 @@@ GIT-VERSION-FILE: FORC
  #   template_dir
  #   sysconfdir
  # can be specified as a relative path some/where/else;
 -# this is interpreted as relative to $(prefix) and "git" at
 -# runtime figures out where they are based on the path to the executable.
 +# this is interpreted as relative to $(prefix) and "git" built with
 +# RUNTIME_PREFIX flag will figure out (at runtime) where they are
 +# based on the path to the executable.
  # Additionally, the following will be treated as relative by "git" if they
  # begin with "$(prefix)/":
  #   mandir
@@@ -606,9 -608,7 +606,9 @@@ FUZZ_OBJS 
  FUZZ_PROGRAMS =
  GIT_OBJS =
  LIB_OBJS =
 +SCALAR_OBJS =
  OBJECTS =
 +OTHER_PROGRAMS =
  PROGRAM_OBJS =
  PROGRAMS =
  EXCLUDED_PROGRAMS =
@@@ -689,9 -689,9 +689,9 @@@ SCRIPTS = $(SCRIPT_SH_GEN) 
  
  ETAGS_TARGET = TAGS
  
 -FUZZ_OBJS += fuzz-commit-graph.o
 -FUZZ_OBJS += fuzz-pack-headers.o
 -FUZZ_OBJS += fuzz-pack-idx.o
 +FUZZ_OBJS += oss-fuzz/fuzz-commit-graph.o
 +FUZZ_OBJS += oss-fuzz/fuzz-pack-headers.o
 +FUZZ_OBJS += oss-fuzz/fuzz-pack-idx.o
  .PHONY: fuzz-objs
  fuzz-objs: $(FUZZ_OBJS)
  
@@@ -722,6 -722,7 +722,7 @@@ PROGRAMS += $(patsubst %.o,git-%$X,$(PR
  TEST_BUILTINS_OBJS += test-advise.o
  TEST_BUILTINS_OBJS += test-bitmap.o
  TEST_BUILTINS_OBJS += test-bloom.o
+ TEST_BUILTINS_OBJS += test-bundle-uri.o
  TEST_BUILTINS_OBJS += test-chmtime.o
  TEST_BUILTINS_OBJS += test-config.o
  TEST_BUILTINS_OBJS += test-crontab.o
@@@ -772,7 -773,6 +773,7 @@@ TEST_BUILTINS_OBJS += test-read-midx.
  TEST_BUILTINS_OBJS += test-ref-store.o
  TEST_BUILTINS_OBJS += test-reftable.o
  TEST_BUILTINS_OBJS += test-regex.o
 +TEST_BUILTINS_OBJS += test-rot13-filter.o
  TEST_BUILTINS_OBJS += test-repository.o
  TEST_BUILTINS_OBJS += test-revision-walking.o
  TEST_BUILTINS_OBJS += test-run-command.o
@@@ -786,7 -786,6 +787,7 @@@ TEST_BUILTINS_OBJS += test-strcmp-offse
  TEST_BUILTINS_OBJS += test-string-list.o
  TEST_BUILTINS_OBJS += test-submodule-config.o
  TEST_BUILTINS_OBJS += test-submodule-nested-repo-config.o
 +TEST_BUILTINS_OBJS += test-submodule.o
  TEST_BUILTINS_OBJS += test-subprocess.o
  TEST_BUILTINS_OBJS += test-trace2.o
  TEST_BUILTINS_OBJS += test-urlmatch-normalization.o
@@@ -819,16 -818,13 +820,16 @@@ BUILT_INS += git-show$
  BUILT_INS += git-stage$X
  BUILT_INS += git-status$X
  BUILT_INS += git-switch$X
 +BUILT_INS += git-version$X
  BUILT_INS += git-whatchanged$X
  
  # what 'all' will build but not install in gitexecdir
 -OTHER_PROGRAMS = git$X
 +OTHER_PROGRAMS += git$X
 +OTHER_PROGRAMS += scalar$X
  
  # what test wrappers are needed and 'install' will install, in bindir
  BINDIR_PROGRAMS_NEED_X += git
 +BINDIR_PROGRAMS_NEED_X += scalar
  BINDIR_PROGRAMS_NEED_X += git-receive-pack
  BINDIR_PROGRAMS_NEED_X += git-shell
  BINDIR_PROGRAMS_NEED_X += git-upload-archive
@@@ -924,7 -920,6 +925,7 @@@ LIB_OBJS += combine-diff.
  LIB_OBJS += commit-graph.o
  LIB_OBJS += commit-reach.o
  LIB_OBJS += commit.o
 +LIB_OBJS += compat/nonblock.o
  LIB_OBJS += compat/obstack.o
  LIB_OBJS += compat/terminal.o
  LIB_OBJS += compat/zlib-uncompress2.o
@@@ -939,7 -934,6 +940,7 @@@ LIB_OBJS += ctype.
  LIB_OBJS += date.o
  LIB_OBJS += decorate.o
  LIB_OBJS += delta-islands.o
 +LIB_OBJS += diagnose.o
  LIB_OBJS += diff-delta.o
  LIB_OBJS += diff-merges.o
  LIB_OBJS += diff-lib.o
@@@ -1095,7 -1089,6 +1096,7 @@@ LIB_OBJS += trace.
  LIB_OBJS += trace2.o
  LIB_OBJS += trace2/tr2_cfg.o
  LIB_OBJS += trace2/tr2_cmd_name.o
 +LIB_OBJS += trace2/tr2_ctr.o
  LIB_OBJS += trace2/tr2_dst.o
  LIB_OBJS += trace2/tr2_sid.o
  LIB_OBJS += trace2/tr2_sysenv.o
@@@ -1104,7 -1097,6 +1105,7 @@@ LIB_OBJS += trace2/tr2_tgt_event.
  LIB_OBJS += trace2/tr2_tgt_normal.o
  LIB_OBJS += trace2/tr2_tgt_perf.o
  LIB_OBJS += trace2/tr2_tls.o
 +LIB_OBJS += trace2/tr2_tmr.o
  LIB_OBJS += trailer.o
  LIB_OBJS += transport-helper.o
  LIB_OBJS += transport.o
@@@ -1162,7 -1154,6 +1163,7 @@@ BUILTIN_OBJS += builtin/credential-cach
  BUILTIN_OBJS += builtin/credential-store.o
  BUILTIN_OBJS += builtin/credential.o
  BUILTIN_OBJS += builtin/describe.o
 +BUILTIN_OBJS += builtin/diagnose.o
  BUILTIN_OBJS += builtin/diff-files.o
  BUILTIN_OBJS += builtin/diff-index.o
  BUILTIN_OBJS += builtin/diff-tree.o
@@@ -1341,7 -1332,6 +1342,7 @@@ BASIC_CFLAGS += -DSHA1DC_FORCE_ALIGNED_
  endif
  ifneq ($(filter leak,$(SANITIZERS)),)
  BASIC_CFLAGS += -DSUPPRESS_ANNOTATED_LEAKS
 +BASIC_CFLAGS += -O0
  SANITIZE_LEAK = YesCompiledWithIt
  endif
  ifneq ($(filter address,$(SANITIZERS)),)
@@@ -1446,6 -1436,7 +1447,6 @@@ ifeq ($(uname_S),Darwin
                APPLE_COMMON_CRYPTO = YesPlease
                COMPAT_CFLAGS += -DAPPLE_COMMON_CRYPTO
        endif
 -      NO_REGEX = YesPlease
        PTHREAD_LIBS =
  endif
  
@@@ -1809,10 -1800,6 +1810,10 @@@ ifdef APPLE_COMMON_CRYPT
        SHA1_MAX_BLOCK_SIZE = 1024L*1024L*1024L
  endif
  
 +ifdef PPC_SHA1
 +$(error the PPC_SHA1 flag has been removed along with the PowerPC-specific SHA-1 implementation.)
 +endif
 +
  ifdef OPENSSL_SHA1
        EXTLIBS += $(LIB_4_CRYPTO)
        BASIC_CFLAGS += -DSHA1_OPENSSL
@@@ -1821,6 -1808,10 +1822,6 @@@ ifdef BLK_SHA
        LIB_OBJS += block-sha1/sha1.o
        BASIC_CFLAGS += -DSHA1_BLK
  else
 -ifdef PPC_SHA1
 -      LIB_OBJS += ppc/sha1.o ppc/sha1ppc.o
 -      BASIC_CFLAGS += -DSHA1_PPC
 -else
  ifdef APPLE_COMMON_CRYPTO
        COMPAT_CFLAGS += -DCOMMON_DIGEST_FOR_OPENSSL
        BASIC_CFLAGS += -DSHA1_APPLE
@@@ -1854,6 -1845,7 +1855,6 @@@ endi
  endif
  endif
  endif
 -endif
  
  ifdef OPENSSL_SHA256
        EXTLIBS += $(LIB_4_CRYPTO)
@@@ -2042,13 -2034,11 +2043,13 @@@ ifdef FSMONITOR_DAEMON_BACKEN
        COMPAT_CFLAGS += -DHAVE_FSMONITOR_DAEMON_BACKEND
        COMPAT_OBJS += compat/fsmonitor/fsm-listen-$(FSMONITOR_DAEMON_BACKEND).o
        COMPAT_OBJS += compat/fsmonitor/fsm-health-$(FSMONITOR_DAEMON_BACKEND).o
 +      COMPAT_OBJS += compat/fsmonitor/fsm-ipc-$(FSMONITOR_DAEMON_BACKEND).o
  endif
  
  ifdef FSMONITOR_OS_SETTINGS
        COMPAT_CFLAGS += -DHAVE_FSMONITOR_OS_SETTINGS
        COMPAT_OBJS += compat/fsmonitor/fsm-settings-$(FSMONITOR_OS_SETTINGS).o
 +      COMPAT_OBJS += compat/fsmonitor/fsm-path-utils-$(FSMONITOR_OS_SETTINGS).o
  endif
  
  ifeq ($(TCLTK_PATH),)
@@@ -2230,7 -2220,7 +2231,7 @@@ profile-fast: profile-clea
  
  all:: $(ALL_COMMANDS_TO_INSTALL) $(SCRIPT_LIB) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS
  ifneq (,$X)
 -      $(QUIET_BUILT_IN)$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_COMMANDS_TO_INSTALL) git$X)), test -d '$p' -o '$p' -ef '$p$X' || $(RM) '$p';)
 +      $(QUIET_BUILT_IN)$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_COMMANDS_TO_INSTALL) $(OTHER_PROGRAMS))), test -d '$p' -o '$p' -ef '$p$X' || $(RM) '$p';)
  endif
  
  all::
@@@ -2553,12 -2543,7 +2554,12 @@@ GIT_OBJS += git.
  .PHONY: git-objs
  git-objs: $(GIT_OBJS)
  
 +SCALAR_OBJS += scalar.o
 +.PHONY: scalar-objs
 +scalar-objs: $(SCALAR_OBJS)
 +
  OBJECTS += $(GIT_OBJS)
 +OBJECTS += $(SCALAR_OBJS)
  OBJECTS += $(PROGRAM_OBJS)
  OBJECTS += $(TEST_OBJS)
  OBJECTS += $(XDIFF_OBJS)
@@@ -2569,6 -2554,10 +2570,6 @@@ ifndef NO_CUR
        OBJECTS += http.o http-walker.o remote-curl.o
  endif
  
 -SCALAR_SOURCES := contrib/scalar/scalar.c
 -SCALAR_OBJECTS := $(SCALAR_SOURCES:c=o)
 -OBJECTS += $(SCALAR_OBJECTS)
 -
  .PHONY: objects
  objects: $(OBJECTS)
  
@@@ -2603,7 -2592,13 +2604,7 @@@ missing_compdb_dir 
  compdb_args =
  endif
  
 -ASM_SRC := $(wildcard $(OBJECTS:o=S))
 -ASM_OBJ := $(ASM_SRC:S=o)
 -C_OBJ := $(filter-out $(ASM_OBJ),$(OBJECTS))
 -
 -$(C_OBJ): %.o: %.c GIT-CFLAGS $(missing_dep_dirs) $(missing_compdb_dir)
 -      $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(compdb_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
 -$(ASM_OBJ): %.o: %.S GIT-CFLAGS $(missing_dep_dirs) $(missing_compdb_dir)
 +$(OBJECTS): %.o: %.c GIT-CFLAGS $(missing_dep_dirs) $(missing_compdb_dir)
        $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(compdb_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
  
  %.s: %.c GIT-CFLAGS FORCE
@@@ -2694,7 -2689,7 +2695,7 @@@ $(REMOTE_CURL_PRIMARY): remote-curl.o h
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
                $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) $(LIBS)
  
 -contrib/scalar/scalar$X: $(SCALAR_OBJECTS) GIT-LDFLAGS $(GITLIBS)
 +scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \
                $(filter %.o,$^) $(LIBS)
  
@@@ -2750,7 -2745,8 +2751,7 @@@ XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) -
  XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --language=Perl \
        --keyword=__ --keyword=N__ --keyword="__n:1,2"
  MSGMERGE_FLAGS = --add-location --backup=off --update
 -LOCALIZED_C = $(sort $(FOUND_C_SOURCES) $(FOUND_H_SOURCES) $(SCALAR_SOURCES) \
 -              $(GENERATED_H))
 +LOCALIZED_C = $(sort $(FOUND_C_SOURCES) $(FOUND_H_SOURCES) $(GENERATED_H))
  LOCALIZED_SH = $(sort $(SCRIPT_SH) git-sh-setup.sh)
  LOCALIZED_PERL = $(sort $(SCRIPT_PERL))
  
@@@ -2985,7 -2981,6 +2986,7 @@@ GIT-BUILD-OPTIONS: FORC
        @echo NO_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@+
        @echo NO_PTHREADS=\''$(subst ','\'',$(subst ','\'',$(NO_PTHREADS)))'\' >>$@+
        @echo NO_PYTHON=\''$(subst ','\'',$(subst ','\'',$(NO_PYTHON)))'\' >>$@+
 +      @echo NO_REGEX=\''$(subst ','\'',$(subst ','\'',$(NO_REGEX)))'\' >>$@+
        @echo NO_UNIX_SOCKETS=\''$(subst ','\'',$(subst ','\'',$(NO_UNIX_SOCKETS)))'\' >>$@+
        @echo PAGER_ENV=\''$(subst ','\'',$(subst ','\'',$(PAGER_ENV)))'\' >>$@+
        @echo DC_SHA1=\''$(subst ','\'',$(subst ','\'',$(DC_SHA1)))'\' >>$@+
@@@ -3044,7 -3039,6 +3045,7 @@@ els
        @echo RUNTIME_PREFIX=\'false\' >>$@+
  endif
        @if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi
 +      @if test -f GIT-BUILD-DIR; then rm GIT-BUILD-DIR; fi
  
  ### Detect Python interpreter path changes
  ifndef NO_PYTHON
@@@ -3066,7 -3060,7 +3067,7 @@@ bin-wrappers/%: wrap-for-bin.s
        $(call mkdir_p_parent_template)
        $(QUIET_GEN)sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
             -e 's|@@BUILD_DIR@@|$(shell pwd)|' \
 -           -e 's|@@PROG@@|$(patsubst test-%,t/helper/test-%$(X),$(@F))$(patsubst git%,$(X),$(filter $(@F),$(BINDIR_PROGRAMS_NEED_X)))|' < $< > $@ && \
 +           -e 's|@@PROG@@|$(patsubst test-%,t/helper/test-%,$(@F))$(if $(filter-out $(BINDIR_PROGRAMS_NO_X),$(@F)),$(X),)|' < $< > $@ && \
        chmod +x $@
  
  # GNU make supports exporting all variables by "export" without parameters.
@@@ -3096,7 -3090,7 +3097,7 @@@ t/helper/test-%$X: t/helper/test-%.o GI
  check-sha1:: t/helper/test-tool$X
        t/helper/test-sha1.sh
  
 -SP_OBJ = $(patsubst %.o,%.sp,$(C_OBJ))
 +SP_OBJ = $(patsubst %.o,%.sp,$(OBJECTS))
  
  $(SP_OBJ): %.sp: %.c %.o
        $(QUIET_SP)cgcc -no-compile $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) \
@@@ -3280,14 -3274,14 +3281,14 @@@ ifndef NO_TCLT
        $(MAKE) -C git-gui gitexecdir='$(gitexec_instdir_SQ)' install
  endif
  ifneq (,$X)
 -      $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_COMMANDS_TO_INSTALL) git$X)), test '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p' -ef '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p$X' || $(RM) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p';)
 +      $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_COMMANDS_TO_INSTALL) $(OTHER_PROGRAMS))), test '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p' -ef '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p$X' || $(RM) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p';)
  endif
  
        bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \
        execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \
        destdir_from_execdir_SQ=$$(echo '$(gitexecdir_relative_SQ)' | sed -e 's|[^/][^/]*|..|g') && \
        { test "$$bindir/" = "$$execdir/" || \
 -        for p in git$X $(filter $(install_bindir_programs),$(ALL_PROGRAMS)); do \
 +        for p in $(OTHER_PROGRAMS) $(filter $(install_bindir_programs),$(ALL_PROGRAMS)); do \
                $(RM) "$$execdir/$$p" && \
                test -n "$(INSTALL_SYMLINKS)" && \
                ln -s "$$destdir_from_execdir_SQ/$(bindir_relative_SQ)/$$p" "$$execdir/$$p" || \
@@@ -3462,7 -3456,7 +3463,7 @@@ clean: profile-clean coverage-clean coc
        $(RM) git.res
        $(RM) $(OBJECTS)
        $(RM) $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(REFTABLE_TEST_LIB)
 -      $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X
 +      $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS)
        $(RM) $(TEST_PROGRAMS)
        $(RM) $(FUZZ_PROGRAMS)
        $(RM) $(SP_OBJ)
@@@ -3513,7 -3507,6 +3514,7 @@@ ALL_COMMANDS += git-citoo
  ALL_COMMANDS += git-gui
  ALL_COMMANDS += gitk
  ALL_COMMANDS += gitweb
 +ALL_COMMANDS += scalar
  
  .PHONY: check-docs
  check-docs::
diff --combined builtin/bundle.c
index 544c78a5f3ae29c1d3c71fdaf78cc9a83c90dec4,fd4586b09e0f8327eedb93f0b10dc3380e66bd53..c12c09f8549940774c2882f18259cfc13318bdb2
   * bundle supporting "fetch", "pull", and "ls-remote".
   */
  
 -static const char * const builtin_bundle_usage[] = {
 -  N_("git bundle create [<options>] <file> <git-rev-list args>"),
 -  N_("git bundle verify [<options>] <file>"),
 -  N_("git bundle list-heads <file> [<refname>...]"),
 -  N_("git bundle unbundle <file> [<refname>...]"),
 -  NULL
 +#define BUILTIN_BUNDLE_CREATE_USAGE \
 +      N_("git bundle create [-q | --quiet | --progress | --all-progress] [--all-progress-implied]\n" \
 +         "                  [--version=<version>] <file> <git-rev-list-args>")
 +#define BUILTIN_BUNDLE_VERIFY_USAGE \
 +      N_("git bundle verify [-q | --quiet] <file>")
 +#define BUILTIN_BUNDLE_LIST_HEADS_USAGE \
 +      N_("git bundle list-heads <file> [<refname>...]")
 +#define BUILTIN_BUNDLE_UNBUNDLE_USAGE \
 +      N_("git bundle unbundle [--progress] <file> [<refname>...]")
 +
 +static char const * const builtin_bundle_usage[] = {
 +      BUILTIN_BUNDLE_CREATE_USAGE,
 +      BUILTIN_BUNDLE_VERIFY_USAGE,
 +      BUILTIN_BUNDLE_LIST_HEADS_USAGE,
 +      BUILTIN_BUNDLE_UNBUNDLE_USAGE,
 +      NULL,
  };
  
  static const char * const builtin_bundle_create_usage[] = {
 -  N_("git bundle create [<options>] <file> <git-rev-list args>"),
 -  NULL
 +      BUILTIN_BUNDLE_CREATE_USAGE,
 +      NULL
  };
  
  static const char * const builtin_bundle_verify_usage[] = {
 -  N_("git bundle verify [<options>] <file>"),
 -  NULL
 +      BUILTIN_BUNDLE_VERIFY_USAGE,
 +      NULL
  };
  
  static const char * const builtin_bundle_list_heads_usage[] = {
 -  N_("git bundle list-heads <file> [<refname>...]"),
 -  NULL
 +      BUILTIN_BUNDLE_LIST_HEADS_USAGE,
 +      NULL
  };
  
  static const char * const builtin_bundle_unbundle_usage[] = {
 -  N_("git bundle unbundle <file> [<refname>...]"),
 -  NULL
 +      BUILTIN_BUNDLE_UNBUNDLE_USAGE,
 +      NULL
  };
  
  static int parse_options_cmd_bundle(int argc,
@@@ -129,7 -119,8 +129,8 @@@ static int cmd_bundle_verify(int argc, 
                goto cleanup;
        }
        close(bundle_fd);
-       if (verify_bundle(the_repository, &header, !quiet)) {
+       if (verify_bundle(the_repository, &header,
+                         quiet ? VERIFY_BUNDLE_QUIET : VERIFY_BUNDLE_VERBOSE)) {
                ret = 1;
                goto cleanup;
        }
@@@ -195,7 -186,7 +196,7 @@@ static int cmd_bundle_unbundle(int argc
                strvec_pushl(&extra_index_pack_args, "-v", "--progress-title",
                             _("Unbundling objects"), NULL);
        ret = !!unbundle(the_repository, &header, bundle_fd,
-                        &extra_index_pack_args) ||
+                        &extra_index_pack_args, 0) ||
                list_bundle_refs(&header, argc, argv);
        bundle_header_release(&header);
  cleanup:
  
  int cmd_bundle(int argc, const char **argv, const char *prefix)
  {
 +      parse_opt_subcommand_fn *fn = NULL;
        struct option options[] = {
 +              OPT_SUBCOMMAND("create", &fn, cmd_bundle_create),
 +              OPT_SUBCOMMAND("verify", &fn, cmd_bundle_verify),
 +              OPT_SUBCOMMAND("list-heads", &fn, cmd_bundle_list_heads),
 +              OPT_SUBCOMMAND("unbundle", &fn, cmd_bundle_unbundle),
                OPT_END()
        };
 -      int result;
  
        argc = parse_options(argc, argv, prefix, options, builtin_bundle_usage,
 -              PARSE_OPT_STOP_AT_NON_OPTION);
 +                           0);
  
        packet_trace_identity("bundle");
  
 -      if (argc < 2)
 -              usage_with_options(builtin_bundle_usage, options);
 -
 -      else if (!strcmp(argv[0], "create"))
 -              result = cmd_bundle_create(argc, argv, prefix);
 -      else if (!strcmp(argv[0], "verify"))
 -              result = cmd_bundle_verify(argc, argv, prefix);
 -      else if (!strcmp(argv[0], "list-heads"))
 -              result = cmd_bundle_list_heads(argc, argv, prefix);
 -      else if (!strcmp(argv[0], "unbundle"))
 -              result = cmd_bundle_unbundle(argc, argv, prefix);
 -      else {
 -              error(_("Unknown subcommand: %s"), argv[0]);
 -              usage_with_options(builtin_bundle_usage, options);
 -      }
 -      return result ? 1 : 0;
 +      return !!fn(argc, argv, prefix);
  }
diff --combined bundle.h
index 68ff39a0a74085a218f16d07619fad0adad1972c,575c34245d1ed448ac9dd5f20e4cf13cbd7f8a97..9f2bd733a6aa33a7f192a5fd70bd34c61ad9517a
+++ b/bundle.h
@@@ -18,7 -18,6 +18,7 @@@ struct bundle_header 
  { \
        .prerequisites = STRING_LIST_INIT_DUP, \
        .references = STRING_LIST_INIT_DUP, \
 +      .filter = LIST_OBJECTS_FILTER_INIT, \
  }
  void bundle_header_init(struct bundle_header *header);
  void bundle_header_release(struct bundle_header *header);
@@@ -30,7 -29,14 +30,14 @@@ int read_bundle_header_fd(int fd, struc
  int create_bundle(struct repository *r, const char *path,
                  int argc, const char **argv, struct strvec *pack_options,
                  int version);
- int verify_bundle(struct repository *r, struct bundle_header *header, int verbose);
+ enum verify_bundle_flags {
+       VERIFY_BUNDLE_VERBOSE = (1 << 0),
+       VERIFY_BUNDLE_QUIET = (1 << 1),
+ };
+ int verify_bundle(struct repository *r, struct bundle_header *header,
+                 enum verify_bundle_flags flags);
  
  /**
   * Unbundle after reading the header with read_bundle_header().
   * Provide "extra_index_pack_args" to pass any extra arguments
   * (e.g. "-v" for verbose/progress), NULL otherwise. The provided
   * "extra_index_pack_args" (if any) will be strvec_clear()'d for you.
+  *
+  * Before unbundling, this method will call verify_bundle() with the
+  * given 'flags'.
   */
  int unbundle(struct repository *r, struct bundle_header *header,
-            int bundle_fd, struct strvec *extra_index_pack_args);
+            int bundle_fd, struct strvec *extra_index_pack_args,
+            enum verify_bundle_flags flags);
  int list_bundle_refs(struct bundle_header *header,
                int argc, const char **argv);
  
diff --combined config.c
index c157fb5ae3f9619b4efd7fe4ecdda85222d231db,1cb35bea2fc928c472418989eefe3a7710a2faaa..c058b2c70c39c68e8c3967e90e9848dab56537ed
+++ b/config.c
@@@ -362,8 -362,7 +362,8 @@@ static void populate_remote_urls(struc
        current_parsing_scope = store_scope;
  }
  
 -static int forbid_remote_url(const char *var, const char *value, void *data)
 +static int forbid_remote_url(const char *var, const char *value UNUSED,
 +                           void *data UNUSED)
  {
        const char *remote_name;
        size_t remote_name_len;
@@@ -1215,7 -1214,7 +1215,7 @@@ static int git_parse_unsigned(const cha
        return 0;
  }
  
static int git_parse_int(const char *value, int *ret)
+ int git_parse_int(const char *value, int *ret)
  {
        intmax_t tmp;
        if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(int)))
@@@ -2338,10 -2337,10 +2338,10 @@@ static int configset_add_value(struct c
        return 0;
  }
  
 -static int config_set_element_cmp(const void *unused_cmp_data,
 +static int config_set_element_cmp(const void *cmp_data UNUSED,
                                  const struct hashmap_entry *eptr,
                                  const struct hashmap_entry *entry_or_key,
 -                                const void *unused_keydata)
 +                                const void *keydata UNUSED)
  {
        const struct config_set_element *e1, *e2;
  
@@@ -2392,6 -2391,11 +2392,6 @@@ int git_configset_add_file(struct confi
        return git_config_from_file(config_set_callback, filename, cs);
  }
  
 -int git_configset_add_parameters(struct config_set *cs)
 -{
 -      return git_config_from_parameters(config_set_callback, cs);
 -}
 -
  int git_configset_get_value(struct config_set *cs, const char *key, const char **value)
  {
        const struct string_list *values = NULL;
@@@ -2636,15 -2640,24 +2636,15 @@@ int repo_config_get_pathname(struct rep
  /* Read values into protected_config. */
  static void read_protected_config(void)
  {
 -      char *xdg_config = NULL, *user_config = NULL, *system_config = NULL;
 -
 +      struct config_options opts = {
 +              .respect_includes = 1,
 +              .ignore_repo = 1,
 +              .ignore_worktree = 1,
 +              .system_gently = 1,
 +      };
        git_configset_init(&protected_config);
 -
 -      system_config = git_system_config();
 -      git_global_config(&user_config, &xdg_config);
 -
 -      if (system_config)
 -              git_configset_add_file(&protected_config, system_config);
 -      if (xdg_config)
 -              git_configset_add_file(&protected_config, xdg_config);
 -      if (user_config)
 -              git_configset_add_file(&protected_config, user_config);
 -      git_configset_add_parameters(&protected_config);
 -
 -      free(system_config);
 -      free(xdg_config);
 -      free(user_config);
 +      config_with_options(config_set_callback, &protected_config,
 +                          NULL, &opts);
  }
  
  void git_protected_config(config_fn_t fn, void *data)
diff --combined t/helper/test-tool.c
index d1d013bcd920b197163b7c780f0131b0a1356541,fbe2d9d8108a77df838083dc25f9b07faeb9047f..01cda9358df01f50de95a93c8aee795696da377d
@@@ -1,6 -1,5 +1,6 @@@
  #include "git-compat-util.h"
  #include "test-tool.h"
 +#include "test-tool-utils.h"
  #include "trace2.h"
  #include "parse-options.h"
  
@@@ -9,10 -8,16 +9,11 @@@ static const char * const test_tool_usa
        NULL
  };
  
 -struct test_cmd {
 -      const char *name;
 -      int (*fn)(int argc, const char **argv);
 -};
 -
  static struct test_cmd cmds[] = {
        { "advise", cmd__advise_if_enabled },
        { "bitmap", cmd__bitmap },
        { "bloom", cmd__bloom },
+       { "bundle-uri", cmd__bundle_uri },
        { "chmtime", cmd__chmtime },
        { "config", cmd__config },
        { "crontab", cmd__crontab },
@@@ -47,9 -52,7 +48,9 @@@
        { "online-cpus", cmd__online_cpus },
        { "pack-mtimes", cmd__pack_mtimes },
        { "parse-options", cmd__parse_options },
 +      { "parse-options-flags", cmd__parse_options_flags },
        { "parse-pathspec-file", cmd__parse_pathspec_file },
 +      { "parse-subcommand", cmd__parse_subcommand },
        { "partial-clone", cmd__partial_clone },
        { "path-utils", cmd__path_utils },
        { "pcre2-config", cmd__pcre2_config },
@@@ -63,7 -66,6 +64,7 @@@
        { "read-midx", cmd__read_midx },
        { "ref-store", cmd__ref_store },
        { "reftable", cmd__reftable },
 +      { "rot13-filter", cmd__rot13_filter },
        { "dump-reftable", cmd__dump_reftable },
        { "regex", cmd__regex },
        { "repository", cmd__repository },
@@@ -77,7 -79,6 +78,7 @@@
        { "simple-ipc", cmd__simple_ipc },
        { "strcmp-offset", cmd__strcmp_offset },
        { "string-list", cmd__string_list },
 +      { "submodule", cmd__submodule },
        { "submodule-config", cmd__submodule_config },
        { "submodule-nested-repo-config", cmd__submodule_nested_repo_config },
        { "subprocess", cmd__subprocess },
diff --combined t/helper/test-tool.h
index 6b46b6444b657c3debdc286c50e81db5ba495f8b,b2aa1f39a8ff708be2dcd613e5bb68aca1191a3c..ca2948066fd64ec4743e498fffd06829c2cfce2b
@@@ -7,6 -7,7 +7,7 @@@
  int cmd__advise_if_enabled(int argc, const char **argv);
  int cmd__bitmap(int argc, const char **argv);
  int cmd__bloom(int argc, const char **argv);
+ int cmd__bundle_uri(int argc, const char **argv);
  int cmd__chmtime(int argc, const char **argv);
  int cmd__config(int argc, const char **argv);
  int cmd__crontab(int argc, const char **argv);
@@@ -41,9 -42,7 +42,9 @@@ int cmd__oidtree(int argc, const char *
  int cmd__online_cpus(int argc, const char **argv);
  int cmd__pack_mtimes(int argc, const char **argv);
  int cmd__parse_options(int argc, const char **argv);
 +int cmd__parse_options_flags(int argc, const char **argv);
  int cmd__parse_pathspec_file(int argc, const char** argv);
 +int cmd__parse_subcommand(int argc, const char **argv);
  int cmd__partial_clone(int argc, const char **argv);
  int cmd__path_utils(int argc, const char **argv);
  int cmd__pcre2_config(int argc, const char **argv);
@@@ -56,7 -55,6 +57,7 @@@ int cmd__read_cache(int argc, const cha
  int cmd__read_graph(int argc, const char **argv);
  int cmd__read_midx(int argc, const char **argv);
  int cmd__ref_store(int argc, const char **argv);
 +int cmd__rot13_filter(int argc, const char **argv);
  int cmd__reftable(int argc, const char **argv);
  int cmd__regex(int argc, const char **argv);
  int cmd__repository(int argc, const char **argv);
@@@ -71,7 -69,6 +72,7 @@@ int cmd__sigchain(int argc, const char 
  int cmd__simple_ipc(int argc, const char **argv);
  int cmd__strcmp_offset(int argc, const char **argv);
  int cmd__string_list(int argc, const char **argv);
 +int cmd__submodule(int argc, const char **argv);
  int cmd__submodule_config(int argc, const char **argv);
  int cmd__submodule_nested_repo_config(int argc, const char **argv);
  int cmd__subprocess(int argc, const char **argv);
diff --combined t/test-lib-functions.sh
index adc0fb6330c13635b69f2815ba43348ecf245fda,5d2f20983b876b1e4db89247fa3937defe1e8848..29d914a12ba170c30ba64c627a508a04dac239d4
@@@ -273,13 -273,13 +273,13 @@@ debug () 
  # <file>, <contents>, and <tag> all default to <message>.
  
  test_commit () {
 -      notick= &&
 -      echo=echo &&
 -      append= &&
 -      author= &&
 -      signoff= &&
 -      indir= &&
 -      tag=light &&
 +      local notick= &&
 +      local echo=echo &&
 +      local append= &&
 +      local author= &&
 +      local signoff= &&
 +      local indir= &&
 +      local tag=light &&
        while test $# != 0
        do
                case "$1" in
                shift
        done &&
        indir=${indir:+"$indir"/} &&
 -      file=${2:-"$1.t"} &&
 +      local file=${2:-"$1.t"} &&
        if test -n "$append"
        then
                $echo "${3-$1}" >>"$indir$file"
@@@ -897,7 -897,7 +897,7 @@@ test_path_is_symlink () 
  test_dir_is_empty () {
        test "$#" -ne 1 && BUG "1 param"
        test_path_is_dir "$1" &&
 -      if test -n "$(ls -a1 "$1" | egrep -v '^\.\.?$')"
 +      if test -n "$(ls -a1 "$1" | grep -E -v '^\.\.?$')"
        then
                echo "Directory '$1' is not empty, it contains:"
                ls -la "$1"
@@@ -1868,3 -1868,14 +1868,14 @@@ test_is_magic_mtime () 
        rm -f .git/test-mtime-actual
        return $ret
  }
+ # Given two filenames, parse both using 'git config --list --file'
+ # and compare the sorted output of those commands. Useful when
+ # wanting to ignore whitespace differences and sorting concerns.
+ test_cmp_config_output () {
+       git config --list --file="$1" >config-expect &&
+       git config --list --file="$2" >config-actual &&
+       sort config-expect >sorted-expect &&
+       sort config-actual >sorted-actual &&
+       test_cmp sorted-expect sorted-actual
+ }
diff --combined transport.c
index 70e9c188a398db37d316becb9f8393a46ab350c5,de4d88687ca5da7455b4ce2170f19f55b4d81d3f..e7b97194c103a3a7fad6d4174e40c96db9ff2a4c
@@@ -142,7 -142,7 +142,7 @@@ static void get_refs_from_bundle_inner(
  
  static struct ref *get_refs_from_bundle(struct transport *transport,
                                        int for_push,
 -                                      struct transport_ls_refs_options *transport_options)
 +                                      struct transport_ls_refs_options *transport_options UNUSED)
  {
        struct bundle_transport_data *data = transport->data;
        struct ref *result = NULL;
@@@ -178,7 -178,7 +178,7 @@@ static int fetch_refs_from_bundle(struc
        if (!data->get_refs_from_bundle_called)
                get_refs_from_bundle_inner(transport);
        ret = unbundle(the_repository, &data->header, data->fd,
-                      &extra_index_pack_args);
+                      &extra_index_pack_args, 0);
        transport->hash_algo = data->header.hash_algo;
        return ret;
  }
@@@ -386,8 -386,7 +386,8 @@@ static int fetch_refs_via_pack(struct t
        args.cloning = transport->cloning;
        args.update_shallow = data->options.update_shallow;
        args.from_promisor = data->options.from_promisor;
 -      args.filter_options = data->options.filter_options;
 +      list_objects_filter_copy(&args.filter_options,
 +                               &data->options.filter_options);
        args.refetch = data->options.refetch;
        args.stateless_rpc = transport->stateless_rpc;
        args.server_options = transport->server_options;
@@@ -454,7 -453,6 +454,7 @@@ cleanup
  
        free_refs(refs_tmp);
        free_refs(refs);
 +      list_objects_filter_release(&args.filter_options);
        return ret;
  }
  
@@@ -895,7 -893,6 +895,7 @@@ static int disconnect_git(struct transp
                finish_connect(data->conn);
        }
  
 +      list_objects_filter_release(&data->options.filter_options);
        free(data);
        return 0;
  }
@@@ -1009,7 -1006,8 +1009,7 @@@ static enum protocol_allow_config get_p
        if (!strcmp(type, "http") ||
            !strcmp(type, "https") ||
            !strcmp(type, "git") ||
 -          !strcmp(type, "ssh") ||
 -          !strcmp(type, "file"))
 +          !strcmp(type, "ssh"))
                return PROTOCOL_ALLOW_ALWAYS;
  
        /* known scary; err on the side of caution */
@@@ -1112,7 -1110,6 +1112,7 @@@ struct transport *transport_get(struct 
                 * will be checked individually in git_connect.
                 */
                struct git_transport_data *data = xcalloc(1, sizeof(*data));
 +              list_objects_filter_init(&data->options.filter_options);
                ret->data = data;
                ret->vtable = &builtin_smart_vtable;
                ret->smart_options = &(data->options);