Merge branch 'jk/show-index'
authorJunio C Hamano <gitster@pobox.com>
Mon, 25 Jun 2018 20:22:37 +0000 (13:22 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 25 Jun 2018 20:22:37 +0000 (13:22 -0700)
Modernize a less often used command.

* jk/show-index:
show-index: update documentation for index v2
make show-index a builtin

1  2 
Makefile
builtin.h
git.c
diff --combined Makefile
index e4b503d259906d60a65204248aeb54962b12c062,ebc1a57cd4a23d00e1098cc27957fa2beb95c1fe..edba22955271fec370d9eba4bcb85069c8de39a6
+++ b/Makefile
@@@ -29,10 -29,10 +29,10 @@@ all:
  # Perl-compatible regular expressions instead of standard or extended
  # POSIX regular expressions.
  #
 -# Currently USE_LIBPCRE is a synonym for USE_LIBPCRE1, define
 -# USE_LIBPCRE2 instead if you'd like to use version 2 of the PCRE
 -# library. The USE_LIBPCRE flag will likely be changed to mean v2 by
 -# default in future releases.
 +# USE_LIBPCRE is a synonym for USE_LIBPCRE2, define USE_LIBPCRE1
 +# instead if you'd like to use the legacy version 1 of the PCRE
 +# library. Support for version 1 will likely be removed in some future
 +# release of Git, as upstream has all but abandoned it.
  #
  # When using USE_LIBPCRE1, define NO_LIBPCRE1_JIT if the PCRE v1
  # library is compiled without --enable-jit. We will auto-detect
  # when hardlinking a file to another name and unlinking the original file right
  # away (some NTFS drivers seem to zero the contents in that scenario).
  #
 +# Define INSTALL_SYMLINKS if you prefer to have everything that can be
 +# symlinked between bin/ and libexec/ to use relative symlinks between
 +# the two. This option overrides NO_CROSS_DIRECTORY_HARDLINKS and
 +# NO_INSTALL_HARDLINKS which will also use symlinking by indirection
 +# within the same directory in some cases, INSTALL_SYMLINKS will
 +# always symlink to the final target directly.
 +#
  # Define NO_CROSS_DIRECTORY_HARDLINKS if you plan to distribute the installed
  # programs as a tar, where bin/ and libexec/ might be on different file systems.
  #
  #
  # When cross-compiling, define HOST_CPU as the canonical name of the CPU on
  # which the built Git will run (for instance "x86_64").
 +#
 +# Define RUNTIME_PREFIX to configure Git to resolve its ancillary tooling and
 +# support files relative to the location of the runtime binary, rather than
 +# hard-coding them into the binary. Git installations built with RUNTIME_PREFIX
 +# can be moved to arbitrary filesystem locations. RUNTIME_PREFIX also causes
 +# Perl scripts to use a modified entry point header allowing them to resolve
 +# support files at runtime.
 +#
 +# When using RUNTIME_PREFIX, define HAVE_BSD_KERN_PROC_SYSCTL if your platform
 +# supports the KERN_PROC BSD sysctl function.
 +#
 +# When using RUNTIME_PREFIX, define PROCFS_EXECUTABLE_PATH if your platform
 +# mounts a "procfs" filesystem capable of resolving the path of the current
 +# executable. If defined, this must be the canonical path for the "procfs"
 +# current executable path.
 +#
 +# When using RUNTIME_PREFIX, define HAVE_NS_GET_EXECUTABLE_PATH if your platform
 +# supports calling _NSGetExecutablePath to retrieve the path of the running
 +# executable.
 +#
 +# When using RUNTIME_PREFIX, define HAVE_WPGMPTR if your platform offers
 +# the global variable _wpgmptr containing the absolute path of the current
 +# executable (this is the case on Windows).
 +#
 +# Define DEVELOPER to enable more compiler warnings. Compiler version
 +# and family are auto detected, but could be overridden by defining
 +# COMPILER_FEATURES (see config.mak.dev)
 +#
 +# When DEVELOPER is set, DEVOPTS can be used to control compiler
 +# options.  This variable contains keywords separated by
 +# whitespace. The following keywords are are recognized:
 +#
 +#    no-error:
 +#
 +#        suppresses the -Werror that implicitly comes with
 +#        DEVELOPER=1. Useful for getting the full set of errors
 +#        without immediately dying, or for logging them.
 +#
 +#    extra-all:
 +#
 +#        The DEVELOPER mode enables -Wextra with a few exceptions. By
 +#        setting this flag the exceptions are removed, and all of
 +#        -Wextra is used.
  
  GIT-VERSION-FILE: FORCE
        @$(SHELL_PATH) ./GIT-VERSION-GEN
  # CFLAGS and LDFLAGS are for the users to override from the command line.
  
  CFLAGS = -g -O2 -Wall
 -DEVELOPER_CFLAGS = -Werror \
 -      -Wdeclaration-after-statement \
 -      -Wno-format-zero-length \
 -      -Wold-style-definition \
 -      -Woverflow \
 -      -Wpointer-arith \
 -      -Wstrict-prototypes \
 -      -Wunused \
 -      -Wvla
  LDFLAGS =
  ALL_CFLAGS = $(CPPFLAGS) $(CFLAGS)
  ALL_LDFLAGS = $(LDFLAGS)
@@@ -512,12 -471,11 +512,12 @@@ ARFLAGS = rc
  #   mandir
  #   infodir
  #   htmldir
 +#   localedir
 +#   perllibdir
  # This can help installing the suite in a relocatable way.
  
  prefix = $(HOME)
 -bindir_relative = bin
 -bindir = $(prefix)/$(bindir_relative)
 +bindir = $(prefix)/bin
  mandir = $(prefix)/share/man
  infodir = $(prefix)/share/info
  gitexecdir = libexec/git-core
@@@ -534,13 -492,9 +534,13 @@@ lib = li
  # DESTDIR =
  pathsep = :
  
 +bindir_relative = $(patsubst $(prefix)/%,%,$(bindir))
  mandir_relative = $(patsubst $(prefix)/%,%,$(mandir))
  infodir_relative = $(patsubst $(prefix)/%,%,$(infodir))
 +gitexecdir_relative = $(patsubst $(prefix)/%,%,$(gitexecdir))
 +localedir_relative = $(patsubst $(prefix)/%,%,$(localedir))
  htmldir_relative = $(patsubst $(prefix)/%,%,$(htmldir))
 +perllibdir_relative = $(patsubst $(prefix)/%,%,$(perllibdir))
  
  export prefix bindir sharedir sysconfdir gitwebdir perllibdir localedir
  
@@@ -592,7 -546,6 +592,7 @@@ SCRIPT_PERL 
  SCRIPT_PYTHON =
  SCRIPT_SH =
  SCRIPT_LIB =
 +TEST_BUILTINS_OBJS =
  TEST_PROGRAMS_NEED_X =
  
  # Having this variable in your environment would break pipelines because
@@@ -689,7 -642,7 +689,6 @@@ PROGRAM_OBJS += http-backend.
  PROGRAM_OBJS += imap-send.o
  PROGRAM_OBJS += sh-i18n--envsubst.o
  PROGRAM_OBJS += shell.o
- PROGRAM_OBJS += show-index.o
 -PROGRAM_OBJS += upload-pack.o
  PROGRAM_OBJS += remote-testsvn.o
  
  # Binary suffix, set to .exe for Windows builds
@@@ -697,50 -650,47 +696,50 @@@ X 
  
  PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
  
 -TEST_PROGRAMS_NEED_X += test-chmtime
 -TEST_PROGRAMS_NEED_X += test-ctype
 -TEST_PROGRAMS_NEED_X += test-config
 -TEST_PROGRAMS_NEED_X += test-date
 -TEST_PROGRAMS_NEED_X += test-delta
 -TEST_PROGRAMS_NEED_X += test-drop-caches
 -TEST_PROGRAMS_NEED_X += test-dump-cache-tree
 +TEST_BUILTINS_OBJS += test-chmtime.o
 +TEST_BUILTINS_OBJS += test-config.o
 +TEST_BUILTINS_OBJS += test-ctype.o
 +TEST_BUILTINS_OBJS += test-date.o
 +TEST_BUILTINS_OBJS += test-delta.o
 +TEST_BUILTINS_OBJS += test-drop-caches.o
 +TEST_BUILTINS_OBJS += test-dump-cache-tree.o
 +TEST_BUILTINS_OBJS += test-dump-split-index.o
 +TEST_BUILTINS_OBJS += test-example-decorate.o
 +TEST_BUILTINS_OBJS += test-genrandom.o
 +TEST_BUILTINS_OBJS += test-hashmap.o
 +TEST_BUILTINS_OBJS += test-index-version.o
 +TEST_BUILTINS_OBJS += test-lazy-init-name-hash.o
 +TEST_BUILTINS_OBJS += test-match-trees.o
 +TEST_BUILTINS_OBJS += test-mergesort.o
 +TEST_BUILTINS_OBJS += test-mktemp.o
 +TEST_BUILTINS_OBJS += test-online-cpus.o
 +TEST_BUILTINS_OBJS += test-path-utils.o
 +TEST_BUILTINS_OBJS += test-prio-queue.o
 +TEST_BUILTINS_OBJS += test-read-cache.o
 +TEST_BUILTINS_OBJS += test-ref-store.o
 +TEST_BUILTINS_OBJS += test-regex.o
 +TEST_BUILTINS_OBJS += test-revision-walking.o
 +TEST_BUILTINS_OBJS += test-run-command.o
 +TEST_BUILTINS_OBJS += test-scrap-cache-tree.o
 +TEST_BUILTINS_OBJS += test-sha1-array.o
 +TEST_BUILTINS_OBJS += test-sha1.o
 +TEST_BUILTINS_OBJS += test-sigchain.o
 +TEST_BUILTINS_OBJS += test-strcmp-offset.o
 +TEST_BUILTINS_OBJS += test-string-list.o
 +TEST_BUILTINS_OBJS += test-submodule-config.o
 +TEST_BUILTINS_OBJS += test-subprocess.o
 +TEST_BUILTINS_OBJS += test-urlmatch-normalization.o
 +TEST_BUILTINS_OBJS += test-wildmatch.o
 +TEST_BUILTINS_OBJS += test-write-cache.o
 +
  TEST_PROGRAMS_NEED_X += test-dump-fsmonitor
 -TEST_PROGRAMS_NEED_X += test-dump-split-index
  TEST_PROGRAMS_NEED_X += test-dump-untracked-cache
 -TEST_PROGRAMS_NEED_X += test-example-decorate
  TEST_PROGRAMS_NEED_X += test-fake-ssh
 -TEST_PROGRAMS_NEED_X += test-genrandom
 -TEST_PROGRAMS_NEED_X += test-hashmap
 -TEST_PROGRAMS_NEED_X += test-index-version
 -TEST_PROGRAMS_NEED_X += test-lazy-init-name-hash
  TEST_PROGRAMS_NEED_X += test-line-buffer
 -TEST_PROGRAMS_NEED_X += test-match-trees
 -TEST_PROGRAMS_NEED_X += test-mergesort
 -TEST_PROGRAMS_NEED_X += test-mktemp
 -TEST_PROGRAMS_NEED_X += test-online-cpus
  TEST_PROGRAMS_NEED_X += test-parse-options
 -TEST_PROGRAMS_NEED_X += test-path-utils
 -TEST_PROGRAMS_NEED_X += test-prio-queue
 -TEST_PROGRAMS_NEED_X += test-read-cache
 -TEST_PROGRAMS_NEED_X += test-write-cache
 -TEST_PROGRAMS_NEED_X += test-ref-store
 -TEST_PROGRAMS_NEED_X += test-regex
 -TEST_PROGRAMS_NEED_X += test-revision-walking
 -TEST_PROGRAMS_NEED_X += test-run-command
 -TEST_PROGRAMS_NEED_X += test-scrap-cache-tree
 -TEST_PROGRAMS_NEED_X += test-sha1
 -TEST_PROGRAMS_NEED_X += test-sha1-array
 -TEST_PROGRAMS_NEED_X += test-sigchain
 -TEST_PROGRAMS_NEED_X += test-strcmp-offset
 -TEST_PROGRAMS_NEED_X += test-string-list
 -TEST_PROGRAMS_NEED_X += test-submodule-config
 -TEST_PROGRAMS_NEED_X += test-subprocess
 +TEST_PROGRAMS_NEED_X += test-pkt-line
  TEST_PROGRAMS_NEED_X += test-svn-fe
 -TEST_PROGRAMS_NEED_X += test-urlmatch-normalization
 -TEST_PROGRAMS_NEED_X += test-wildmatch
 +TEST_PROGRAMS_NEED_X += test-tool
  
  TEST_PROGRAMS = $(patsubst %,t/helper/%$X,$(TEST_PROGRAMS_NEED_X))
  
@@@ -795,7 -745,7 +794,7 @@@ LIB_FILE = libgit.
  XDIFF_LIB = xdiff/lib.a
  VCSSVN_LIB = vcs-svn/lib.a
  
 -GENERATED_H += common-cmds.h
 +GENERATED_H += command-list.h
  
  LIB_H = $(shell $(FIND) . \
        -name .git -prune -o \
@@@ -821,13 -771,11 +820,13 @@@ LIB_OBJS += branch.
  LIB_OBJS += bulk-checkin.o
  LIB_OBJS += bundle.o
  LIB_OBJS += cache-tree.o
 +LIB_OBJS += chdir-notify.o
  LIB_OBJS += checkout.o
  LIB_OBJS += color.o
  LIB_OBJS += column.o
  LIB_OBJS += combine-diff.o
  LIB_OBJS += commit.o
 +LIB_OBJS += commit-graph.o
  LIB_OBJS += compat/obstack.o
  LIB_OBJS += compat/terminal.o
  LIB_OBJS += config.o
@@@ -858,7 -806,7 +857,7 @@@ LIB_OBJS += ewah/bitmap.
  LIB_OBJS += ewah/ewah_bitmap.o
  LIB_OBJS += ewah/ewah_io.o
  LIB_OBJS += ewah/ewah_rlw.o
 -LIB_OBJS += exec_cmd.o
 +LIB_OBJS += exec-cmd.o
  LIB_OBJS += fetch-object.o
  LIB_OBJS += fetch-pack.o
  LIB_OBJS += fsck.o
@@@ -881,11 -829,9 +880,11 @@@ LIB_OBJS += list-objects-filter-options
  LIB_OBJS += ll-merge.o
  LIB_OBJS += lockfile.o
  LIB_OBJS += log-tree.o
 +LIB_OBJS += ls-refs.o
  LIB_OBJS += mailinfo.o
  LIB_OBJS += mailmap.o
  LIB_OBJS += match-trees.o
 +LIB_OBJS += mem-pool.o
  LIB_OBJS += merge.o
  LIB_OBJS += merge-blobs.o
  LIB_OBJS += merge-recursive.o
@@@ -928,10 -874,9 +927,10 @@@ LIB_OBJS += refs/files-backend.
  LIB_OBJS += refs/iterator.o
  LIB_OBJS += refs/packed-backend.o
  LIB_OBJS += refs/ref-cache.o
 +LIB_OBJS += refspec.o
  LIB_OBJS += ref-filter.o
  LIB_OBJS += remote.o
 -LIB_OBJS += replace_object.o
 +LIB_OBJS += replace-object.o
  LIB_OBJS += repository.o
  LIB_OBJS += rerere.o
  LIB_OBJS += resolve-undo.o
@@@ -939,13 -884,12 +938,13 @@@ LIB_OBJS += revision.
  LIB_OBJS += run-command.o
  LIB_OBJS += send-pack.o
  LIB_OBJS += sequencer.o
 +LIB_OBJS += serve.o
  LIB_OBJS += server-info.o
  LIB_OBJS += setup.o
  LIB_OBJS += sha1-array.o
  LIB_OBJS += sha1-lookup.o
 -LIB_OBJS += sha1_file.o
 -LIB_OBJS += sha1_name.o
 +LIB_OBJS += sha1-file.o
 +LIB_OBJS += sha1-name.o
  LIB_OBJS += shallow.o
  LIB_OBJS += sideband.o
  LIB_OBJS += sigchain.o
@@@ -968,7 -912,6 +967,7 @@@ LIB_OBJS += tree-diff.
  LIB_OBJS += tree.o
  LIB_OBJS += tree-walk.o
  LIB_OBJS += unpack-trees.o
 +LIB_OBJS += upload-pack.o
  LIB_OBJS += url.o
  LIB_OBJS += urlmatch.o
  LIB_OBJS += usage.o
@@@ -981,7 -924,7 +980,7 @@@ LIB_OBJS += walker.
  LIB_OBJS += wildmatch.o
  LIB_OBJS += worktree.o
  LIB_OBJS += wrapper.o
 -LIB_OBJS += write_or_die.o
 +LIB_OBJS += write-or-die.o
  LIB_OBJS += ws.o
  LIB_OBJS += wt-status.o
  LIB_OBJS += xdiff-interface.o
@@@ -1008,7 -951,6 +1007,7 @@@ BUILTIN_OBJS += builtin/clone.
  BUILTIN_OBJS += builtin/column.o
  BUILTIN_OBJS += builtin/commit-tree.o
  BUILTIN_OBJS += builtin/commit.o
 +BUILTIN_OBJS += builtin/commit-graph.o
  BUILTIN_OBJS += builtin/config.o
  BUILTIN_OBJS += builtin/count-objects.o
  BUILTIN_OBJS += builtin/credential.o
@@@ -1074,9 -1016,9 +1073,10 @@@ BUILTIN_OBJS += builtin/rev-parse.
  BUILTIN_OBJS += builtin/revert.o
  BUILTIN_OBJS += builtin/rm.o
  BUILTIN_OBJS += builtin/send-pack.o
 +BUILTIN_OBJS += builtin/serve.o
  BUILTIN_OBJS += builtin/shortlog.o
  BUILTIN_OBJS += builtin/show-branch.o
+ BUILTIN_OBJS += builtin/show-index.o
  BUILTIN_OBJS += builtin/show-ref.o
  BUILTIN_OBJS += builtin/stripspace.o
  BUILTIN_OBJS += builtin/submodule--helper.o
@@@ -1088,7 -1030,6 +1088,7 @@@ BUILTIN_OBJS += builtin/update-index.
  BUILTIN_OBJS += builtin/update-ref.o
  BUILTIN_OBJS += builtin/update-server-info.o
  BUILTIN_OBJS += builtin/upload-archive.o
 +BUILTIN_OBJS += builtin/upload-pack.o
  BUILTIN_OBJS += builtin/var.o
  BUILTIN_OBJS += builtin/verify-commit.o
  BUILTIN_OBJS += builtin/verify-pack.o
@@@ -1110,7 -1051,7 +1110,7 @@@ include config.mak.unam
  -include config.mak
  
  ifdef DEVELOPER
 -CFLAGS += $(DEVELOPER_CFLAGS)
 +include config.mak.dev
  endif
  
  comma := ,
@@@ -1229,18 -1170,13 +1229,18 @@@ ifdef NO_LIBGEN_
        COMPAT_OBJS += compat/basename.o
  endif
  
 -USE_LIBPCRE1 ?= $(USE_LIBPCRE)
 +USE_LIBPCRE2 ?= $(USE_LIBPCRE)
  
 -ifneq (,$(USE_LIBPCRE1))
 -      ifdef USE_LIBPCRE2
 -$(error Only set USE_LIBPCRE1 (or its alias USE_LIBPCRE) or USE_LIBPCRE2, not both!)
 +ifneq (,$(USE_LIBPCRE2))
 +      ifdef USE_LIBPCRE1
 +$(error Only set USE_LIBPCRE2 (or its alias USE_LIBPCRE) or USE_LIBPCRE1, not both!)
        endif
  
 +      BASIC_CFLAGS += -DUSE_LIBPCRE2
 +      EXTLIBS += -lpcre2-8
 +endif
 +
 +ifdef USE_LIBPCRE1
        BASIC_CFLAGS += -DUSE_LIBPCRE1
        EXTLIBS += -lpcre
  
@@@ -1249,6 -1185,11 +1249,6 @@@ ifdef NO_LIBPCRE1_JI
  endif
  endif
  
 -ifdef USE_LIBPCRE2
 -      BASIC_CFLAGS += -DUSE_LIBPCRE2
 -      EXTLIBS += -lpcre2-8
 -endif
 -
  ifdef LIBPCREDIR
        BASIC_CFLAGS += -I$(LIBPCREDIR)/include
        EXTLIBS += -L$(LIBPCREDIR)/$(lib) $(CC_LD_DYNPATH)$(LIBPCREDIR)/$(lib)
@@@ -1351,19 -1292,17 +1351,19 @@@ ifdef APPLE_COMMON_CRYPT
        LIB_4_CRYPTO += -framework Security -framework CoreFoundation
  endif
  endif
 -ifdef NEEDS_LIBICONV
 -      ifdef ICONVDIR
 -              BASIC_CFLAGS += -I$(ICONVDIR)/include
 -              ICONV_LINK = -L$(ICONVDIR)/$(lib) $(CC_LD_DYNPATH)$(ICONVDIR)/$(lib)
 -      else
 -              ICONV_LINK =
 -      endif
 -      ifdef NEEDS_LIBINTL_BEFORE_LIBICONV
 -              ICONV_LINK += -lintl
 +ifndef NO_ICONV
 +      ifdef NEEDS_LIBICONV
 +              ifdef ICONVDIR
 +                      BASIC_CFLAGS += -I$(ICONVDIR)/include
 +                      ICONV_LINK = -L$(ICONVDIR)/$(lib) $(CC_LD_DYNPATH)$(ICONVDIR)/$(lib)
 +              else
 +                      ICONV_LINK =
 +              endif
 +              ifdef NEEDS_LIBINTL_BEFORE_LIBICONV
 +                      ICONV_LINK += -lintl
 +              endif
 +              EXTLIBS += $(ICONV_LINK) -liconv
        endif
 -      EXTLIBS += $(ICONV_LINK) -liconv
  endif
  ifdef NEEDS_LIBGEN
        EXTLIBS += -lgen
@@@ -1713,27 -1652,10 +1713,27 @@@ ifdef HAVE_BSD_SYSCT
        BASIC_CFLAGS += -DHAVE_BSD_SYSCTL
  endif
  
 +ifdef HAVE_BSD_KERN_PROC_SYSCTL
 +      BASIC_CFLAGS += -DHAVE_BSD_KERN_PROC_SYSCTL
 +endif
 +
  ifdef HAVE_GETDELIM
        BASIC_CFLAGS += -DHAVE_GETDELIM
  endif
  
 +ifneq ($(PROCFS_EXECUTABLE_PATH),)
 +      procfs_executable_path_SQ = $(subst ','\'',$(PROCFS_EXECUTABLE_PATH))
 +      BASIC_CFLAGS += '-DPROCFS_EXECUTABLE_PATH="$(procfs_executable_path_SQ)"'
 +endif
 +
 +ifdef HAVE_NS_GET_EXECUTABLE_PATH
 +      BASIC_CFLAGS += -DHAVE_NS_GET_EXECUTABLE_PATH
 +endif
 +
 +ifdef HAVE_WPGMPTR
 +      BASIC_CFLAGS += -DHAVE_WPGMPTR
 +endif
 +
  ifeq ($(TCLTK_PATH),)
  NO_TCLTK = NoThanks
  endif
@@@ -1818,13 -1740,10 +1818,13 @@@ mandir_relative_SQ = $(subst ','\'',$(m
  infodir_relative_SQ = $(subst ','\'',$(infodir_relative))
  perllibdir_SQ = $(subst ','\'',$(perllibdir))
  localedir_SQ = $(subst ','\'',$(localedir))
 +localedir_relative_SQ = $(subst ','\'',$(localedir_relative))
  gitexecdir_SQ = $(subst ','\'',$(gitexecdir))
 +gitexecdir_relative_SQ = $(subst ','\'',$(gitexecdir_relative))
  template_dir_SQ = $(subst ','\'',$(template_dir))
  htmldir_relative_SQ = $(subst ','\'',$(htmldir_relative))
  prefix_SQ = $(subst ','\'',$(prefix))
 +perllibdir_relative_SQ = $(subst ','\'',$(perllibdir_relative))
  gitwebdir_SQ = $(subst ','\'',$(gitwebdir))
  
  SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
@@@ -1835,31 -1754,6 +1835,31 @@@ TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_
  DIFF_SQ = $(subst ','\'',$(DIFF))
  PERLLIB_EXTRA_SQ = $(subst ','\'',$(PERLLIB_EXTRA))
  
 +# RUNTIME_PREFIX's resolution logic requires resource paths to be expressed
 +# relative to each other and share an installation path.
 +#
 +# This is a dependency in:
 +# - Git's binary RUNTIME_PREFIX logic in (see "exec_cmd.c").
 +# - The runtime prefix Perl header (see
 +#   "perl/header_templates/runtime_prefix.template.pl").
 +ifdef RUNTIME_PREFIX
 +
 +ifneq ($(filter /%,$(firstword $(gitexecdir_relative))),)
 +$(error RUNTIME_PREFIX requires a relative gitexecdir, not: $(gitexecdir))
 +endif
 +
 +ifneq ($(filter /%,$(firstword $(localedir_relative))),)
 +$(error RUNTIME_PREFIX requires a relative localedir, not: $(localedir))
 +endif
 +
 +ifndef NO_PERL
 +ifneq ($(filter /%,$(firstword $(perllibdir_relative))),)
 +$(error RUNTIME_PREFIX requires a relative perllibdir, not: $(perllibdir))
 +endif
 +endif
 +
 +endif
 +
  # We must filter out any object files from $(GITLIBS),
  # as it is typically used like:
  #
@@@ -2008,9 -1902,9 +2008,9 @@@ git$X: git.o GIT-LDFLAGS $(BUILTIN_OBJS
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \
                $(filter %.o,$^) $(LIBS)
  
 -help.sp help.s help.o: common-cmds.h
 +help.sp help.s help.o: command-list.h
  
 -builtin/help.sp builtin/help.s builtin/help.o: common-cmds.h GIT-PREFIX
 +builtin/help.sp builtin/help.s builtin/help.o: command-list.h GIT-PREFIX
  builtin/help.sp builtin/help.s builtin/help.o: EXTRA_CPPFLAGS = \
        '-DGIT_HTML_PATH="$(htmldir_relative_SQ)"' \
        '-DGIT_MAN_PATH="$(mandir_relative_SQ)"' \
@@@ -2029,9 -1923,9 +2029,9 @@@ $(BUILT_INS): git$
        ln -s $< $@ 2>/dev/null || \
        cp $< $@
  
 -common-cmds.h: generate-cmdlist.sh command-list.txt
 +command-list.h: generate-cmdlist.sh command-list.txt
  
 -common-cmds.h: $(wildcard Documentation/git-*.txt)
 +command-list.h: $(wildcard Documentation/git*.txt)
        $(QUIET_GEN)$(SHELL_PATH) ./generate-cmdlist.sh command-list.txt >$@+ && mv $@+ $@
  
  SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\
@@@ -2080,44 -1974,27 +2080,44 @@@ git.res: git.rc GIT-VERSION-FIL
  # This makes sure we depend on the NO_PERL setting itself.
  $(SCRIPT_PERL_GEN): GIT-BUILD-OPTIONS
  
 -ifndef NO_PERL
 -$(SCRIPT_PERL_GEN):
 +# Used for substitution in Perl modules. Disabled when using RUNTIME_PREFIX
 +# since the locale directory is injected.
 +perl_localedir_SQ = $(localedir_SQ)
  
 +ifndef NO_PERL
 +PERL_HEADER_TEMPLATE = perl/header_templates/fixed_prefix.template.pl
  PERL_DEFINES = $(PERL_PATH_SQ):$(PERLLIB_EXTRA_SQ):$(perllibdir_SQ)
 -$(SCRIPT_PERL_GEN): % : %.perl GIT-PERL-DEFINES GIT-VERSION-FILE
 +
 +PERL_DEFINES := $(PERL_PATH_SQ) $(PERLLIB_EXTRA_SQ) $(perllibdir_SQ)
 +PERL_DEFINES += $(RUNTIME_PREFIX)
 +
 +# Support Perl runtime prefix. In this mode, a different header is installed
 +# into Perl scripts.
 +ifdef RUNTIME_PREFIX
 +
 +PERL_HEADER_TEMPLATE = perl/header_templates/runtime_prefix.template.pl
 +
 +# Don't export a fixed $(localedir) path; it will be resolved by the Perl header
 +# at runtime.
 +perl_localedir_SQ =
 +
 +endif
 +
 +PERL_DEFINES += $(gitexecdir) $(perllibdir) $(localedir)
 +
 +$(SCRIPT_PERL_GEN): % : %.perl GIT-PERL-DEFINES GIT-PERL-HEADER GIT-VERSION-FILE
        $(QUIET_GEN)$(RM) $@ $@+ && \
 -      INSTLIBDIR='$(perllibdir_SQ)' && \
 -      INSTLIBDIR_EXTRA='$(PERLLIB_EXTRA_SQ)' && \
 -      INSTLIBDIR="$$INSTLIBDIR$${INSTLIBDIR_EXTRA:+:$$INSTLIBDIR_EXTRA}" && \
        sed -e '1{' \
            -e '        s|#!.*perl|#!$(PERL_PATH_SQ)|' \
 -          -e '        h' \
 -          -e '        s=.*=use lib (split(/$(pathsep)/, $$ENV{GITPERLLIB} || "'"$$INSTLIBDIR"'"));=' \
 -          -e '        H' \
 -          -e '        x' \
 +          -e '        rGIT-PERL-HEADER' \
 +          -e '        G' \
            -e '}' \
            -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
            $< >$@+ && \
        chmod +x $@+ && \
        mv $@+ $@
  
 +PERL_DEFINES := $(subst $(space),:,$(PERL_DEFINES))
  GIT-PERL-DEFINES: FORCE
        @FLAGS='$(PERL_DEFINES)'; \
            if test x"$$FLAGS" != x"`cat $@ 2>/dev/null`" ; then \
                echo "$$FLAGS" >$@; \
            fi
  
 +GIT-PERL-HEADER: $(PERL_HEADER_TEMPLATE) GIT-PERL-DEFINES Makefile
 +      $(QUIET_GEN)$(RM) $@ && \
 +      INSTLIBDIR='$(perllibdir_SQ)' && \
 +      INSTLIBDIR_EXTRA='$(PERLLIB_EXTRA_SQ)' && \
 +      INSTLIBDIR="$$INSTLIBDIR$${INSTLIBDIR_EXTRA:+:$$INSTLIBDIR_EXTRA}" && \
 +      sed -e 's=@@PATHSEP@@=$(pathsep)=g' \
 +          -e "s=@@INSTLIBDIR@@=$$INSTLIBDIR=g" \
 +          -e 's=@@PERLLIBDIR_REL@@=$(perllibdir_relative_SQ)=g' \
 +          -e 's=@@GITEXECDIR_REL@@=$(gitexecdir_relative_SQ)=g' \
 +          -e 's=@@LOCALEDIR_REL@@=$(localedir_relative_SQ)=g' \
 +          $< >$@+ && \
 +      mv $@+ $@
 +
 +.PHONY: perllibdir
 +perllibdir:
 +      @echo '$(perllibdir_SQ)'
  
  .PHONY: gitweb
  gitweb:
@@@ -2222,7 -2083,7 +2222,7 @@@ VCSSVN_OBJS += vcs-svn/fast_export.
  VCSSVN_OBJS += vcs-svn/svndiff.o
  VCSSVN_OBJS += vcs-svn/svndump.o
  
 -TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS))
 +TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS)) $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS))
  OBJECTS := $(LIB_OBJS) $(BUILTIN_OBJS) $(PROGRAM_OBJS) $(TEST_OBJS) \
        $(XDIFF_OBJS) \
        $(VCSSVN_OBJS) \
  # Dependencies on header files, for platforms that do not support
  # the gcc -MMD option.
  #
 -# Dependencies on automatically generated headers such as common-cmds.h
 +# Dependencies on automatically generated headers such as command-list.h
  # should _not_ be included here, since they are necessary even when
  # building an object for the first time.
  
  $(OBJECTS): $(LIB_H)
  endif
  
 -exec_cmd.sp exec_cmd.s exec_cmd.o: GIT-PREFIX
 -exec_cmd.sp exec_cmd.s exec_cmd.o: EXTRA_CPPFLAGS = \
 +exec-cmd.sp exec-cmd.s exec-cmd.o: GIT-PREFIX
 +exec-cmd.sp exec-cmd.s exec-cmd.o: EXTRA_CPPFLAGS = \
        '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' \
 +      '-DGIT_LOCALE_PATH="$(localedir_relative_SQ)"' \
        '-DBINDIR="$(bindir_relative_SQ)"' \
 -      '-DPREFIX="$(prefix_SQ)"'
 +      '-DFALLBACK_RUNTIME_PREFIX="$(prefix_SQ)"'
  
  builtin/init-db.sp builtin/init-db.s builtin/init-db.o: GIT-PREFIX
  builtin/init-db.sp builtin/init-db.s builtin/init-db.o: EXTRA_CPPFLAGS = \
@@@ -2303,7 -2163,7 +2303,7 @@@ attr.sp attr.s attr.o: EXTRA_CPPFLAGS 
  
  gettext.sp gettext.s gettext.o: GIT-PREFIX
  gettext.sp gettext.s gettext.o: EXTRA_CPPFLAGS = \
 -      -DGIT_LOCALE_PATH='"$(localedir_SQ)"'
 +      -DGIT_LOCALE_PATH='"$(localedir_relative_SQ)"'
  
  http-push.sp http.sp http-walker.sp remote-curl.sp imap-send.sp: SPARSE_FLAGS += \
        -DCURL_DISABLE_TYPECHECK
@@@ -2463,7 -2323,7 +2463,7 @@@ endi
  
  perl/build/lib/%.pm: perl/%.pm
        $(QUIET_GEN)mkdir -p $(dir $@) && \
 -      sed -e 's|@@LOCALEDIR@@|$(localedir_SQ)|g' \
 +      sed -e 's|@@LOCALEDIR@@|$(perl_localedir_SQ)|g' \
            -e 's|@@NO_PERL_CPAN_FALLBACKS@@|$(NO_PERL_CPAN_FALLBACKS_SQ)|g' \
        < $< > $@
  
@@@ -2634,12 -2494,10 +2634,12 @@@ t/helper/test-svn-fe$X: $(VCSSVN_LIB
  
  .PRECIOUS: $(TEST_OBJS)
  
 +t/helper/test-tool$X: $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS))
 +
  t/helper/test-%$X: t/helper/test-%.o GIT-LDFLAGS $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(filter %.a,$^) $(LIBS)
  
 -check-sha1:: t/helper/test-sha1$X
 +check-sha1:: t/helper/test-tool$X
        t/helper/test-sha1.sh
  
  SP_OBJ = $(patsubst %.o,%.sp,$(C_OBJ))
@@@ -2655,7 -2513,7 +2655,7 @@@ sparse: $(SP_OBJ
  style:
        git clang-format --style file --diff --extensions c,h
  
 -check: common-cmds.h
 +check: command-list.h
        @if sparse; \
        then \
                echo >&2 "Use 'make sparse' instead"; \
@@@ -2748,44 -2606,35 +2748,44 @@@ endi
  
        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 \
                $(RM) "$$execdir/$$p" && \
 -              test -z "$(NO_INSTALL_HARDLINKS)$(NO_CROSS_DIRECTORY_HARDLINKS)" && \
 -              ln "$$bindir/$$p" "$$execdir/$$p" 2>/dev/null || \
 -              cp "$$bindir/$$p" "$$execdir/$$p" || exit; \
 +              test -n "$(INSTALL_SYMLINKS)" && \
 +              ln -s "$$destdir_from_execdir_SQ/$(bindir_relative_SQ)/$$p" "$$execdir/$$p" || \
 +              { test -z "$(NO_INSTALL_HARDLINKS)$(NO_CROSS_DIRECTORY_HARDLINKS)" && \
 +                ln "$$bindir/$$p" "$$execdir/$$p" 2>/dev/null || \
 +                cp "$$bindir/$$p" "$$execdir/$$p" || exit; } \
          done; \
        } && \
        for p in $(filter $(install_bindir_programs),$(BUILT_INS)); do \
                $(RM) "$$bindir/$$p" && \
 -              test -z "$(NO_INSTALL_HARDLINKS)" && \
 -              ln "$$bindir/git$X" "$$bindir/$$p" 2>/dev/null || \
 -              ln -s "git$X" "$$bindir/$$p" 2>/dev/null || \
 -              cp "$$bindir/git$X" "$$bindir/$$p" || exit; \
 +              test -n "$(INSTALL_SYMLINKS)" && \
 +              ln -s "git$X" "$$bindir/$$p" || \
 +              { test -z "$(NO_INSTALL_HARDLINKS)" && \
 +                ln "$$bindir/git$X" "$$bindir/$$p" 2>/dev/null || \
 +                ln -s "git$X" "$$bindir/$$p" 2>/dev/null || \
 +                cp "$$bindir/git$X" "$$bindir/$$p" || exit; } \
        done && \
        for p in $(BUILT_INS); do \
                $(RM) "$$execdir/$$p" && \
 -              test -z "$(NO_INSTALL_HARDLINKS)" && \
 -              ln "$$execdir/git$X" "$$execdir/$$p" 2>/dev/null || \
 -              ln -s "git$X" "$$execdir/$$p" 2>/dev/null || \
 -              cp "$$execdir/git$X" "$$execdir/$$p" || exit; \
 +              test -n "$(INSTALL_SYMLINKS)" && \
 +              ln -s "$$destdir_from_execdir_SQ/$(bindir_relative_SQ)/git$X" "$$execdir/$$p" || \
 +              { test -z "$(NO_INSTALL_HARDLINKS)" && \
 +                ln "$$execdir/git$X" "$$execdir/$$p" 2>/dev/null || \
 +                ln -s "git$X" "$$execdir/$$p" 2>/dev/null || \
 +                cp "$$execdir/git$X" "$$execdir/$$p" || exit; } \
        done && \
        remote_curl_aliases="$(REMOTE_CURL_ALIASES)" && \
        for p in $$remote_curl_aliases; do \
                $(RM) "$$execdir/$$p" && \
 -              test -z "$(NO_INSTALL_HARDLINKS)" && \
 -              ln "$$execdir/git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
 -              ln -s "git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
 -              cp "$$execdir/git-remote-http$X" "$$execdir/$$p" || exit; \
 +              test -n "$(INSTALL_SYMLINKS)" && \
 +              ln -s "git-remote-http$X" "$$execdir/$$p" || \
 +              { test -z "$(NO_INSTALL_HARDLINKS)" && \
 +                ln "$$execdir/git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
 +                ln -s "git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
 +                cp "$$execdir/git-remote-http$X" "$$execdir/$$p" || exit; } \
        done && \
        ./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X"
  
@@@ -2903,7 -2752,7 +2903,7 @@@ clean: profile-clean coverage-clea
        $(RM) $(TEST_PROGRAMS) $(NO_INSTALL)
        $(RM) -r bin-wrappers $(dep_dirs)
        $(RM) -r po/build/
 -      $(RM) *.pyc *.pyo */*.pyc */*.pyo common-cmds.h $(ETAGS_TARGET) tags cscope*
 +      $(RM) *.pyc *.pyo */*.pyc */*.pyo command-list.h $(ETAGS_TARGET) tags cscope*
        $(RM) -r $(GIT_TARNAME) .doc-tmp-dir
        $(RM) $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
        $(RM) $(htmldocs).tar.gz $(manpages).tar.gz
@@@ -2921,7 -2770,7 +2921,7 @@@ ifndef NO_TCLT
  endif
        $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-LDFLAGS GIT-BUILD-OPTIONS
        $(RM) GIT-USER-AGENT GIT-PREFIX
 -      $(RM) GIT-SCRIPT-DEFINES GIT-PERL-DEFINES GIT-PYTHON-VARS
 +      $(RM) GIT-SCRIPT-DEFINES GIT-PERL-DEFINES GIT-PERL-HEADER GIT-PYTHON-VARS
  
  .PHONY: all install profile-clean clean strip
  .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
diff --combined builtin.h
index 4e0f64723ed8dde9c97827cc688535b2dda73025,feb559e58255441833566c855eb0dd609fa06390..0362f1ce25fb64631e28f00eafa46f35bc94c7eb
+++ b/builtin.h
@@@ -149,7 -149,6 +149,7 @@@ extern int cmd_clone(int argc, const ch
  extern int cmd_clean(int argc, const char **argv, const char *prefix);
  extern int cmd_column(int argc, const char **argv, const char *prefix);
  extern int cmd_commit(int argc, const char **argv, const char *prefix);
 +extern int cmd_commit_graph(int argc, const char **argv, const char *prefix);
  extern int cmd_commit_tree(int argc, const char **argv, const char *prefix);
  extern int cmd_config(int argc, const char **argv, const char *prefix);
  extern int cmd_count_objects(int argc, const char **argv, const char *prefix);
@@@ -216,10 -215,10 +216,11 @@@ extern int cmd_rev_parse(int argc, cons
  extern int cmd_revert(int argc, const char **argv, const char *prefix);
  extern int cmd_rm(int argc, const char **argv, const char *prefix);
  extern int cmd_send_pack(int argc, const char **argv, const char *prefix);
 +extern int cmd_serve(int argc, const char **argv, const char *prefix);
  extern int cmd_shortlog(int argc, const char **argv, const char *prefix);
  extern int cmd_show(int argc, const char **argv, const char *prefix);
  extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
+ extern int cmd_show_index(int argc, const char **argv, const char *prefix);
  extern int cmd_status(int argc, const char **argv, const char *prefix);
  extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
  extern int cmd_submodule__helper(int argc, const char **argv, const char *prefix);
@@@ -233,7 -232,6 +234,7 @@@ extern int cmd_update_ref(int argc, con
  extern int cmd_update_server_info(int argc, const char **argv, const char *prefix);
  extern int cmd_upload_archive(int argc, const char **argv, const char *prefix);
  extern int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix);
 +extern int cmd_upload_pack(int argc, const char **argv, const char *prefix);
  extern int cmd_var(int argc, const char **argv, const char *prefix);
  extern int cmd_verify_commit(int argc, const char **argv, const char *prefix);
  extern int cmd_verify_tag(int argc, const char **argv, const char *prefix);
diff --combined git.c
index c2f48d53dd4aaba0752aa5f2e6633242d320b248,1a10c9637586aa50bf1b716d6777c5bf10604ca4..9dbe6ffaa7f04ceba22b215a221b9a389d0cad97
--- 1/git.c
--- 2/git.c
+++ b/git.c
@@@ -1,32 -1,13 +1,32 @@@
  #include "builtin.h"
  #include "config.h"
 -#include "exec_cmd.h"
 +#include "exec-cmd.h"
  #include "help.h"
  #include "run-command.h"
 +#include "alias.h"
 +
 +#define RUN_SETUP             (1<<0)
 +#define RUN_SETUP_GENTLY      (1<<1)
 +#define USE_PAGER             (1<<2)
 +/*
 + * require working tree to be present -- anything uses this needs
 + * RUN_SETUP for reading from the configuration file.
 + */
 +#define NEED_WORK_TREE                (1<<3)
 +#define SUPPORT_SUPER_PREFIX  (1<<4)
 +#define DELAY_PAGER_CONFIG    (1<<5)
 +#define NO_PARSEOPT           (1<<6) /* parse-options is not used */
 +
 +struct cmd_struct {
 +      const char *cmd;
 +      int (*fn)(int, const char **, const char *);
 +      unsigned int option;
 +};
  
  const char git_usage_string[] =
        N_("git [--version] [--help] [-C <path>] [-c <name>=<value>]\n"
           "           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n"
 -         "           [-p | --paginate | --no-pager] [--no-replace-objects] [--bare]\n"
 +         "           [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]\n"
           "           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n"
           "           <command> [<args>]");
  
@@@ -37,66 -18,7 +37,66 @@@ const char git_more_info_string[] 
  
  static int use_pager = -1;
  
 -static void list_builtins(void);
 +static void list_builtins(struct string_list *list, unsigned int exclude_option);
 +
 +static void exclude_helpers_from_list(struct string_list *list)
 +{
 +      int i = 0;
 +
 +      while (i < list->nr) {
 +              if (strstr(list->items[i].string, "--"))
 +                      unsorted_string_list_delete_item(list, i, 0);
 +              else
 +                      i++;
 +      }
 +}
 +
 +static int match_token(const char *spec, int len, const char *token)
 +{
 +      int token_len = strlen(token);
 +
 +      return len == token_len && !strncmp(spec, token, token_len);
 +}
 +
 +static int list_cmds(const char *spec)
 +{
 +      struct string_list list = STRING_LIST_INIT_DUP;
 +      int i;
 +
 +      while (*spec) {
 +              const char *sep = strchrnul(spec, ',');
 +              int len = sep - spec;
 +
 +              if (match_token(spec, len, "builtins"))
 +                      list_builtins(&list, 0);
 +              else if (match_token(spec, len, "main"))
 +                      list_all_main_cmds(&list);
 +              else if (match_token(spec, len, "others"))
 +                      list_all_other_cmds(&list);
 +              else if (match_token(spec, len, "nohelpers"))
 +                      exclude_helpers_from_list(&list);
 +              else if (match_token(spec, len, "alias"))
 +                      list_aliases(&list);
 +              else if (match_token(spec, len, "config"))
 +                      list_cmds_by_config(&list);
 +              else if (len > 5 && !strncmp(spec, "list-", 5)) {
 +                      struct strbuf sb = STRBUF_INIT;
 +
 +                      strbuf_add(&sb, spec + 5, len - 5);
 +                      list_cmds_by_category(&list, sb.buf);
 +                      strbuf_release(&sb);
 +              }
 +              else
 +                      die(_("unsupported command listing type '%s'"), spec);
 +              spec += len;
 +              if (*spec == ',')
 +                      spec++;
 +      }
 +      for (i = 0; i < list.nr; i++)
 +              puts(list.items[i].string);
 +      string_list_clear(&list, 0);
 +      return 0;
 +}
  
  static void commit_pager_choice(void) {
        switch (use_pager) {
@@@ -143,7 -65,7 +143,7 @@@ static int handle_options(const char **
                 */
                if (skip_prefix(cmd, "--exec-path", &cmd)) {
                        if (*cmd == '=')
 -                              git_set_argv_exec_path(cmd + 1);
 +                              git_set_exec_path(cmd + 1);
                        else {
                                puts(git_exec_path());
                                exit(0);
                        exit(0);
                } else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
                        use_pager = 1;
 -              } else if (!strcmp(cmd, "--no-pager")) {
 +              } else if (!strcmp(cmd, "-P") || !strcmp(cmd, "--no-pager")) {
                        use_pager = 0;
                        if (envchanged)
                                *envchanged = 1;
                        }
                        (*argv)++;
                        (*argc)--;
 -              } else if (!strcmp(cmd, "--list-builtins")) {
 -                      list_builtins();
 -                      exit(0);
 +              } else if (skip_prefix(cmd, "--list-cmds=", &cmd)) {
 +                      if (!strcmp(cmd, "parseopt")) {
 +                              struct string_list list = STRING_LIST_INIT_DUP;
 +                              int i;
 +
 +                              list_builtins(&list, NO_PARSEOPT);
 +                              for (i = 0; i < list.nr; i++)
 +                                      printf("%s ", list.items[i].string);
 +                              string_list_clear(&list, 0);
 +                              exit(0);
 +                      } else {
 +                              exit(list_cmds(cmd));
 +                      }
                } else {
                        fprintf(stderr, _("unknown option: %s\n"), cmd);
                        usage(git_usage_string);
@@@ -376,6 -288,23 +376,6 @@@ static int handle_alias(int *argcp, con
        return ret;
  }
  
 -#define RUN_SETUP             (1<<0)
 -#define RUN_SETUP_GENTLY      (1<<1)
 -#define USE_PAGER             (1<<2)
 -/*
 - * require working tree to be present -- anything uses this needs
 - * RUN_SETUP for reading from the configuration file.
 - */
 -#define NEED_WORK_TREE                (1<<3)
 -#define SUPPORT_SUPER_PREFIX  (1<<4)
 -#define DELAY_PAGER_CONFIG    (1<<5)
 -
 -struct cmd_struct {
 -      const char *cmd;
 -      int (*fn)(int, const char **, const char *);
 -      int option;
 -};
 -
  static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
  {
        int status, help;
  static struct cmd_struct commands[] = {
        { "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
        { "am", cmd_am, RUN_SETUP | NEED_WORK_TREE },
 -      { "annotate", cmd_annotate, RUN_SETUP },
 +      { "annotate", cmd_annotate, RUN_SETUP | NO_PARSEOPT },
        { "apply", cmd_apply, RUN_SETUP_GENTLY },
        { "archive", cmd_archive, RUN_SETUP_GENTLY },
        { "bisect--helper", cmd_bisect__helper, RUN_SETUP },
        { "blame", cmd_blame, RUN_SETUP },
        { "branch", cmd_branch, RUN_SETUP | DELAY_PAGER_CONFIG },
 -      { "bundle", cmd_bundle, RUN_SETUP_GENTLY },
 +      { "bundle", cmd_bundle, RUN_SETUP_GENTLY | NO_PARSEOPT },
        { "cat-file", cmd_cat_file, RUN_SETUP },
        { "check-attr", cmd_check_attr, RUN_SETUP },
        { "check-ignore", cmd_check_ignore, RUN_SETUP | NEED_WORK_TREE },
        { "check-mailmap", cmd_check_mailmap, RUN_SETUP },
 -      { "check-ref-format", cmd_check_ref_format },
 +      { "check-ref-format", cmd_check_ref_format, NO_PARSEOPT  },
        { "checkout", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },
        { "checkout-index", cmd_checkout_index,
                RUN_SETUP | NEED_WORK_TREE},
        { "clone", cmd_clone },
        { "column", cmd_column, RUN_SETUP_GENTLY },
        { "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE },
 -      { "commit-tree", cmd_commit_tree, RUN_SETUP },
 +      { "commit-graph", cmd_commit_graph, RUN_SETUP },
 +      { "commit-tree", cmd_commit_tree, RUN_SETUP | NO_PARSEOPT },
        { "config", cmd_config, RUN_SETUP_GENTLY | DELAY_PAGER_CONFIG },
        { "count-objects", cmd_count_objects, RUN_SETUP },
 -      { "credential", cmd_credential, RUN_SETUP_GENTLY },
 +      { "credential", cmd_credential, RUN_SETUP_GENTLY | NO_PARSEOPT },
        { "describe", cmd_describe, RUN_SETUP },
 -      { "diff", cmd_diff },
 -      { "diff-files", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE },
 -      { "diff-index", cmd_diff_index, RUN_SETUP },
 -      { "diff-tree", cmd_diff_tree, RUN_SETUP },
 +      { "diff", cmd_diff, NO_PARSEOPT },
 +      { "diff-files", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },
 +      { "diff-index", cmd_diff_index, RUN_SETUP | NO_PARSEOPT },
 +      { "diff-tree", cmd_diff_tree, RUN_SETUP | NO_PARSEOPT },
        { "difftool", cmd_difftool, RUN_SETUP | NEED_WORK_TREE },
        { "fast-export", cmd_fast_export, RUN_SETUP },
        { "fetch", cmd_fetch, RUN_SETUP },
 -      { "fetch-pack", cmd_fetch_pack, RUN_SETUP },
 +      { "fetch-pack", cmd_fetch_pack, RUN_SETUP | NO_PARSEOPT },
        { "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP },
        { "for-each-ref", cmd_for_each_ref, RUN_SETUP },
        { "format-patch", cmd_format_patch, RUN_SETUP },
        { "fsck", cmd_fsck, RUN_SETUP },
        { "fsck-objects", cmd_fsck, RUN_SETUP },
        { "gc", cmd_gc, RUN_SETUP },
 -      { "get-tar-commit-id", cmd_get_tar_commit_id },
 +      { "get-tar-commit-id", cmd_get_tar_commit_id, NO_PARSEOPT },
        { "grep", cmd_grep, RUN_SETUP_GENTLY },
        { "hash-object", cmd_hash_object },
        { "help", cmd_help },
 -      { "index-pack", cmd_index_pack, RUN_SETUP_GENTLY },
 +      { "index-pack", cmd_index_pack, RUN_SETUP_GENTLY | NO_PARSEOPT },
        { "init", cmd_init_db },
        { "init-db", cmd_init_db },
        { "interpret-trailers", cmd_interpret_trailers, RUN_SETUP_GENTLY },
        { "ls-files", cmd_ls_files, RUN_SETUP },
        { "ls-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
        { "ls-tree", cmd_ls_tree, RUN_SETUP },
 -      { "mailinfo", cmd_mailinfo, RUN_SETUP_GENTLY },
 -      { "mailsplit", cmd_mailsplit },
 +      { "mailinfo", cmd_mailinfo, RUN_SETUP_GENTLY | NO_PARSEOPT },
 +      { "mailsplit", cmd_mailsplit, NO_PARSEOPT },
        { "merge", cmd_merge, RUN_SETUP | NEED_WORK_TREE },
        { "merge-base", cmd_merge_base, RUN_SETUP },
        { "merge-file", cmd_merge_file, RUN_SETUP_GENTLY },
 -      { "merge-index", cmd_merge_index, RUN_SETUP },
 -      { "merge-ours", cmd_merge_ours, RUN_SETUP },
 -      { "merge-recursive", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
 -      { "merge-recursive-ours", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
 -      { "merge-recursive-theirs", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
 -      { "merge-subtree", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
 -      { "merge-tree", cmd_merge_tree, RUN_SETUP },
 -      { "mktag", cmd_mktag, RUN_SETUP },
 +      { "merge-index", cmd_merge_index, RUN_SETUP | NO_PARSEOPT },
 +      { "merge-ours", cmd_merge_ours, RUN_SETUP | NO_PARSEOPT },
 +      { "merge-recursive", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },
 +      { "merge-recursive-ours", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },
 +      { "merge-recursive-theirs", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },
 +      { "merge-subtree", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },
 +      { "merge-tree", cmd_merge_tree, RUN_SETUP | NO_PARSEOPT },
 +      { "mktag", cmd_mktag, RUN_SETUP | NO_PARSEOPT },
        { "mktree", cmd_mktree, RUN_SETUP },
        { "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
        { "name-rev", cmd_name_rev, RUN_SETUP },
        { "notes", cmd_notes, RUN_SETUP },
        { "pack-objects", cmd_pack_objects, RUN_SETUP },
 -      { "pack-redundant", cmd_pack_redundant, RUN_SETUP },
 +      { "pack-redundant", cmd_pack_redundant, RUN_SETUP | NO_PARSEOPT },
        { "pack-refs", cmd_pack_refs, RUN_SETUP },
 -      { "patch-id", cmd_patch_id, RUN_SETUP_GENTLY },
 +      { "patch-id", cmd_patch_id, RUN_SETUP_GENTLY | NO_PARSEOPT },
        { "pickaxe", cmd_blame, RUN_SETUP },
        { "prune", cmd_prune, RUN_SETUP },
        { "prune-packed", cmd_prune_packed, RUN_SETUP },
        { "receive-pack", cmd_receive_pack },
        { "reflog", cmd_reflog, RUN_SETUP },
        { "remote", cmd_remote, RUN_SETUP },
 -      { "remote-ext", cmd_remote_ext },
 -      { "remote-fd", cmd_remote_fd },
 +      { "remote-ext", cmd_remote_ext, NO_PARSEOPT },
 +      { "remote-fd", cmd_remote_fd, NO_PARSEOPT },
        { "repack", cmd_repack, RUN_SETUP },
        { "replace", cmd_replace, RUN_SETUP },
        { "rerere", cmd_rerere, RUN_SETUP },
        { "reset", cmd_reset, RUN_SETUP },
 -      { "rev-list", cmd_rev_list, RUN_SETUP },
 -      { "rev-parse", cmd_rev_parse },
 +      { "rev-list", cmd_rev_list, RUN_SETUP | NO_PARSEOPT },
 +      { "rev-parse", cmd_rev_parse, NO_PARSEOPT },
        { "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
        { "rm", cmd_rm, RUN_SETUP },
        { "send-pack", cmd_send_pack, RUN_SETUP },
 +      { "serve", cmd_serve, RUN_SETUP },
        { "shortlog", cmd_shortlog, RUN_SETUP_GENTLY | USE_PAGER },
        { "show", cmd_show, RUN_SETUP },
        { "show-branch", cmd_show_branch, RUN_SETUP },
+       { "show-index", cmd_show_index },
        { "show-ref", cmd_show_ref, RUN_SETUP },
        { "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
        { "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
        { "stripspace", cmd_stripspace },
 -      { "submodule--helper", cmd_submodule__helper, RUN_SETUP | SUPPORT_SUPER_PREFIX},
 +      { "submodule--helper", cmd_submodule__helper, RUN_SETUP | SUPPORT_SUPER_PREFIX | NO_PARSEOPT },
        { "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
        { "tag", cmd_tag, RUN_SETUP | DELAY_PAGER_CONFIG },
 -      { "unpack-file", cmd_unpack_file, RUN_SETUP },
 -      { "unpack-objects", cmd_unpack_objects, RUN_SETUP },
 +      { "unpack-file", cmd_unpack_file, RUN_SETUP | NO_PARSEOPT },
 +      { "unpack-objects", cmd_unpack_objects, RUN_SETUP | NO_PARSEOPT },
        { "update-index", cmd_update_index, RUN_SETUP },
        { "update-ref", cmd_update_ref, RUN_SETUP },
        { "update-server-info", cmd_update_server_info, RUN_SETUP },
 -      { "upload-archive", cmd_upload_archive },
 -      { "upload-archive--writer", cmd_upload_archive_writer },
 -      { "var", cmd_var, RUN_SETUP_GENTLY },
 +      { "upload-archive", cmd_upload_archive, NO_PARSEOPT },
 +      { "upload-archive--writer", cmd_upload_archive_writer, NO_PARSEOPT },
 +      { "upload-pack", cmd_upload_pack },
 +      { "var", cmd_var, RUN_SETUP_GENTLY | NO_PARSEOPT },
        { "verify-commit", cmd_verify_commit, RUN_SETUP },
        { "verify-pack", cmd_verify_pack },
        { "verify-tag", cmd_verify_tag, RUN_SETUP },
        { "version", cmd_version },
        { "whatchanged", cmd_whatchanged, RUN_SETUP },
 -      { "worktree", cmd_worktree, RUN_SETUP },
 +      { "worktree", cmd_worktree, RUN_SETUP | NO_PARSEOPT },
        { "write-tree", cmd_write_tree, RUN_SETUP },
  };
  
@@@ -578,15 -505,11 +579,15 @@@ int is_builtin(const char *s
        return !!get_builtin(s);
  }
  
 -static void list_builtins(void)
 +static void list_builtins(struct string_list *out, unsigned int exclude_option)
  {
        int i;
 -      for (i = 0; i < ARRAY_SIZE(commands); i++)
 -              printf("%s\n", commands[i].cmd);
 +      for (i = 0; i < ARRAY_SIZE(commands); i++) {
 +              if (exclude_option &&
 +                  (commands[i].option & exclude_option))
 +                      continue;
 +              string_list_append(out, commands[i].cmd);
 +      }
  }
  
  #ifdef STRIP_EXTENSION