Merge branch 'nd/retire-fnmatch'
authorJunio C Hamano <gitster@pobox.com>
Fri, 25 Jan 2013 20:34:55 +0000 (12:34 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 25 Jan 2013 20:34:55 +0000 (12:34 -0800)
Replace our use of fnmatch(3) with a more feature-rich wildmatch.
A handful patches at the bottom have been moved to nd/wildmatch to
graduate as part of that branch, before this series solidifies.

We may want to mark USE_WILDMATCH as an experimental curiosity a
bit more clearly (i.e. should not be enabled in production
environment, because it will make the behaviour between builds
unpredictable).

* nd/retire-fnmatch:
Makefile: add USE_WILDMATCH to use wildmatch as fnmatch
wildmatch: advance faster in <asterisk> + <literal> patterns
wildmatch: make a special case for "*/" with FNM_PATHNAME
test-wildmatch: add "perf" command to compare wildmatch and fnmatch
wildmatch: support "no FNM_PATHNAME" mode
wildmatch: make dowild() take arbitrary flags
wildmatch: rename constants and update prototype

1  2 
Makefile
dir.c
git-compat-util.h
diff --combined Makefile
index 11e85a639652f8b47aaad8113fcc2776eae982e5,24e277481fcadf7f0d16733705d1dab9f53993c5..731b6a8834834fe6e6d1852e57752ee38d4321b0
+++ b/Makefile
@@@ -74,14 -74,10 +74,14 @@@ all:
  # Define NO_D_TYPE_IN_DIRENT if your platform defines DT_UNKNOWN but lacks
  # d_type in struct dirent (Cygwin 1.5, fixed in Cygwin 1.7).
  #
 +# Define HAVE_STRINGS_H if you have strings.h and need it for strcasecmp.
 +#
  # Define NO_STRCASESTR if you don't have strcasestr.
  #
  # Define NO_MEMMEM if you don't have memmem.
  #
 +# Define NO_GETPAGESIZE if you don't have getpagesize.
 +#
  # Define NO_STRLCPY if you don't have strlcpy.
  #
  # Define NO_STRTOUMAX if you don't have both strtoimax and strtoumax in the
@@@ -94,8 -90,6 +94,8 @@@
  #
  # Define NO_MKDTEMP if you don't have mkdtemp in the C library.
  #
 +# Define MKDIR_WO_TRAILING_SLASH if your mkdir() can't deal with trailing slash.
 +#
  # Define NO_MKSTEMPS if you don't have mkstemps in the C library.
  #
  # Define NO_STRTOK_R if you don't have strtok_r in the C library.
  # Define NO_FNMATCH_CASEFOLD if your fnmatch function doesn't have the
  # FNM_CASEFOLD GNU extension.
  #
+ # Define USE_WILDMATCH if you want to use Git's wildmatch
+ # implementation as fnmatch
+ #
  # Define NO_GECOS_IN_PWENT if you don't have pw_gecos in struct passwd
  # in the C library.
  #
  #
  # Define NEEDS_LIBICONV if linking with libc is not enough (Darwin).
  #
 +# Define NEEDS_LIBINTL_BEFORE_LIBICONV if you need libintl before libiconv.
 +#
 +# Define NO_INTPTR_T if you don't have intptr_t nor uintptr_t.
 +#
 +# Define NO_UINTMAX_T if you don't have uintmax_t.
 +#
  # Define NEEDS_SOCKET if linking with libc is not enough (SunOS,
  # Patrick Mauritz).
  #
  #
  # Define NO_MMAP if you want to avoid mmap.
  #
 +# Define NO_SYS_POLL_H if you don't have sys/poll.h.
 +#
 +# Define NO_POLL if you do not have or don't want to use poll().
 +# This also implies NO_SYS_POLL_H.
 +#
 +# Define NEEDS_SYS_PARAM_H if you need to include sys/param.h to compile,
 +# *PLEASE* REPORT to git@vger.kernel.org if your platform needs this;
 +# we want to know more about the issue.
 +#
  # Define NO_PTHREADS if you do not have or do not want to use Pthreads.
  #
  # Define NO_PREAD if you have a problem with pread() system call (e.g.
  # cygwin1.dll before v1.5.22).
  #
 +# Define NO_SETITIMER if you don't have setitimer()
 +#
 +# Define NO_STRUCT_ITIMERVAL if you don't have struct itimerval
 +# This also implies NO_SETITIMER
 +#
  # Define NO_THREAD_SAFE_PREAD if your pread() implementation is not
  # thread-safe. (e.g. compat/pread.c or cygwin)
  #
  # Define NO_ST_BLOCKS_IN_STRUCT_STAT if your platform does not have st_blocks
  # field that counts the on-disk footprint in 512-byte blocks.
  #
 -# Define ASCIIDOC7 if you want to format documentation with AsciiDoc 7
 -#
  # Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72
  # (not v1.73 or v1.71).
  #
  # apostrophes to be ASCII so that cut&pasting examples to the shell
  # will work.
  #
 +# Define PERL_PATH to the path of your Perl binary (usually /usr/bin/perl).
 +#
  # Define NO_PERL_MAKEMAKER if you cannot use Makefiles generated by perl's
  # MakeMaker (e.g. using ActiveState under Cygwin).
  #
  # Define NO_PERL if you do not want Perl scripts or libraries at all.
  #
 +# Define PYTHON_PATH to the path of your Python binary (often /usr/bin/python
 +# but /usr/bin/python2.7 on some platforms).
 +#
  # Define NO_PYTHON if you do not want Python scripts or libraries at all.
  #
  # Define NO_TCLTK if you do not want Tcl/Tk GUI.
  #
  # Define NO_REGEX if you have no or inferior regex support in your C library.
  #
 +# Define CYGWIN_V15_WIN32API if you are using Cygwin v1.7.x but are not
 +# using the current w32api packages. The recommended approach, however,
 +# is to update your installation if compilation errors occur.
 +#
  # Define HAVE_DEV_TTY if your system can open /dev/tty to interact with the
  # user.
  #
  # the diff algorithm.  It gives a nice speedup if your processor has
  # fast unaligned word loads.  Does NOT work on big-endian systems!
  # Enabled by default on x86_64.
 +#
 +# Define GIT_USER_AGENT if you want to change how git identifies itself during
 +# network interactions.  The default is "git/$(GIT_VERSION)".
 +#
 +# Define DEFAULT_HELP_FORMAT to "man", "info" or "html"
 +# (defaults to "man") if you want to have a different default when
 +# "git help" is called without a parameter specifying the format.
  
  GIT-VERSION-FILE: FORCE
        @$(SHELL_PATH) ./GIT-VERSION-GEN
  -include GIT-VERSION-FILE
  
 -uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
 -uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
 -uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
 -uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
 -uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
 -uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
 -
 -ifdef MSVC
 -      # avoid the MingW and Cygwin configuration sections
 -      uname_S := Windows
 -      uname_O := Windows
 -endif
 -
  # CFLAGS and LDFLAGS are for the users to override from the command line.
  
  CFLAGS = -g -O2 -Wall
@@@ -378,7 -354,7 +381,7 @@@ htmldir = share/doc/git-do
  ETC_GITCONFIG = $(sysconfdir)/gitconfig
  ETC_GITATTRIBUTES = $(sysconfdir)/gitattributes
  lib = lib
 -# DESTDIR=
 +# DESTDIR =
  pathsep = :
  
  export prefix bindir sharedir sysconfdir gitwebdir localedir
@@@ -418,9 -394,12 +421,9 @@@ BUILTIN_OBJS 
  BUILT_INS =
  COMPAT_CFLAGS =
  COMPAT_OBJS =
 -XDIFF_H =
  XDIFF_OBJS =
 -VCSSVN_H =
  VCSSVN_OBJS =
 -VCSSVN_TEST_OBJS =
 -MISC_H =
 +GENERATED_H =
  EXTRA_CPPFLAGS =
  LIB_H =
  LIB_OBJS =
@@@ -474,7 -453,7 +477,7 @@@ SCRIPT_PERL += git-relink.per
  SCRIPT_PERL += git-send-email.perl
  SCRIPT_PERL += git-svn.perl
  
 -SCRIPT_PYTHON += git-remote-testgit.py
 +SCRIPT_PYTHON += git-remote-testpy.py
  SCRIPT_PYTHON += git-p4.py
  
  SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
@@@ -499,7 -478,6 +502,7 @@@ PROGRAM_OBJS += sh-i18n--envsubst.
  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
  X =
  PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
  
  TEST_PROGRAMS_NEED_X += test-chmtime
 -TEST_PROGRAMS_NEED_X += test-credential
  TEST_PROGRAMS_NEED_X += test-ctype
  TEST_PROGRAMS_NEED_X += test-date
  TEST_PROGRAMS_NEED_X += test-delta
@@@ -525,7 -504,6 +528,7 @@@ TEST_PROGRAMS_NEED_X += test-run-comman
  TEST_PROGRAMS_NEED_X += test-scrap-cache-tree
  TEST_PROGRAMS_NEED_X += test-sha1
  TEST_PROGRAMS_NEED_X += test-sigchain
 +TEST_PROGRAMS_NEED_X += test-string-list
  TEST_PROGRAMS_NEED_X += test-subprocess
  TEST_PROGRAMS_NEED_X += test-svn-fe
  TEST_PROGRAMS_NEED_X += test-wildmatch
@@@ -580,51 -558,58 +583,51 @@@ endi
  export PERL_PATH
  export PYTHON_PATH
  
 -LIB_FILE=libgit.a
 -XDIFF_LIB=xdiff/lib.a
 -VCSSVN_LIB=vcs-svn/lib.a
 -
 -XDIFF_H += xdiff/xinclude.h
 -XDIFF_H += xdiff/xmacros.h
 -XDIFF_H += xdiff/xdiff.h
 -XDIFF_H += xdiff/xtypes.h
 -XDIFF_H += xdiff/xutils.h
 -XDIFF_H += xdiff/xprepare.h
 -XDIFF_H += xdiff/xdiffi.h
 -XDIFF_H += xdiff/xemit.h
 -
 -VCSSVN_H += vcs-svn/line_buffer.h
 -VCSSVN_H += vcs-svn/sliding_window.h
 -VCSSVN_H += vcs-svn/repo_tree.h
 -VCSSVN_H += vcs-svn/fast_export.h
 -VCSSVN_H += vcs-svn/svndiff.h
 -VCSSVN_H += vcs-svn/svndump.h
 -
 -MISC_H += bisect.h
 -MISC_H += branch.h
 -MISC_H += bundle.h
 -MISC_H += common-cmds.h
 -MISC_H += fetch-pack.h
 -MISC_H += reachable.h
 -MISC_H += send-pack.h
 -MISC_H += shortlog.h
 -MISC_H += tar.h
 -MISC_H += thread-utils.h
 -MISC_H += url.h
 -MISC_H += walker.h
 -MISC_H += wt-status.h
 +LIB_FILE = libgit.a
 +XDIFF_LIB = xdiff/lib.a
 +VCSSVN_LIB = vcs-svn/lib.a
 +
 +LIB_H += xdiff/xinclude.h
 +LIB_H += xdiff/xmacros.h
 +LIB_H += xdiff/xdiff.h
 +LIB_H += xdiff/xtypes.h
 +LIB_H += xdiff/xutils.h
 +LIB_H += xdiff/xprepare.h
 +LIB_H += xdiff/xdiffi.h
 +LIB_H += xdiff/xemit.h
 +
 +LIB_H += vcs-svn/line_buffer.h
 +LIB_H += vcs-svn/sliding_window.h
 +LIB_H += vcs-svn/repo_tree.h
 +LIB_H += vcs-svn/fast_export.h
 +LIB_H += vcs-svn/svndiff.h
 +LIB_H += vcs-svn/svndump.h
 +
 +GENERATED_H += common-cmds.h
  
  LIB_H += advice.h
  LIB_H += archive.h
  LIB_H += argv-array.h
  LIB_H += attr.h
 +LIB_H += bisect.h
  LIB_H += blob.h
 +LIB_H += branch.h
  LIB_H += builtin.h
  LIB_H += bulk-checkin.h
 -LIB_H += cache.h
 +LIB_H += bundle.h
  LIB_H += cache-tree.h
 +LIB_H += cache.h
  LIB_H += color.h
 +LIB_H += column.h
  LIB_H += commit.h
  LIB_H += compat/bswap.h
  LIB_H += compat/cygwin.h
  LIB_H += compat/mingw.h
  LIB_H += compat/obstack.h
 +LIB_H += compat/poll/poll.h
 +LIB_H += compat/precompose_utf8.h
  LIB_H += compat/terminal.h
  LIB_H += compat/win32/dirent.h
 -LIB_H += compat/win32/poll.h
  LIB_H += compat/win32/pthread.h
  LIB_H += compat/win32/syslog.h
  LIB_H += connected.h
@@@ -637,7 -622,6 +640,7 @@@ LIB_H += diff.
  LIB_H += diffcore.h
  LIB_H += dir.h
  LIB_H += exec_cmd.h
 +LIB_H += fetch-pack.h
  LIB_H += fmt-merge-msg.h
  LIB_H += fsck.h
  LIB_H += gettext.h
@@@ -647,31 -631,28 +650,31 @@@ LIB_H += graph.
  LIB_H += grep.h
  LIB_H += hash.h
  LIB_H += help.h
 +LIB_H += http.h
  LIB_H += kwset.h
  LIB_H += levenshtein.h
  LIB_H += list-objects.h
  LIB_H += ll-merge.h
  LIB_H += log-tree.h
  LIB_H += mailmap.h
 -LIB_H += merge-file.h
 +LIB_H += merge-blobs.h
  LIB_H += merge-recursive.h
  LIB_H += mergesort.h
 -LIB_H += notes.h
  LIB_H += notes-cache.h
  LIB_H += notes-merge.h
 +LIB_H += notes.h
  LIB_H += object.h
 -LIB_H += pack.h
  LIB_H += pack-refs.h
  LIB_H += pack-revindex.h
 +LIB_H += pack.h
  LIB_H += parse-options.h
  LIB_H += patch-ids.h
 +LIB_H += pathspec.h
  LIB_H += pkt-line.h
  LIB_H += progress.h
  LIB_H += prompt.h
  LIB_H += quote.h
 +LIB_H += reachable.h
  LIB_H += reflog-walk.h
  LIB_H += refs.h
  LIB_H += remote.h
@@@ -679,11 -660,9 +682,11 @@@ LIB_H += rerere.
  LIB_H += resolve-undo.h
  LIB_H += revision.h
  LIB_H += run-command.h
 +LIB_H += send-pack.h
  LIB_H += sequencer.h
  LIB_H += sha1-array.h
  LIB_H += sha1-lookup.h
 +LIB_H += shortlog.h
  LIB_H += sideband.h
  LIB_H += sigchain.h
  LIB_H += strbuf.h
@@@ -691,19 -670,15 +694,19 @@@ LIB_H += streaming.
  LIB_H += string-list.h
  LIB_H += submodule.h
  LIB_H += tag.h
 +LIB_H += tar.h
  LIB_H += thread-utils.h
  LIB_H += transport.h
 -LIB_H += tree.h
  LIB_H += tree-walk.h
 +LIB_H += tree.h
  LIB_H += unpack-trees.h
 +LIB_H += url.h
  LIB_H += userdiff.h
  LIB_H += utf8.h
  LIB_H += varint.h
 +LIB_H += walker.h
  LIB_H += wildmatch.h
 +LIB_H += wt-status.h
  LIB_H += xdiff-interface.h
  LIB_H += xdiff/xdiff.h
  
@@@ -753,7 -728,6 +756,7 @@@ LIB_OBJS += editor.
  LIB_OBJS += entry.o
  LIB_OBJS += environment.o
  LIB_OBJS += exec_cmd.o
 +LIB_OBJS += fetch-pack.o
  LIB_OBJS += fsck.o
  LIB_OBJS += gettext.o
  LIB_OBJS += gpg-interface.o
@@@ -771,8 -745,7 +774,8 @@@ LIB_OBJS += lockfile.
  LIB_OBJS += log-tree.o
  LIB_OBJS += mailmap.o
  LIB_OBJS += match-trees.o
 -LIB_OBJS += merge-file.o
 +LIB_OBJS += merge.o
 +LIB_OBJS += merge-blobs.o
  LIB_OBJS += merge-recursive.o
  LIB_OBJS += mergesort.o
  LIB_OBJS += name-hash.o
@@@ -790,7 -763,6 +793,7 @@@ LIB_OBJS += parse-options-cb.
  LIB_OBJS += patch-delta.o
  LIB_OBJS += patch-ids.o
  LIB_OBJS += path.o
 +LIB_OBJS += pathspec.o
  LIB_OBJS += pkt-line.o
  LIB_OBJS += preload-index.o
  LIB_OBJS += pretty.o
@@@ -807,7 -779,6 +810,7 @@@ LIB_OBJS += rerere.
  LIB_OBJS += resolve-undo.o
  LIB_OBJS += revision.o
  LIB_OBJS += run-command.o
 +LIB_OBJS += send-pack.o
  LIB_OBJS += sequencer.o
  LIB_OBJS += server-info.o
  LIB_OBJS += setup.o
@@@ -836,7 -807,6 +839,7 @@@ LIB_OBJS += usage.
  LIB_OBJS += userdiff.o
  LIB_OBJS += utf8.o
  LIB_OBJS += varint.o
 +LIB_OBJS += version.o
  LIB_OBJS += walker.o
  LIB_OBJS += wildmatch.o
  LIB_OBJS += wrapper.o
@@@ -856,7 -826,6 +859,7 @@@ BUILTIN_OBJS += builtin/branch.
  BUILTIN_OBJS += builtin/bundle.o
  BUILTIN_OBJS += builtin/cat-file.o
  BUILTIN_OBJS += builtin/check-attr.o
 +BUILTIN_OBJS += builtin/check-ignore.o
  BUILTIN_OBJS += builtin/check-ref-format.o
  BUILTIN_OBJS += builtin/checkout-index.o
  BUILTIN_OBJS += builtin/checkout.o
@@@ -867,7 -836,6 +870,7 @@@ BUILTIN_OBJS += builtin/commit-tree.
  BUILTIN_OBJS += builtin/commit.o
  BUILTIN_OBJS += builtin/config.o
  BUILTIN_OBJS += builtin/count-objects.o
 +BUILTIN_OBJS += builtin/credential.o
  BUILTIN_OBJS += builtin/describe.o
  BUILTIN_OBJS += builtin/diff-files.o
  BUILTIN_OBJS += builtin/diff-index.o
@@@ -945,9 -913,455 +948,9 @@@ BUILTIN_OBJS += builtin/write-tree.
  GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
  EXTLIBS =
  
 -#
 -# Platform specific tweaks
 -#
 -
 -# We choose to avoid "if .. else if .. else .. endif endif"
 -# because maintaining the nesting to match is a pain.  If
 -# we had "elif" things would have been much nicer...
 -
 -ifeq ($(uname_M),x86_64)
 -      XDL_FAST_HASH = YesPlease
 -endif
 -ifeq ($(uname_S),OSF1)
 -      # Need this for u_short definitions et al
 -      BASIC_CFLAGS += -D_OSF_SOURCE
 -      SOCKLEN_T = int
 -      NO_STRTOULL = YesPlease
 -      NO_NSEC = YesPlease
 -endif
 -ifeq ($(uname_S),Linux)
 -      NO_STRLCPY = YesPlease
 -      NO_MKSTEMPS = YesPlease
 -      HAVE_PATHS_H = YesPlease
 -      LIBC_CONTAINS_LIBINTL = YesPlease
 -      HAVE_DEV_TTY = YesPlease
 -endif
 -ifeq ($(uname_S),GNU/kFreeBSD)
 -      NO_STRLCPY = YesPlease
 -      NO_MKSTEMPS = YesPlease
 -      HAVE_PATHS_H = YesPlease
 -      DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
 -      LIBC_CONTAINS_LIBINTL = YesPlease
 -endif
 -ifeq ($(uname_S),UnixWare)
 -      CC = cc
 -      NEEDS_SOCKET = YesPlease
 -      NEEDS_NSL = YesPlease
 -      NEEDS_SSL_WITH_CRYPTO = YesPlease
 -      NEEDS_LIBICONV = YesPlease
 -      SHELL_PATH = /usr/local/bin/bash
 -      NO_IPV6 = YesPlease
 -      NO_HSTRERROR = YesPlease
 -      NO_MKSTEMPS = YesPlease
 -      BASIC_CFLAGS += -Kthread
 -      BASIC_CFLAGS += -I/usr/local/include
 -      BASIC_LDFLAGS += -L/usr/local/lib
 -      INSTALL = ginstall
 -      TAR = gtar
 -      NO_STRCASESTR = YesPlease
 -      NO_MEMMEM = YesPlease
 -endif
 -ifeq ($(uname_S),SCO_SV)
 -      ifeq ($(uname_R),3.2)
 -              CFLAGS = -O2
 -      endif
 -      ifeq ($(uname_R),5)
 -              CC = cc
 -              BASIC_CFLAGS += -Kthread
 -      endif
 -      NEEDS_SOCKET = YesPlease
 -      NEEDS_NSL = YesPlease
 -      NEEDS_SSL_WITH_CRYPTO = YesPlease
 -      NEEDS_LIBICONV = YesPlease
 -      SHELL_PATH = /usr/bin/bash
 -      NO_IPV6 = YesPlease
 -      NO_HSTRERROR = YesPlease
 -      NO_MKSTEMPS = YesPlease
 -      BASIC_CFLAGS += -I/usr/local/include
 -      BASIC_LDFLAGS += -L/usr/local/lib
 -      NO_STRCASESTR = YesPlease
 -      NO_MEMMEM = YesPlease
 -      INSTALL = ginstall
 -      TAR = gtar
 -endif
 -ifeq ($(uname_S),Darwin)
 -      NEEDS_CRYPTO_WITH_SSL = YesPlease
 -      NEEDS_SSL_WITH_CRYPTO = YesPlease
 -      NEEDS_LIBICONV = YesPlease
 -      ifeq ($(shell expr "$(uname_R)" : '[15678]\.'),2)
 -              OLD_ICONV = UnfortunatelyYes
 -      endif
 -      ifeq ($(shell expr "$(uname_R)" : '[15]\.'),2)
 -              NO_STRLCPY = YesPlease
 -      endif
 -      NO_MEMMEM = YesPlease
 -      USE_ST_TIMESPEC = YesPlease
 -      HAVE_DEV_TTY = YesPlease
 -endif
 -ifeq ($(uname_S),SunOS)
 -      NEEDS_SOCKET = YesPlease
 -      NEEDS_NSL = YesPlease
 -      SHELL_PATH = /bin/bash
 -      SANE_TOOL_PATH = /usr/xpg6/bin:/usr/xpg4/bin
 -      NO_STRCASESTR = YesPlease
 -      NO_MEMMEM = YesPlease
 -      NO_MKDTEMP = YesPlease
 -      NO_MKSTEMPS = YesPlease
 -      NO_REGEX = YesPlease
 -      NO_FNMATCH_CASEFOLD = YesPlease
 -      NO_MSGFMT_EXTENDED_OPTIONS = YesPlease
 -      HAVE_DEV_TTY = YesPlease
 -      ifeq ($(uname_R),5.6)
 -              SOCKLEN_T = int
 -              NO_HSTRERROR = YesPlease
 -              NO_IPV6 = YesPlease
 -              NO_SOCKADDR_STORAGE = YesPlease
 -              NO_UNSETENV = YesPlease
 -              NO_SETENV = YesPlease
 -              NO_STRLCPY = YesPlease
 -              NO_STRTOUMAX = YesPlease
 -              GIT_TEST_CMP = cmp
 -      endif
 -      ifeq ($(uname_R),5.7)
 -              NEEDS_RESOLV = YesPlease
 -              NO_IPV6 = YesPlease
 -              NO_SOCKADDR_STORAGE = YesPlease
 -              NO_UNSETENV = YesPlease
 -              NO_SETENV = YesPlease
 -              NO_STRLCPY = YesPlease
 -              NO_STRTOUMAX = YesPlease
 -              GIT_TEST_CMP = cmp
 -      endif
 -      ifeq ($(uname_R),5.8)
 -              NO_UNSETENV = YesPlease
 -              NO_SETENV = YesPlease
 -              NO_STRTOUMAX = YesPlease
 -              GIT_TEST_CMP = cmp
 -      endif
 -      ifeq ($(uname_R),5.9)
 -              NO_UNSETENV = YesPlease
 -              NO_SETENV = YesPlease
 -              NO_STRTOUMAX = YesPlease
 -              GIT_TEST_CMP = cmp
 -      endif
 -      INSTALL = /usr/ucb/install
 -      TAR = gtar
 -      BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__ -DHAVE_ALLOCA_H
 -endif
 -ifeq ($(uname_O),Cygwin)
 -      ifeq ($(shell expr "$(uname_R)" : '1\.[1-6]\.'),4)
 -              NO_D_TYPE_IN_DIRENT = YesPlease
 -              NO_D_INO_IN_DIRENT = YesPlease
 -              NO_STRCASESTR = YesPlease
 -              NO_MEMMEM = YesPlease
 -              NO_MKSTEMPS = YesPlease
 -              NO_SYMLINK_HEAD = YesPlease
 -              NO_IPV6 = YesPlease
 -              OLD_ICONV = UnfortunatelyYes
 -      endif
 -      NO_THREAD_SAFE_PREAD = YesPlease
 -      NEEDS_LIBICONV = YesPlease
 -      NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
 -      NO_TRUSTABLE_FILEMODE = UnfortunatelyYes
 -      NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
 -      # There are conflicting reports about this.
 -      # On some boxes NO_MMAP is needed, and not so elsewhere.
 -      # Try commenting this out if you suspect MMAP is more efficient
 -      NO_MMAP = YesPlease
 -      X = .exe
 -      COMPAT_OBJS += compat/cygwin.o
 -      UNRELIABLE_FSTAT = UnfortunatelyYes
 -      SPARSE_FLAGS = -isystem /usr/include/w32api -Wno-one-bit-signed-bitfield
 -endif
 -ifeq ($(uname_S),FreeBSD)
 -      NEEDS_LIBICONV = YesPlease
 -      OLD_ICONV = YesPlease
 -      NO_MEMMEM = YesPlease
 -      BASIC_CFLAGS += -I/usr/local/include
 -      BASIC_LDFLAGS += -L/usr/local/lib
 -      DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
 -      USE_ST_TIMESPEC = YesPlease
 -      ifeq ($(shell expr "$(uname_R)" : '4\.'),2)
 -              PTHREAD_LIBS = -pthread
 -              NO_UINTMAX_T = YesPlease
 -              NO_STRTOUMAX = YesPlease
 -      endif
 -      PYTHON_PATH = /usr/local/bin/python
 -      HAVE_PATHS_H = YesPlease
 -endif
 -ifeq ($(uname_S),OpenBSD)
 -      NO_STRCASESTR = YesPlease
 -      NO_MEMMEM = YesPlease
 -      USE_ST_TIMESPEC = YesPlease
 -      NEEDS_LIBICONV = YesPlease
 -      BASIC_CFLAGS += -I/usr/local/include
 -      BASIC_LDFLAGS += -L/usr/local/lib
 -      HAVE_PATHS_H = YesPlease
 -endif
 -ifeq ($(uname_S),NetBSD)
 -      ifeq ($(shell expr "$(uname_R)" : '[01]\.'),2)
 -              NEEDS_LIBICONV = YesPlease
 -      endif
 -      BASIC_CFLAGS += -I/usr/pkg/include
 -      BASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib
 -      USE_ST_TIMESPEC = YesPlease
 -      NO_MKSTEMPS = YesPlease
 -      HAVE_PATHS_H = YesPlease
 -endif
 -ifeq ($(uname_S),AIX)
 -      DEFAULT_PAGER = more
 -      NO_STRCASESTR=YesPlease
 -      NO_MEMMEM = YesPlease
 -      NO_MKDTEMP = YesPlease
 -      NO_MKSTEMPS = YesPlease
 -      NO_STRLCPY = YesPlease
 -      NO_NSEC = YesPlease
 -      FREAD_READS_DIRECTORIES = UnfortunatelyYes
 -      INTERNAL_QSORT = UnfortunatelyYes
 -      NEEDS_LIBICONV=YesPlease
 -      BASIC_CFLAGS += -D_LARGE_FILES
 -      ifeq ($(shell expr "$(uname_V)" : '[1234]'),1)
 -              NO_PTHREADS = YesPlease
 -      else
 -              PTHREAD_LIBS = -lpthread
 -      endif
 -      ifeq ($(shell expr "$(uname_V).$(uname_R)" : '5\.1'),3)
 -              INLINE=''
 -      endif
 -      GIT_TEST_CMP = cmp
 -endif
 -ifeq ($(uname_S),GNU)
 -      # GNU/Hurd
 -      NO_STRLCPY=YesPlease
 -      NO_MKSTEMPS = YesPlease
 -      HAVE_PATHS_H = YesPlease
 -      LIBC_CONTAINS_LIBINTL = YesPlease
 -endif
 -ifeq ($(uname_S),IRIX)
 -      NO_SETENV = YesPlease
 -      NO_UNSETENV = YesPlease
 -      NO_STRCASESTR = YesPlease
 -      NO_MEMMEM = YesPlease
 -      NO_MKSTEMPS = YesPlease
 -      NO_MKDTEMP = YesPlease
 -      # When compiled with the MIPSpro 7.4.4m compiler, and without pthreads
 -      # (i.e. NO_PTHREADS is set), and _with_ MMAP (i.e. NO_MMAP is not set),
 -      # git dies with a segmentation fault when trying to access the first
 -      # entry of a reflog.  The conservative choice is made to always set
 -      # NO_MMAP.  If you suspect that your compiler is not affected by this
 -      # issue, comment out the NO_MMAP statement.
 -      NO_MMAP = YesPlease
 -      NO_REGEX = YesPlease
 -      NO_FNMATCH_CASEFOLD = YesPlease
 -      SNPRINTF_RETURNS_BOGUS = YesPlease
 -      SHELL_PATH = /usr/gnu/bin/bash
 -      NEEDS_LIBGEN = YesPlease
 -endif
 -ifeq ($(uname_S),IRIX64)
 -      NO_SETENV=YesPlease
 -      NO_UNSETENV = YesPlease
 -      NO_STRCASESTR=YesPlease
 -      NO_MEMMEM = YesPlease
 -      NO_MKSTEMPS = YesPlease
 -      NO_MKDTEMP = YesPlease
 -      # When compiled with the MIPSpro 7.4.4m compiler, and without pthreads
 -      # (i.e. NO_PTHREADS is set), and _with_ MMAP (i.e. NO_MMAP is not set),
 -      # git dies with a segmentation fault when trying to access the first
 -      # entry of a reflog.  The conservative choice is made to always set
 -      # NO_MMAP.  If you suspect that your compiler is not affected by this
 -      # issue, comment out the NO_MMAP statement.
 -      NO_MMAP = YesPlease
 -      NO_REGEX = YesPlease
 -      NO_FNMATCH_CASEFOLD = YesPlease
 -      SNPRINTF_RETURNS_BOGUS = YesPlease
 -      SHELL_PATH=/usr/gnu/bin/bash
 -      NEEDS_LIBGEN = YesPlease
 -endif
 -ifeq ($(uname_S),HP-UX)
 -      INLINE = __inline
 -      NO_IPV6=YesPlease
 -      NO_SETENV=YesPlease
 -      NO_STRCASESTR=YesPlease
 -      NO_MEMMEM = YesPlease
 -      NO_MKSTEMPS = YesPlease
 -      NO_STRLCPY = YesPlease
 -      NO_MKDTEMP = YesPlease
 -      NO_UNSETENV = YesPlease
 -      NO_HSTRERROR = YesPlease
 -      NO_SYS_SELECT_H = YesPlease
 -      NO_FNMATCH_CASEFOLD = YesPlease
 -      SNPRINTF_RETURNS_BOGUS = YesPlease
 -      NO_NSEC = YesPlease
 -      ifeq ($(uname_R),B.11.00)
 -              NO_INET_NTOP = YesPlease
 -              NO_INET_PTON = YesPlease
 -      endif
 -      ifeq ($(uname_R),B.10.20)
 -              # Override HP-UX 11.x setting:
 -              INLINE =
 -              SOCKLEN_T = size_t
 -              NO_PREAD = YesPlease
 -              NO_INET_NTOP = YesPlease
 -              NO_INET_PTON = YesPlease
 -      endif
 -      GIT_TEST_CMP = cmp
 -endif
 -ifeq ($(uname_S),Windows)
 -      GIT_VERSION := $(GIT_VERSION).MSVC
 -      pathsep = ;
 -      NO_PREAD = YesPlease
 -      NEEDS_CRYPTO_WITH_SSL = YesPlease
 -      NO_LIBGEN_H = YesPlease
 -      NO_SYS_POLL_H = YesPlease
 -      NO_SYMLINK_HEAD = YesPlease
 -      NO_IPV6 = YesPlease
 -      NO_UNIX_SOCKETS = YesPlease
 -      NO_SETENV = YesPlease
 -      NO_UNSETENV = YesPlease
 -      NO_STRCASESTR = YesPlease
 -      NO_STRLCPY = YesPlease
 -      NO_STRTOK_R = YesPlease
 -      NO_FNMATCH = YesPlease
 -      NO_MEMMEM = YesPlease
 -      # NEEDS_LIBICONV = YesPlease
 -      NO_ICONV = YesPlease
 -      NO_STRTOUMAX = YesPlease
 -      NO_STRTOULL = YesPlease
 -      NO_MKDTEMP = YesPlease
 -      NO_MKSTEMPS = YesPlease
 -      SNPRINTF_RETURNS_BOGUS = YesPlease
 -      NO_SVN_TESTS = YesPlease
 -      NO_PERL_MAKEMAKER = YesPlease
 -      RUNTIME_PREFIX = YesPlease
 -      NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
 -      NO_NSEC = YesPlease
 -      USE_WIN32_MMAP = YesPlease
 -      # USE_NED_ALLOCATOR = YesPlease
 -      UNRELIABLE_FSTAT = UnfortunatelyYes
 -      OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
 -      NO_REGEX = YesPlease
 -      NO_CURL = YesPlease
 -      NO_PYTHON = YesPlease
 -      BLK_SHA1 = YesPlease
 -      NO_POSIX_GOODIES = UnfortunatelyYes
 -      NATIVE_CRLF = YesPlease
 -
 -      CC = compat/vcbuild/scripts/clink.pl
 -      AR = compat/vcbuild/scripts/lib.pl
 -      CFLAGS =
 -      BASIC_CFLAGS = -nologo -I. -I../zlib -Icompat/vcbuild -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE
 -      COMPAT_OBJS = compat/msvc.o compat/winansi.o \
 -              compat/win32/pthread.o compat/win32/syslog.o \
 -              compat/win32/poll.o compat/win32/dirent.o
 -      COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
 -      BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib
 -      EXTLIBS = user32.lib advapi32.lib shell32.lib wininet.lib ws2_32.lib
 -      PTHREAD_LIBS =
 -      lib =
 -ifndef DEBUG
 -      BASIC_CFLAGS += -GL -Os -MT
 -      BASIC_LDFLAGS += -LTCG
 -      AR += -LTCG
 -else
 -      BASIC_CFLAGS += -Zi -MTd
 -endif
 -      X = .exe
 -endif
 -ifeq ($(uname_S),Interix)
 -      NO_INITGROUPS = YesPlease
 -      NO_IPV6 = YesPlease
 -      NO_MEMMEM = YesPlease
 -      NO_MKDTEMP = YesPlease
 -      NO_STRTOUMAX = YesPlease
 -      NO_NSEC = YesPlease
 -      NO_MKSTEMPS = YesPlease
 -      ifeq ($(uname_R),3.5)
 -              NO_INET_NTOP = YesPlease
 -              NO_INET_PTON = YesPlease
 -              NO_SOCKADDR_STORAGE = YesPlease
 -              NO_FNMATCH_CASEFOLD = YesPlease
 -      endif
 -      ifeq ($(uname_R),5.2)
 -              NO_INET_NTOP = YesPlease
 -              NO_INET_PTON = YesPlease
 -              NO_SOCKADDR_STORAGE = YesPlease
 -              NO_FNMATCH_CASEFOLD = YesPlease
 -      endif
 -endif
 -ifeq ($(uname_S),Minix)
 -      NO_IPV6 = YesPlease
 -      NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
 -      NO_NSEC = YesPlease
 -      NEEDS_LIBGEN =
 -      NEEDS_CRYPTO_WITH_SSL = YesPlease
 -      NEEDS_IDN_WITH_CURL = YesPlease
 -      NEEDS_SSL_WITH_CURL = YesPlease
 -      NEEDS_RESOLV =
 -      NO_HSTRERROR = YesPlease
 -      NO_MMAP = YesPlease
 -      NO_CURL =
 -      NO_EXPAT =
 -endif
 -ifneq (,$(findstring MINGW,$(uname_S)))
 -      pathsep = ;
 -      NO_PREAD = YesPlease
 -      NEEDS_CRYPTO_WITH_SSL = YesPlease
 -      NO_LIBGEN_H = YesPlease
 -      NO_SYS_POLL_H = YesPlease
 -      NO_SYMLINK_HEAD = YesPlease
 -      NO_UNIX_SOCKETS = YesPlease
 -      NO_SETENV = YesPlease
 -      NO_UNSETENV = YesPlease
 -      NO_STRCASESTR = YesPlease
 -      NO_STRLCPY = YesPlease
 -      NO_STRTOK_R = YesPlease
 -      NO_FNMATCH = YesPlease
 -      NO_MEMMEM = YesPlease
 -      NEEDS_LIBICONV = YesPlease
 -      OLD_ICONV = YesPlease
 -      NO_STRTOUMAX = YesPlease
 -      NO_MKDTEMP = YesPlease
 -      NO_MKSTEMPS = YesPlease
 -      NO_SVN_TESTS = YesPlease
 -      NO_PERL_MAKEMAKER = YesPlease
 -      RUNTIME_PREFIX = YesPlease
 -      NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
 -      NO_NSEC = YesPlease
 -      USE_WIN32_MMAP = YesPlease
 -      USE_NED_ALLOCATOR = YesPlease
 -      UNRELIABLE_FSTAT = UnfortunatelyYes
 -      OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
 -      NO_REGEX = YesPlease
 -      NO_PYTHON = YesPlease
 -      BLK_SHA1 = YesPlease
 -      ETAGS_TARGET = ETAGS
 -      NO_INET_PTON = YesPlease
 -      NO_INET_NTOP = YesPlease
 -      NO_POSIX_GOODIES = UnfortunatelyYes
 -      COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/win32
 -      COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
 -      COMPAT_OBJS += compat/mingw.o compat/winansi.o \
 -              compat/win32/pthread.o compat/win32/syslog.o \
 -              compat/win32/poll.o compat/win32/dirent.o
 -      EXTLIBS += -lws2_32
 -      PTHREAD_LIBS =
 -      X = .exe
 -      SPARSE_FLAGS = -Wno-one-bit-signed-bitfield
 -ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
 -      htmldir=doc/git/html/
 -      prefix =
 -      INSTALL = /bin/install
 -      EXTLIBS += /mingw/lib/libz.a
 -      NO_R_TO_GCC_LINKER = YesPlease
 -      INTERNAL_QSORT = YesPlease
 -      HAVE_LIBCHARSET_H = YesPlease
 -else
 -      NO_CURL = YesPlease
 -endif
 -endif
 +GIT_USER_AGENT = git/$(GIT_VERSION)
  
 +include config.mak.uname
  -include config.mak.autogen
  -include config.mak
  
@@@ -1058,7 -1472,7 +1061,7 @@@ els
                CURL_LIBCURL = -lcurl
        endif
        ifdef NEEDS_SSL_WITH_CURL
 -              CURL_LIBCURL += -lssl
 +              CURL_LIBCURL += -lssl
                ifdef NEEDS_CRYPTO_WITH_SSL
                        CURL_LIBCURL += -lcrypto
                endif
        REMOTE_CURL_NAMES = $(REMOTE_CURL_PRIMARY) $(REMOTE_CURL_ALIASES)
        PROGRAM_OBJS += http-fetch.o
        PROGRAMS += $(REMOTE_CURL_NAMES)
 -      curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p)
 +      curl_check := $(shell (echo 070908; curl-config --vernum) 2>/dev/null | sort -r | sed -ne 2p)
        ifeq "$(curl_check)" "070908"
                ifndef NO_EXPAT
                        PROGRAM_OBJS += http-push.o
@@@ -1126,9 -1540,6 +1129,9 @@@ ifdef NEEDS_LIBICON
        else
                ICONV_LINK =
        endif
 +      ifdef NEEDS_LIBINTL_BEFORE_LIBICONV
 +              ICONV_LINK += -lintl
 +      endif
        EXTLIBS += $(ICONV_LINK) -liconv
  endif
  ifdef NEEDS_LIBGEN
@@@ -1154,9 -1565,6 +1157,9 @@@ endi
  ifdef NO_D_INO_IN_DIRENT
        BASIC_CFLAGS += -DNO_D_INO_IN_DIRENT
  endif
 +ifdef NO_GECOS_IN_PWENT
 +      BASIC_CFLAGS += -DNO_GECOS_IN_PWENT
 +endif
  ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
        BASIC_CFLAGS += -DNO_ST_BLOCKS_IN_STRUCT_STAT
  endif
@@@ -1190,11 -1598,6 +1193,11 @@@ ifdef NO_GETTEX
        BASIC_CFLAGS += -DNO_GETTEXT
        USE_GETTEXT_SCHEME ?= fallthrough
  endif
 +ifdef NO_POLL
 +      NO_SYS_POLL_H = YesPlease
 +      COMPAT_CFLAGS += -DNO_POLL -Icompat/poll
 +      COMPAT_OBJS += compat/poll/poll.o
 +endif
  ifdef NO_STRCASESTR
        COMPAT_CFLAGS += -DNO_STRCASESTR
        COMPAT_OBJS += compat/strcasestr.o
@@@ -1225,6 -1628,9 +1228,9 @@@ ifdef NO_FNMATCH_CASEFOL
        COMPAT_OBJS += compat/fnmatch/fnmatch.o
  endif
  endif
+ ifdef USE_WILDMATCH
+       COMPAT_CFLAGS += -DUSE_WILDMATCH
+ endif
  ifdef NO_SETENV
        COMPAT_CFLAGS += -DNO_SETENV
        COMPAT_OBJS += compat/setenv.o
@@@ -1233,10 -1639,6 +1239,10 @@@ ifdef NO_MKDTEM
        COMPAT_CFLAGS += -DNO_MKDTEMP
        COMPAT_OBJS += compat/mkdtemp.o
  endif
 +ifdef MKDIR_WO_TRAILING_SLASH
 +      COMPAT_CFLAGS += -DMKDIR_WO_TRAILING_SLASH
 +      COMPAT_OBJS += compat/mkdir.o
 +endif
  ifdef NO_MKSTEMPS
        COMPAT_CFLAGS += -DNO_MKSTEMPS
  endif
@@@ -1250,9 -1652,6 +1256,9 @@@ endi
  ifdef NO_SYS_POLL_H
        BASIC_CFLAGS += -DNO_SYS_POLL_H
  endif
 +ifdef NEEDS_SYS_PARAM_H
 +      BASIC_CFLAGS += -DNEEDS_SYS_PARAM_H
 +endif
  ifdef NO_INTTYPES_H
        BASIC_CFLAGS += -DNO_INTTYPES_H
  endif
@@@ -1271,13 -1670,6 +1277,13 @@@ endi
  ifdef OBJECT_CREATION_USES_RENAMES
        COMPAT_CFLAGS += -DOBJECT_CREATION_MODE=1
  endif
 +ifdef NO_STRUCT_ITIMERVAL
 +      COMPAT_CFLAGS += -DNO_STRUCT_ITIMERVAL
 +      NO_SETITIMER = YesPlease
 +endif
 +ifdef NO_SETITIMER
 +      COMPAT_CFLAGS += -DNO_SETITIMER
 +endif
  ifdef NO_PREAD
        COMPAT_CFLAGS += -DNO_PREAD
        COMPAT_OBJS += compat/pread.o
@@@ -1295,9 -1687,6 +1301,9 @@@ endi
  ifdef NO_IPV6
        BASIC_CFLAGS += -DNO_IPV6
  endif
 +ifdef NO_INTPTR_T
 +      COMPAT_CFLAGS += -DNO_INTPTR_T
 +endif
  ifdef NO_UINTMAX_T
        BASIC_CFLAGS += -Duintmax_t=uint32_t
  endif
@@@ -1364,9 -1753,6 +1370,9 @@@ ifdef NO_MEMME
        COMPAT_CFLAGS += -DNO_MEMMEM
        COMPAT_OBJS += compat/memmem.o
  endif
 +ifdef NO_GETPAGESIZE
 +      COMPAT_CFLAGS += -DNO_GETPAGESIZE
 +endif
  ifdef INTERNAL_QSORT
        COMPAT_CFLAGS += -DINTERNAL_QSORT
        COMPAT_OBJS += compat/qsort.o
@@@ -1392,10 -1778,6 +1398,10 @@@ ifdef HAVE_LIBCHARSET_
        EXTLIBS += $(CHARSET_LIB)
  endif
  
 +ifdef HAVE_STRINGS_H
 +      BASIC_CFLAGS += -DHAVE_STRINGS_H
 +endif
 +
  ifdef HAVE_DEV_TTY
        BASIC_CFLAGS += -DHAVE_DEV_TTY
  endif
@@@ -1410,9 -1792,6 +1416,9 @@@ ifdef NO_REGE
        COMPAT_CFLAGS += -Icompat/regex
        COMPAT_OBJS += compat/regex/regex.o
  endif
 +ifdef CYGWIN_V15_WIN32API
 +      COMPAT_CFLAGS += -DCYGWIN_V15_WIN32API
 +endif
  
  ifdef USE_NED_ALLOCATOR
         COMPAT_CFLAGS += -Icompat/nedmalloc
@@@ -1432,15 -1811,15 +1438,15 @@@ ifneq (,$(XDL_FAST_HASH)
  endif
  
  ifeq ($(TCLTK_PATH),)
 -NO_TCLTK=NoThanks
 +NO_TCLTK = NoThanks
  endif
  
  ifeq ($(PERL_PATH),)
 -NO_PERL=NoThanks
 +NO_PERL = NoThanks
  endif
  
  ifeq ($(PYTHON_PATH),)
 -NO_PYTHON=NoThanks
 +NO_PYTHON = NoThanks
  endif
  
  QUIET_SUBDIR0  = +$(MAKE) -C # space to separate -C and subdir
@@@ -1473,6 -1852,10 +1479,6 @@@ ifndef 
  endif
  endif
  
 -ifdef ASCIIDOC7
 -      export ASCIIDOC7
 -endif
 -
  ifdef NO_INSTALL_HARDLINKS
        export NO_INSTALL_HARDLINKS
  endif
@@@ -1487,13 -1870,13 +1493,13 @@@ PROFILE_DIR := $(CURDIR
  ifeq ("$(PROFILE)","GEN")
        CFLAGS += -fprofile-generate=$(PROFILE_DIR) -DNO_NORETURN=1
        EXTLIBS += -lgcov
 -      export CCACHE_DISABLE=t
 -      V=1
 +      export CCACHE_DISABLE = t
 +      V = 1
  else
  ifneq ("$(PROFILE)","")
        CFLAGS += -fprofile-use=$(PROFILE_DIR) -fprofile-correction -DNO_NORETURN=1
 -      export CCACHE_DISABLE=t
 -      V=1
 +      export CCACHE_DISABLE = t
 +      V = 1
  endif
  endif
  
@@@ -1550,18 -1933,6 +1556,18 @@@ SHELL_PATH_CQ_SQ = $(subst ','\'',$(SHE
  BASIC_CFLAGS += -DSHELL_PATH='$(SHELL_PATH_CQ_SQ)'
  endif
  
 +GIT_USER_AGENT_SQ = $(subst ','\'',$(GIT_USER_AGENT))
 +GIT_USER_AGENT_CQ = "$(subst ",\",$(subst \,\\,$(GIT_USER_AGENT)))"
 +GIT_USER_AGENT_CQ_SQ = $(subst ','\'',$(GIT_USER_AGENT_CQ))
 +GIT-USER-AGENT: FORCE
 +      @if test x'$(GIT_USER_AGENT_SQ)' != x"`cat GIT-USER-AGENT 2>/dev/null`"; then \
 +              echo '$(GIT_USER_AGENT_SQ)' >GIT-USER-AGENT; \
 +      fi
 +
 +ifdef DEFAULT_HELP_FORMAT
 +BASIC_CFLAGS += -DDEFAULT_HELP_FORMAT='"$(DEFAULT_HELP_FORMAT)"'
 +endif
 +
  ALL_CFLAGS += $(BASIC_CFLAGS)
  ALL_LDFLAGS += $(BASIC_LDFLAGS)
  
@@@ -1608,41 -1979,8 +1614,41 @@@ shell_compatibility_test: please_set_SH
  strip: $(PROGRAMS) git$X
        $(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X
  
 -git.o: common-cmds.h
 -git.sp git.s git.o: EXTRA_CPPFLAGS = -DGIT_VERSION='"$(GIT_VERSION)"' \
 +### Target-specific flags and dependencies
 +
 +# The generic compilation pattern rule and automatically
 +# computed header dependencies (falling back to a dependency on
 +# LIB_H) are enough to describe how most targets should be built,
 +# but some targets are special enough to need something a little
 +# different.
 +#
 +# - When a source file "foo.c" #includes a generated header file,
 +#   we need to list that dependency for the "foo.o" target.
 +#
 +#   We also list it from other targets that are built from foo.c
 +#   like "foo.sp" and "foo.s", even though that is easy to forget
 +#   to do because the generated header is already present around
 +#   after a regular build attempt.
 +#
 +# - Some code depends on configuration kept in makefile
 +#   variables. The target-specific variable EXTRA_CPPFLAGS can
 +#   be used to convey that information to the C preprocessor
 +#   using -D options.
 +#
 +#   The "foo.o" target should have a corresponding dependency on
 +#   a file that changes when the value of the makefile variable
 +#   changes.  For example, targets making use of the
 +#   $(GIT_VERSION) variable depend on GIT-VERSION-FILE.
 +#
 +#   Technically the ".sp" and ".s" targets do not need this
 +#   dependency because they are force-built, but they get the
 +#   same dependency for consistency. This way, you do not have to
 +#   know how each target is implemented. And it means the
 +#   dependencies here will not need to change if the force-build
 +#   details change some day.
 +
 +git.sp git.s git.o: GIT-PREFIX
 +git.sp git.s git.o: EXTRA_CPPFLAGS = \
        '-DGIT_HTML_PATH="$(htmldir_SQ)"' \
        '-DGIT_MAN_PATH="$(mandir_SQ)"' \
        '-DGIT_INFO_PATH="$(infodir_SQ)"'
@@@ -1651,19 -1989,14 +1657,19 @@@ git$X: git.o GIT-LDFLAGS $(BUILTIN_OBJS
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ git.o \
                $(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
  
 -help.sp help.o: common-cmds.h
 +help.sp help.s help.o: common-cmds.h
  
 -builtin/help.sp builtin/help.o: common-cmds.h
 +builtin/help.sp builtin/help.s builtin/help.o: common-cmds.h GIT-PREFIX
  builtin/help.sp builtin/help.s builtin/help.o: EXTRA_CPPFLAGS = \
        '-DGIT_HTML_PATH="$(htmldir_SQ)"' \
        '-DGIT_MAN_PATH="$(mandir_SQ)"' \
        '-DGIT_INFO_PATH="$(infodir_SQ)"'
  
 +version.sp version.s version.o: GIT-VERSION-FILE GIT-USER-AGENT
 +version.sp version.s version.o: EXTRA_CPPFLAGS = \
 +      '-DGIT_VERSION="$(GIT_VERSION)"' \
 +      '-DGIT_USER_AGENT=$(GIT_USER_AGENT_CQ_SQ)'
 +
  $(BUILT_INS): git$X
        $(QUIET_BUILT_IN)$(RM) $@ && \
        ln git$X $@ 2>/dev/null || \
@@@ -1675,54 -2008,35 +1681,54 @@@ common-cmds.h: ./generate-cmdlist.sh co
  common-cmds.h: $(wildcard Documentation/git-*.txt)
        $(QUIET_GEN)./generate-cmdlist.sh > $@+ && mv $@+ $@
  
 +SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\
 +      $(localedir_SQ):$(NO_CURL):$(USE_GETTEXT_SCHEME):$(SANE_TOOL_PATH_SQ):\
 +      $(gitwebdir_SQ):$(PERL_PATH_SQ)
  define cmd_munge_script
  $(RM) $@ $@+ && \
  sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
      -e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \
      -e 's|@@DIFF@@|$(DIFF_SQ)|' \
 -    -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
      -e 's|@@LOCALEDIR@@|$(localedir_SQ)|g' \
      -e 's/@@NO_CURL@@/$(NO_CURL)/g' \
      -e 's/@@USE_GETTEXT_SCHEME@@/$(USE_GETTEXT_SCHEME)/g' \
      -e $(BROKEN_PATH_FIX) \
 +    -e 's|@@GITWEBDIR@@|$(gitwebdir_SQ)|g' \
 +    -e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \
      $@.sh >$@+
  endef
  
 -$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
 +GIT-SCRIPT-DEFINES: FORCE
 +      @FLAGS='$(SCRIPT_DEFINES)'; \
 +          if test x"$$FLAGS" != x"`cat $@ 2>/dev/null`" ; then \
 +              echo >&2 "    * new script parameters"; \
 +              echo "$$FLAGS" >$@; \
 +            fi
 +
 +
 +$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh GIT-SCRIPT-DEFINES
        $(QUIET_GEN)$(cmd_munge_script) && \
        chmod +x $@+ && \
        mv $@+ $@
  
 -$(SCRIPT_LIB) : % : %.sh
 +$(SCRIPT_LIB) : % : %.sh GIT-SCRIPT-DEFINES
        $(QUIET_GEN)$(cmd_munge_script) && \
        mv $@+ $@
  
  ifndef NO_PERL
  $(patsubst %.perl,%,$(SCRIPT_PERL)): perl/perl.mak
  
 -perl/perl.mak: GIT-CFLAGS perl/Makefile perl/Makefile.PL
 +perl/perl.mak: perl/PM.stamp
 +
 +perl/PM.stamp: FORCE
 +      $(QUIET_GEN)$(FIND) perl -type f -name '*.pm' | sort >$@+ && \
 +      { cmp $@+ $@ >/dev/null 2>/dev/null || mv $@+ $@; } && \
 +      $(RM) $@+
 +
 +perl/perl.mak: GIT-CFLAGS GIT-PREFIX perl/Makefile perl/Makefile.PL
        $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' $(@F)
  
 -$(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl
 +$(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl GIT-VERSION-FILE
        $(QUIET_GEN)$(RM) $@ $@+ && \
        INSTLIBDIR=`MAKEFLAGS= $(MAKE) -C perl -s --no-print-directory instlibdir` && \
        sed -e '1{' \
  gitweb:
        $(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) all
  
 -git-instaweb: git-instaweb.sh gitweb
 -      $(QUIET_GEN)$(RM) $@ $@+ && \
 -      sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
 -          -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
 -          -e 's/@@NO_CURL@@/$(NO_CURL)/g' \
 -          -e 's|@@GITWEBDIR@@|$(gitwebdir_SQ)|g' \
 -          -e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \
 -          $@.sh > $@+ && \
 +git-instaweb: git-instaweb.sh gitweb GIT-SCRIPT-DEFINES
 +      $(QUIET_GEN)$(cmd_munge_script) && \
        chmod +x $@+ && \
        mv $@+ $@
  else # NO_PERL
@@@ -1757,7 -2077,7 +1763,7 @@@ $(patsubst %.perl,%,$(SCRIPT_PERL)) git
  endif # NO_PERL
  
  ifndef NO_PYTHON
 -$(patsubst %.py,%,$(SCRIPT_PYTHON)): GIT-CFLAGS
 +$(patsubst %.py,%,$(SCRIPT_PYTHON)): GIT-CFLAGS GIT-PREFIX GIT-PYTHON-VARS
  $(patsubst %.py,%,$(SCRIPT_PYTHON)): % : %.py
        $(QUIET_GEN)$(RM) $@ $@+ && \
        INSTLIBDIR=`MAKEFLAGS= $(MAKE) -C git_remote_helpers -s \
@@@ -1779,29 -2099,24 +1785,29 @@@ $(patsubst %.py,%,$(SCRIPT_PYTHON)): % 
        mv $@+ $@
  endif # NO_PYTHON
  
 -configure: configure.ac
 +configure: configure.ac GIT-VERSION-FILE
        $(QUIET_GEN)$(RM) $@ $<+ && \
        sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
            $< > $<+ && \
        autoconf -o $@ $<+ && \
        $(RM) $<+
  
 -# These can record GIT_VERSION
 -git.o git.spec http.o \
 -      $(patsubst %.sh,%,$(SCRIPT_SH)) \
 -      $(patsubst %.perl,%,$(SCRIPT_PERL)) \
 -      : GIT-VERSION-FILE
 -
 -TEST_OBJS := $(patsubst test-%$X,test-%.o,$(TEST_PROGRAMS))
 -GIT_OBJS := $(LIB_OBJS) $(BUILTIN_OBJS) $(PROGRAM_OBJS) $(TEST_OBJS) \
 -      git.o
 -ifndef NO_CURL
 -      GIT_OBJS += http.o http-walker.o remote-curl.o
 +ifdef AUTOCONFIGURED
 +# We avoid depending on 'configure' here, because it gets rebuilt
 +# every time GIT-VERSION-FILE is modified, only to update the embedded
 +# version number string, which config.status does not care about.  We
 +# do want to recheck when the platform/environment detection logic
 +# changes, hence this depends on configure.ac.
 +config.status: configure.ac
 +      $(QUIET_GEN)$(MAKE) configure && \
 +      if test -f config.status; then \
 +        ./config.status --recheck; \
 +      else \
 +        ./configure; \
 +      fi
 +reconfigure config.mak.autogen: config.status
 +      $(QUIET_GEN)./config.status
 +.PHONY: reconfigure # This is a convenience target.
  endif
  
  XDIFF_OBJS += xdiff/xdiffi.o
@@@ -1819,14 -2134,9 +1825,14 @@@ VCSSVN_OBJS += vcs-svn/fast_export.
  VCSSVN_OBJS += vcs-svn/svndiff.o
  VCSSVN_OBJS += vcs-svn/svndump.o
  
 -VCSSVN_TEST_OBJS += test-line-buffer.o
 -
 -OBJECTS := $(GIT_OBJS) $(XDIFF_OBJS) $(VCSSVN_OBJS)
 +TEST_OBJS := $(patsubst test-%$X,test-%.o,$(TEST_PROGRAMS))
 +OBJECTS := $(LIB_OBJS) $(BUILTIN_OBJS) $(PROGRAM_OBJS) $(TEST_OBJS) \
 +      $(XDIFF_OBJS) \
 +      $(VCSSVN_OBJS) \
 +      git.o
 +ifndef NO_CURL
 +      OBJECTS += http.o http-walker.o remote-curl.o
 +endif
  
  dep_files := $(foreach f,$(OBJECTS),$(dir $f).depend/$(notdir $f).d)
  dep_dirs := $(addsuffix .depend,$(sort $(dir $(OBJECTS))))
  # Dependencies on automatically generated headers such as common-cmds.h
  # should _not_ be included here, since they are necessary even when
  # building an object for the first time.
 -#
 -# XXX. Please check occasionally that these include all dependencies
 -# gcc detects!
 -
 -$(GIT_OBJS): $(LIB_H)
 -builtin/branch.o builtin/checkout.o builtin/clone.o builtin/reset.o branch.o transport.o: branch.h
 -builtin/bundle.o bundle.o transport.o: bundle.h
 -builtin/bisect--helper.o builtin/rev-list.o bisect.o: bisect.h
 -builtin/clone.o builtin/fetch-pack.o transport.o: fetch-pack.h
 -builtin/index-pack.o builtin/grep.o builtin/pack-objects.o transport-helper.o thread-utils.o: thread-utils.h
 -builtin/send-pack.o transport.o: send-pack.h
 -builtin/log.o builtin/shortlog.o: shortlog.h
 -builtin/prune.o builtin/reflog.o reachable.o: reachable.h
 -builtin/commit.o builtin/revert.o wt-status.o: wt-status.h
 -builtin/tar-tree.o archive-tar.o: tar.h
 -connect.o transport.o url.o http-backend.o: url.h
 -builtin/branch.o builtin/commit.o builtin/tag.o column.o help.o pager.o: column.h
 -http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h
 -http.o http-walker.o http-push.o http-fetch.o remote-curl.o: http.h url.h
  
 -xdiff-interface.o $(XDIFF_OBJS): $(XDIFF_H)
 -
 -$(VCSSVN_OBJS) $(VCSSVN_TEST_OBJS): $(LIB_H) $(VCSSVN_H)
 +$(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 = \
        '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' \
        '-DBINDIR="$(bindir_relative_SQ)"' \
        '-DPREFIX="$(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 = \
        -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"'
  
 +config.sp config.s config.o: GIT-PREFIX
  config.sp config.s config.o: EXTRA_CPPFLAGS = \
        -DETC_GITCONFIG='"$(ETC_GITCONFIG_SQ)"'
  
 +attr.sp attr.s attr.o: GIT-PREFIX
  attr.sp attr.s attr.o: EXTRA_CPPFLAGS = \
        -DETC_GITATTRIBUTES='"$(ETC_GITATTRIBUTES_SQ)"'
  
 +gettext.sp gettext.s gettext.o: GIT-PREFIX
  gettext.sp gettext.s gettext.o: EXTRA_CPPFLAGS = \
        -DGIT_LOCALE_PATH='"$(localedir_SQ)"'
  
 -http.sp http.s http.o: EXTRA_CPPFLAGS = \
 -      -DGIT_HTTP_USER_AGENT='"git/$(GIT_VERSION)"'
 -
  ifdef NO_EXPAT
  http-walker.sp http-walker.s http-walker.o: EXTRA_CPPFLAGS = -DNO_EXPAT
  endif
@@@ -1979,10 -2308,6 +1985,10 @@@ git-http-push$X: revision.o http.o http
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
                $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
  
 +git-remote-testsvn$X: remote-testsvn.o GIT-LDFLAGS $(GITLIBS) $(VCSSVN_LIB)
 +      $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) \
 +      $(VCSSVN_LIB)
 +
  $(REMOTE_CURL_ALIASES): $(REMOTE_CURL_PRIMARY)
        $(QUIET_LNCP)$(RM) $@ && \
        ln $< $@ 2>/dev/null || \
@@@ -2026,10 -2351,9 +2032,10 @@@ XGETTEXT_FLAGS = 
        --from-code=UTF-8
  XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --language=C \
        --keyword=_ --keyword=N_ --keyword="Q_:1,2"
 -XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell
 +XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell \
 +      --keyword=gettextln --keyword=eval_gettextln
  XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --keyword=__ --language=Perl
 -LOCALIZED_C := $(C_OBJ:o=c) $(LIB_H) $(XDIFF_H) $(VCSSVN_H) $(MISC_H)
 +LOCALIZED_C := $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)
  LOCALIZED_SH := $(SCRIPT_SH)
  LOCALIZED_PERL := $(SCRIPT_PERL)
  
@@@ -2076,22 -2400,14 +2082,22 @@@ cscope
        $(FIND_SOURCE_FILES) | xargs cscope -b
  
  ### Detect prefix changes
 -TRACK_CFLAGS = $(CC):$(subst ','\'',$(ALL_CFLAGS)):\
 -             $(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ):\
 -             $(localedir_SQ):$(USE_GETTEXT_SCHEME)
 +TRACK_PREFIX = $(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ):\
 +              $(localedir_SQ)
 +
 +GIT-PREFIX: FORCE
 +      @FLAGS='$(TRACK_PREFIX)'; \
 +      if test x"$$FLAGS" != x"`cat GIT-PREFIX 2>/dev/null`" ; then \
 +              echo >&2 "    * new prefix flags"; \
 +              echo "$$FLAGS" >GIT-PREFIX; \
 +      fi
 +
 +TRACK_CFLAGS = $(CC):$(subst ','\'',$(ALL_CFLAGS)):$(USE_GETTEXT_SCHEME)
  
  GIT-CFLAGS: FORCE
        @FLAGS='$(TRACK_CFLAGS)'; \
            if test x"$$FLAGS" != x"`cat GIT-CFLAGS 2>/dev/null`" ; then \
 -              echo 1>&2 "    * new build flags or prefix"; \
 +              echo >&2 "    * new build flags"; \
                echo "$$FLAGS" >GIT-CFLAGS; \
              fi
  
@@@ -2100,7 -2416,7 +2106,7 @@@ TRACK_LDFLAGS = $(subst ','\'',$(ALL_LD
  GIT-LDFLAGS: FORCE
        @FLAGS='$(TRACK_LDFLAGS)'; \
            if test x"$$FLAGS" != x"`cat GIT-LDFLAGS 2>/dev/null`" ; then \
 -              echo 1>&2 "    * new link flags"; \
 +              echo >&2 "    * new link flags"; \
                echo "$$FLAGS" >GIT-LDFLAGS; \
              fi
  
@@@ -2142,14 -2458,14 +2148,14 @@@ ifdef GIT_PERF_MAKE_OPT
        @echo GIT_PERF_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_PERF_MAKE_OPTS)))'\' >>$@
  endif
  
 -### Detect Tck/Tk interpreter path changes
 -ifndef NO_TCLTK
 -TRACK_VARS = $(subst ','\'',-DTCLTK_PATH='$(TCLTK_PATH_SQ)')
 +### Detect Python interpreter path changes
 +ifndef NO_PYTHON
 +TRACK_PYTHON = $(subst ','\'',-DPYTHON_PATH='$(PYTHON_PATH_SQ)')
  
 -GIT-GUI-VARS: FORCE
 -      @VARS='$(TRACK_VARS)'; \
 +GIT-PYTHON-VARS: FORCE
 +      @VARS='$(TRACK_PYTHON)'; \
            if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \
 -              echo 1>&2 "    * new Tcl/Tk interpreter location"; \
 +              echo >&2 "    * new Python interpreter location"; \
                echo "$$VARS" >$@; \
              fi
  endif
@@@ -2170,7 -2486,6 +2176,7 @@@ bin-wrappers/%: wrap-for-bin.s
  # with that.
  
  export NO_SVN_TESTS
 +export TEST_NO_MALLOC_CHECK
  
  ### Testing rules
  
@@@ -2344,11 -2659,11 +2350,11 @@@ quick-install-html
  
  ### Maintainer's dist rules
  
 -git.spec: git.spec.in
 +git.spec: git.spec.in GIT-VERSION-FILE
        sed -e 's/@@VERSION@@/$(GIT_VERSION)/g' < $< > $@+
        mv $@+ $@
  
 -GIT_TARNAME=git-$(GIT_VERSION)
 +GIT_TARNAME = git-$(GIT_VERSION)
  dist: git.spec git-archive$(X) configure
        ./git-archive --format=tar \
                --prefix=$(GIT_TARNAME)/ HEAD^{tree} > $(GIT_TARNAME).tar
@@@ -2394,9 -2709,6 +2400,9 @@@ dist-doc
  
  distclean: clean
        $(RM) configure
 +      $(RM) config.log config.status config.cache
 +      $(RM) config.mak.autogen config.mak.append
 +      $(RM) -r autom4te.cache
  
  profile-clean:
        $(RM) $(addsuffix *.gcda,$(addprefix $(PROFILE_DIR)/, $(object_dirs)))
@@@ -2411,6 -2723,8 +2417,6 @@@ clean: profile-clea
        $(RM) -r $(dep_dirs)
        $(RM) -r po/build/
        $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h $(ETAGS_TARGET) tags cscope*
 -      $(RM) -r autom4te.cache
 -      $(RM) config.log config.mak.autogen config.mak.append config.status config.cache
        $(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
@@@ -2428,8 -2742,7 +2434,8 @@@ ifndef NO_TCLT
        $(MAKE) -C gitk-git clean
        $(MAKE) -C git-gui clean
  endif
 -      $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-LDFLAGS GIT-GUI-VARS GIT-BUILD-OPTIONS
 +      $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-LDFLAGS GIT-BUILD-OPTIONS
 +      $(RM) GIT-USER-AGENT GIT-PREFIX GIT-SCRIPT-DEFINES GIT-PYTHON-VARS
  
  .PHONY: all install profile-clean clean strip
  .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
  
  ### Check documentation
  #
 +ALL_COMMANDS = $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS)
 +ALL_COMMANDS += git
 +ALL_COMMANDS += gitk
 +ALL_COMMANDS += gitweb
 +ALL_COMMANDS += git-gui git-citool
  check-docs::
 -      @(for v in $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git gitk; \
 +      @(for v in $(ALL_COMMANDS); \
        do \
                case "$$v" in \
                git-merge-octopus | git-merge-ours | git-merge-recursive | \
                sed -e '/^#/d' \
                    -e 's/[     ].*//' \
                    -e 's/^/listed /' command-list.txt; \
 -              ls -1 Documentation/git*txt | \
 +              $(MAKE) -C Documentation print-man1 | \
 +              grep '\.txt$$' | \
                sed -e 's|Documentation/|documented |' \
                    -e 's/\.txt//'; \
        ) | while read how cmd; \
        do \
 -              case "$$how,$$cmd" in \
 -              *,git-citool | \
 -              *,git-gui | \
 -              *,git-help | \
 -              documented,gitattributes | \
 -              documented,gitignore | \
 -              documented,gitmodules | \
 -              documented,gitcli | \
 -              documented,git-tools | \
 -              documented,gitcore-tutorial | \
 -              documented,gitcvs-migration | \
 -              documented,gitdiffcore | \
 -              documented,gitglossary | \
 -              documented,githooks | \
 -              documented,gitrepository-layout | \
 -              documented,gitrevisions | \
 -              documented,gittutorial | \
 -              documented,gittutorial-2 | \
 -              documented,git-bisect-lk2009 | \
 -              documented,git-remote-helpers | \
 -              documented,gitworkflows | \
 -              sentinel,not,matching,is,ok ) continue ;; \
 -              esac; \
 -              case " $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git gitk " in \
 +              case " $(ALL_COMMANDS) " in \
                *" $$cmd "*)    ;; \
                *) echo "removed but $$how: $$cmd" ;; \
                esac; \
diff --combined dir.c
index cf1e6b0082381670809a4293c4a49cfef681d756,6ef03961f334462f4408825635cda29ffb48bd16..57394e452eb0de117b27f64804e529b617a6c7e0
--- 1/dir.c
--- 2/dir.c
+++ b/dir.c
@@@ -2,8 -2,6 +2,8 @@@
   * This handles recursive filename detection with exclude
   * files, index knowledge etc..
   *
 + * See Documentation/technical/api-directory-listing.txt
 + *
   * Copyright (C) Linus Torvalds, 2005-2006
   *             Junio Hamano, 2005-2006
   */
@@@ -37,33 -35,10 +37,33 @@@ int fnmatch_icase(const char *pattern, 
        return fnmatch(pattern, string, flags | (ignore_case ? FNM_CASEFOLD : 0));
  }
  
 +inline int git_fnmatch(const char *pattern, const char *string,
 +                     int flags, int prefix)
 +{
 +      int fnm_flags = 0;
 +      if (flags & GFNM_PATHNAME)
 +              fnm_flags |= FNM_PATHNAME;
 +      if (prefix > 0) {
 +              if (strncmp(pattern, string, prefix))
 +                      return FNM_NOMATCH;
 +              pattern += prefix;
 +              string += prefix;
 +      }
 +      if (flags & GFNM_ONESTAR) {
 +              int pattern_len = strlen(++pattern);
 +              int string_len = strlen(string);
 +              return string_len < pattern_len ||
 +                     strcmp(pattern,
 +                            string + string_len - pattern_len);
 +      }
 +      return fnmatch(pattern, string, fnm_flags);
 +}
 +
  static size_t common_prefix_len(const char **pathspec)
  {
        const char *n, *first;
        size_t max = 0;
 +      int literal = limit_pathspec_to_literal();
  
        if (!pathspec)
                return max;
@@@ -73,7 -48,7 +73,7 @@@
                size_t i, len = 0;
                for (i = 0; first == n || i < max; i++) {
                        char c = n[i];
 -                      if (!c || c != first[i] || is_glob_special(c))
 +                      if (!c || c != first[i] || (!literal && is_glob_special(c)))
                                break;
                        if (c == '/')
                                len = i + 1;
@@@ -143,7 -118,6 +143,7 @@@ int within_depth(const char *name, int 
  static int match_one(const char *match, const char *name, int namelen)
  {
        int matchlen;
 +      int literal = limit_pathspec_to_literal();
  
        /* If the match was just the prefix, we matched */
        if (!*match)
                for (;;) {
                        unsigned char c1 = tolower(*match);
                        unsigned char c2 = tolower(*name);
 -                      if (c1 == '\0' || is_glob_special(c1))
 +                      if (c1 == '\0' || (!literal && is_glob_special(c1)))
                                break;
                        if (c1 != c2)
                                return 0;
                for (;;) {
                        unsigned char c1 = *match;
                        unsigned char c2 = *name;
 -                      if (c1 == '\0' || is_glob_special(c1))
 +                      if (c1 == '\0' || (!literal && is_glob_special(c1)))
                                break;
                        if (c1 != c2)
                                return 0;
                }
        }
  
 -
        /*
         * If we don't match the matchstring exactly,
         * we need to match by fnmatch
         */
        matchlen = strlen(match);
 -      if (strncmp_icase(match, name, matchlen))
 +      if (strncmp_icase(match, name, matchlen)) {
 +              if (literal)
 +                      return 0;
                return !fnmatch_icase(match, name, 0) ? MATCHED_FNMATCH : 0;
 +      }
  
        if (namelen == matchlen)
                return MATCHED_EXACTLY;
  }
  
  /*
 - * Given a name and a list of pathspecs, see if the name matches
 - * any of the pathspecs.  The caller is also interested in seeing
 - * all pathspec matches some names it calls this function with
 - * (otherwise the user could have mistyped the unmatched pathspec),
 - * and a mark is left in seen[] array for pathspec element that
 - * actually matched anything.
 + * Given a name and a list of pathspecs, returns the nature of the
 + * closest (i.e. most specific) match of the name to any of the
 + * pathspecs.
 + *
 + * The caller typically calls this multiple times with the same
 + * pathspec and seen[] array but with different name/namelen
 + * (e.g. entries from the index) and is interested in seeing if and
 + * how each pathspec matches all the names it calls this function
 + * with.  A mark is left in the seen[] array for each pathspec element
 + * indicating the closest type of match that element achieved, so if
 + * seen[n] remains zero after multiple invocations, that means the nth
 + * pathspec did not match any names, which could indicate that the
 + * user mistyped the nth pathspec.
   */
  int match_pathspec(const char **pathspec, const char *name, int namelen,
                int prefix, char *seen)
@@@ -266,29 -231,19 +266,29 @@@ static int match_pathspec_item(const st
                        return MATCHED_RECURSIVELY;
        }
  
 -      if (item->use_wildcard && !fnmatch(match, name, 0))
 +      if (item->nowildcard_len < item->len &&
 +          !git_fnmatch(match, name,
 +                       item->flags & PATHSPEC_ONESTAR ? GFNM_ONESTAR : 0,
 +                       item->nowildcard_len - prefix))
                return MATCHED_FNMATCH;
  
        return 0;
  }
  
  /*
 - * Given a name and a list of pathspecs, see if the name matches
 - * any of the pathspecs.  The caller is also interested in seeing
 - * all pathspec matches some names it calls this function with
 - * (otherwise the user could have mistyped the unmatched pathspec),
 - * and a mark is left in seen[] array for pathspec element that
 - * actually matched anything.
 + * Given a name and a list of pathspecs, returns the nature of the
 + * closest (i.e. most specific) match of the name to any of the
 + * pathspecs.
 + *
 + * The caller typically calls this multiple times with the same
 + * pathspec and seen[] array but with different name/namelen
 + * (e.g. entries from the index) and is interested in seeing if and
 + * how each pathspec matches all the names it calls this function
 + * with.  A mark is left in the seen[] array for each pathspec element
 + * indicating the closest type of match that element achieved, so if
 + * seen[n] remains zero after multiple invocations, that means the nth
 + * pathspec did not match any names, which could indicate that the
 + * user mistyped the nth pathspec.
   */
  int match_pathspec_depth(const struct pathspec *ps,
                         const char *name, int namelen,
@@@ -393,7 -348,7 +393,7 @@@ void parse_exclude_pattern(const char *
  }
  
  void add_exclude(const char *string, const char *base,
 -               int baselen, struct exclude_list *which)
 +               int baselen, struct exclude_list *el, int srcpos)
  {
        struct exclude *x;
        int patternlen;
        x->base = base;
        x->baselen = baselen;
        x->flags = flags;
 -      ALLOC_GROW(which->excludes, which->nr + 1, which->alloc);
 -      which->excludes[which->nr++] = x;
 +      x->srcpos = srcpos;
 +      ALLOC_GROW(el->excludes, el->nr + 1, el->alloc);
 +      el->excludes[el->nr++] = x;
 +      x->el = el;
  }
  
  static void *read_skip_worktree_file_from_index(const char *path, size_t *size)
        return data;
  }
  
 -void free_excludes(struct exclude_list *el)
 +/*
 + * Frees memory within el which was allocated for exclude patterns and
 + * the file buffer.  Does not free el itself.
 + */
 +void clear_exclude_list(struct exclude_list *el)
  {
        int i;
  
        for (i = 0; i < el->nr; i++)
                free(el->excludes[i]);
        free(el->excludes);
 +      free(el->filebuf);
  
        el->nr = 0;
        el->excludes = NULL;
 +      el->filebuf = NULL;
  }
  
  int add_excludes_from_file_to_list(const char *fname,
                                   const char *base,
                                   int baselen,
 -                                 char **buf_p,
 -                                 struct exclude_list *which,
 +                                 struct exclude_list *el,
                                   int check_index)
  {
        struct stat st;
 -      int fd, i;
 +      int fd, i, lineno = 1;
        size_t size = 0;
        char *buf, *entry;
  
        fd = open(fname, O_RDONLY);
        if (fd < 0 || fstat(fd, &st) < 0) {
 +              if (errno != ENOENT)
 +                      warn_on_inaccessible(fname);
                if (0 <= fd)
                        close(fd);
                if (!check_index ||
                close(fd);
        }
  
 -      if (buf_p)
 -              *buf_p = buf;
 +      el->filebuf = buf;
        entry = buf;
        for (i = 0; i < size; i++) {
                if (buf[i] == '\n') {
                        if (entry != buf + i && entry[0] != '#') {
                                buf[i - (i && buf[i-1] == '\r')] = 0;
 -                              add_exclude(entry, base, baselen, which);
 +                              add_exclude(entry, base, baselen, el, lineno);
                        }
 +                      lineno++;
                        entry = buf + i + 1;
                }
        }
        return 0;
  }
  
 +struct exclude_list *add_exclude_list(struct dir_struct *dir,
 +                                    int group_type, const char *src)
 +{
 +      struct exclude_list *el;
 +      struct exclude_list_group *group;
 +
 +      group = &dir->exclude_list_group[group_type];
 +      ALLOC_GROW(group->el, group->nr + 1, group->alloc);
 +      el = &group->el[group->nr++];
 +      memset(el, 0, sizeof(*el));
 +      el->src = src;
 +      return el;
 +}
 +
 +/*
 + * Used to set up core.excludesfile and .git/info/exclude lists.
 + */
  void add_excludes_from_file(struct dir_struct *dir, const char *fname)
  {
 -      if (add_excludes_from_file_to_list(fname, "", 0, NULL,
 -                                         &dir->exclude_list[EXC_FILE], 0) < 0)
 +      struct exclude_list *el;
 +      el = add_exclude_list(dir, EXC_FILE, fname);
 +      if (add_excludes_from_file_to_list(fname, "", 0, el, 0) < 0)
                die("cannot use %s as an exclude file", fname);
  }
  
 +/*
 + * Loads the per-directory exclude list for the substring of base
 + * which has a char length of baselen.
 + */
  static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
  {
 +      struct exclude_list_group *group;
        struct exclude_list *el;
        struct exclude_stack *stk = NULL;
        int current;
            (baselen + strlen(dir->exclude_per_dir) >= PATH_MAX))
                return; /* too long a path -- ignore */
  
 -      /* Pop the ones that are not the prefix of the path being checked. */
 -      el = &dir->exclude_list[EXC_DIRS];
 +      group = &dir->exclude_list_group[EXC_DIRS];
 +
 +      /* Pop the exclude lists from the EXCL_DIRS exclude_list_group
 +       * which originate from directories not in the prefix of the
 +       * path being checked. */
        while ((stk = dir->exclude_stack) != NULL) {
                if (stk->baselen <= baselen &&
                    !strncmp(dir->basebuf, base, stk->baselen))
                        break;
 +              el = &group->el[dir->exclude_stack->exclude_ix];
                dir->exclude_stack = stk->prev;
 -              while (stk->exclude_ix < el->nr)
 -                      free(el->excludes[--el->nr]);
 -              free(stk->filebuf);
 +              free((char *)el->src); /* see strdup() below */
 +              clear_exclude_list(el);
                free(stk);
 +              group->nr--;
        }
  
        /* Read from the parent directories and push them down. */
                }
                stk->prev = dir->exclude_stack;
                stk->baselen = cp - base;
 -              stk->exclude_ix = el->nr;
                memcpy(dir->basebuf + current, base + current,
                       stk->baselen - current);
                strcpy(dir->basebuf + stk->baselen, dir->exclude_per_dir);
 +              /*
 +               * dir->basebuf gets reused by the traversal, but we
 +               * need fname to remain unchanged to ensure the src
 +               * member of each struct exclude correctly
 +               * back-references its source file.  Other invocations
 +               * of add_exclude_list provide stable strings, so we
 +               * strdup() and free() here in the caller.
 +               */
 +              el = add_exclude_list(dir, EXC_DIRS, strdup(dir->basebuf));
 +              stk->exclude_ix = group->nr - 1;
                add_excludes_from_file_to_list(dir->basebuf,
                                               dir->basebuf, stk->baselen,
 -                                             &stk->filebuf, el, 1);
 +                                             el, 1);
                dir->exclude_stack = stk;
                current = stk->baselen;
        }
@@@ -685,29 -595,26 +685,30 @@@ int match_pathname(const char *pathname
        }
  
        return wildmatch(pattern, name,
-                        ignore_case ? FNM_CASEFOLD : 0) == 0;
+                        WM_PATHNAME | (ignore_case ? WM_CASEFOLD : 0),
+                        NULL) == 0;
  }
  
 -/* Scan the list and let the last match determine the fate.
 - * Return 1 for exclude, 0 for include and -1 for undecided.
 +/*
 + * Scan the given exclude list in reverse to see whether pathname
 + * should be ignored.  The first match (i.e. the last on the list), if
 + * any, determines the fate.  Returns the exclude_list element which
 + * matched, or NULL for undecided.
   */
 -int excluded_from_list(const char *pathname,
 -                     int pathlen, const char *basename, int *dtype,
 -                     struct exclude_list *el)
 +static struct exclude *last_exclude_matching_from_list(const char *pathname,
 +                                                     int pathlen,
 +                                                     const char *basename,
 +                                                     int *dtype,
 +                                                     struct exclude_list *el)
  {
        int i;
  
        if (!el->nr)
 -              return -1;      /* undefined */
 +              return NULL;    /* undefined */
  
        for (i = el->nr - 1; 0 <= i; i--) {
                struct exclude *x = el->excludes[i];
                const char *exclude = x->pattern;
 -              int to_exclude = x->flags & EXC_FLAG_NEGATIVE ? 0 : 1;
                int prefix = x->nowildcardlen;
  
                if (x->flags & EXC_FLAG_MUSTBEDIR) {
                                           pathlen - (basename - pathname),
                                           exclude, prefix, x->patternlen,
                                           x->flags))
 -                              return to_exclude;
 +                              return x;
                        continue;
                }
  
                if (match_pathname(pathname, pathlen,
                                   x->base, x->baselen ? x->baselen - 1 : 0,
                                   exclude, prefix, x->patternlen, x->flags))
 -                      return to_exclude;
 +                      return x;
        }
 +      return NULL; /* undecided */
 +}
 +
 +/*
 + * Scan the list and let the last match determine the fate.
 + * Return 1 for exclude, 0 for include and -1 for undecided.
 + */
 +int is_excluded_from_list(const char *pathname,
 +                        int pathlen, const char *basename, int *dtype,
 +                        struct exclude_list *el)
 +{
 +      struct exclude *exclude;
 +      exclude = last_exclude_matching_from_list(pathname, pathlen, basename, dtype, el);
 +      if (exclude)
 +              return exclude->flags & EXC_FLAG_NEGATIVE ? 0 : 1;
        return -1; /* undecided */
  }
  
 -static int excluded(struct dir_struct *dir, const char *pathname, int *dtype_p)
 +/*
 + * Loads the exclude lists for the directory containing pathname, then
 + * scans all exclude lists to determine whether pathname is excluded.
 + * Returns the exclude_list element which matched, or NULL for
 + * undecided.
 + */
 +static struct exclude *last_exclude_matching(struct dir_struct *dir,
 +                                           const char *pathname,
 +                                           int *dtype_p)
  {
        int pathlen = strlen(pathname);
 -      int st;
 +      int i, j;
 +      struct exclude_list_group *group;
 +      struct exclude *exclude;
        const char *basename = strrchr(pathname, '/');
        basename = (basename) ? basename+1 : pathname;
  
        prep_exclude(dir, pathname, basename-pathname);
 -      for (st = EXC_CMDL; st <= EXC_FILE; st++) {
 -              switch (excluded_from_list(pathname, pathlen, basename,
 -                                         dtype_p, &dir->exclude_list[st])) {
 -              case 0:
 -                      return 0;
 -              case 1:
 -                      return 1;
 +
 +      for (i = EXC_CMDL; i <= EXC_FILE; i++) {
 +              group = &dir->exclude_list_group[i];
 +              for (j = group->nr - 1; j >= 0; j--) {
 +                      exclude = last_exclude_matching_from_list(
 +                              pathname, pathlen, basename, dtype_p,
 +                              &group->el[j]);
 +                      if (exclude)
 +                              return exclude;
                }
        }
 +      return NULL;
 +}
 +
 +/*
 + * Loads the exclude lists for the directory containing pathname, then
 + * scans all exclude lists to determine whether pathname is excluded.
 + * Returns 1 if true, otherwise 0.
 + */
 +static int is_excluded(struct dir_struct *dir, const char *pathname, int *dtype_p)
 +{
 +      struct exclude *exclude =
 +              last_exclude_matching(dir, pathname, dtype_p);
 +      if (exclude)
 +              return exclude->flags & EXC_FLAG_NEGATIVE ? 0 : 1;
        return 0;
  }
  
@@@ -800,7 -666,6 +801,7 @@@ void path_exclude_check_init(struct pat
                             struct dir_struct *dir)
  {
        check->dir = dir;
 +      check->exclude = NULL;
        strbuf_init(&check->path, 256);
  }
  
@@@ -810,41 -675,32 +811,41 @@@ void path_exclude_check_clear(struct pa
  }
  
  /*
 - * Is this name excluded?  This is for a caller like show_files() that
 - * do not honor directory hierarchy and iterate through paths that are
 - * possibly in an ignored directory.
 + * For each subdirectory in name, starting with the top-most, checks
 + * to see if that subdirectory is excluded, and if so, returns the
 + * corresponding exclude structure.  Otherwise, checks whether name
 + * itself (which is presumably a file) is excluded.
   *
   * A path to a directory known to be excluded is left in check->path to
   * optimize for repeated checks for files in the same excluded directory.
   */
 -int path_excluded(struct path_exclude_check *check,
 -                const char *name, int namelen, int *dtype)
 +struct exclude *last_exclude_matching_path(struct path_exclude_check *check,
 +                                         const char *name, int namelen,
 +                                         int *dtype)
  {
        int i;
        struct strbuf *path = &check->path;
 +      struct exclude *exclude;
  
        /*
         * we allow the caller to pass namelen as an optimization; it
         * must match the length of the name, as we eventually call
 -       * excluded() on the whole name string.
 +       * is_excluded() on the whole name string.
         */
        if (namelen < 0)
                namelen = strlen(name);
  
 +      /*
 +       * If path is non-empty, and name is equal to path or a
 +       * subdirectory of path, name should be excluded, because
 +       * it's inside a directory which is already known to be
 +       * excluded and was previously left in check->path.
 +       */
        if (path->len &&
            path->len <= namelen &&
            !memcmp(name, path->buf, path->len) &&
            (!name[path->len] || name[path->len] == '/'))
 -              return 1;
 +              return check->exclude;
  
        strbuf_setlen(path, 0);
        for (i = 0; name[i]; i++) {
  
                if (ch == '/') {
                        int dt = DT_DIR;
 -                      if (excluded(check->dir, path->buf, &dt))
 -                              return 1;
 +                      exclude = last_exclude_matching(check->dir,
 +                                                      path->buf, &dt);
 +                      if (exclude) {
 +                              check->exclude = exclude;
 +                              return exclude;
 +                      }
                }
                strbuf_addch(path, ch);
        }
        /* An entry in the index; cannot be a directory with subentries */
        strbuf_setlen(path, 0);
  
 -      return excluded(check->dir, name, dtype);
 +      return last_exclude_matching(check->dir, name, dtype);
 +}
 +
 +/*
 + * Is this name excluded?  This is for a caller like show_files() that
 + * do not honor directory hierarchy and iterate through paths that are
 + * possibly in an ignored directory.
 + */
 +int is_path_excluded(struct path_exclude_check *check,
 +                const char *name, int namelen, int *dtype)
 +{
 +      struct exclude *exclude =
 +              last_exclude_matching_path(check, name, namelen, dtype);
 +      if (exclude)
 +              return exclude->flags & EXC_FLAG_NEGATIVE ? 0 : 1;
 +      return 0;
  }
  
  static struct dir_entry *dir_entry_new(const char *pathname, int len)
  
  static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int len)
  {
 -      if (cache_name_exists(pathname, len, ignore_case))
 +      if (!(dir->flags & DIR_SHOW_IGNORED) &&
 +          cache_name_exists(pathname, len, ignore_case))
                return NULL;
  
        ALLOC_GROW(dir->entries, dir->nr+1, dir->alloc);
@@@ -999,9 -835,8 +1000,9 @@@ static enum exist_status directory_exis
   * traversal routine.
   *
   * Case 1: If we *already* have entries in the index under that
 - * directory name, we always recurse into the directory to see
 - * all the files.
 + * directory name, we recurse into the directory to see all the files,
 + * unless the directory is excluded and we want to show ignored
 + * directories
   *
   * Case 2: If we *already* have that directory name as a gitlink,
   * we always continue to see it as a gitlink, regardless of whether
   *      just a directory, unless "hide_empty_directories" is
   *      also true and the directory is empty, in which case
   *      we just ignore it entirely.
 + *      if we are looking for ignored directories, look if it
 + *      contains only ignored files to decide if it must be shown as
 + *      ignored or not.
   *  (b) if it looks like a git directory, and we don't have
   *      'no_gitlinks' set we treat it as a gitlink, and show it
   *      as a directory.
@@@ -1030,15 -862,12 +1031,15 @@@ enum directory_treatment 
  };
  
  static enum directory_treatment treat_directory(struct dir_struct *dir,
 -      const char *dirname, int len,
 +      const char *dirname, int len, int exclude,
        const struct path_simplify *simplify)
  {
        /* The "len-1" is to strip the final '/' */
        switch (directory_exists_in_index(dirname, len-1)) {
        case index_directory:
 +              if ((dir->flags & DIR_SHOW_OTHER_DIRECTORIES) && exclude)
 +                      break;
 +
                return recurse_into_directory;
  
        case index_gitdir:
        }
  
        /* This is the "show_other_directories" case */
 -      if (!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
 +
 +      /*
 +       * We are looking for ignored files and our directory is not ignored,
 +       * check if it contains only ignored files
 +       */
 +      if ((dir->flags & DIR_SHOW_IGNORED) && !exclude) {
 +              int ignored;
 +              dir->flags &= ~DIR_SHOW_IGNORED;
 +              dir->flags |= DIR_HIDE_EMPTY_DIRECTORIES;
 +              ignored = read_directory_recursive(dir, dirname, len, 1, simplify);
 +              dir->flags &= ~DIR_HIDE_EMPTY_DIRECTORIES;
 +              dir->flags |= DIR_SHOW_IGNORED;
 +
 +              return ignored ? ignore_directory : show_directory;
 +      }
 +      if (!(dir->flags & DIR_SHOW_IGNORED) &&
 +          !(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
                return show_directory;
        if (!read_directory_recursive(dir, dirname, len, 1, simplify))
                return ignore_directory;
        return show_directory;
  }
  
 +/*
 + * Decide what to do when we find a file while traversing the
 + * filesystem. Mostly two cases:
 + *
 + *  1. We are looking for ignored files
 + *   (a) File is ignored, include it
 + *   (b) File is in ignored path, include it
 + *   (c) File is not ignored, exclude it
 + *
 + *  2. Other scenarios, include the file if not excluded
 + *
 + * Return 1 for exclude, 0 for include.
 + */
 +static int treat_file(struct dir_struct *dir, struct strbuf *path, int exclude, int *dtype)
 +{
 +      struct path_exclude_check check;
 +      int exclude_file = 0;
 +
 +      if (exclude)
 +              exclude_file = !(dir->flags & DIR_SHOW_IGNORED);
 +      else if (dir->flags & DIR_SHOW_IGNORED) {
 +              /* Always exclude indexed files */
 +              struct cache_entry *ce = index_name_exists(&the_index,
 +                  path->buf, path->len, ignore_case);
 +
 +              if (ce)
 +                      return 1;
 +
 +              path_exclude_check_init(&check, dir);
 +
 +              if (!is_path_excluded(&check, path->buf, path->len, dtype))
 +                      exclude_file = 1;
 +
 +              path_exclude_check_clear(&check);
 +      }
 +
 +      return exclude_file;
 +}
 +
  /*
   * This is an inexact early pruning of any recursive directory
   * reading - if the path cannot possibly be in the pathspec,
@@@ -1243,7 -1017,7 +1244,7 @@@ static enum path_treatment treat_one_pa
                                          const struct path_simplify *simplify,
                                          int dtype, struct dirent *de)
  {
 -      int exclude = excluded(dir, path->buf, &dtype);
 +      int exclude = is_excluded(dir, path->buf, &dtype);
        if (exclude && (dir->flags & DIR_COLLECT_IGNORED)
            && exclude_matches_pathspec(path->buf, path->len, simplify))
                dir_add_ignored(dir, path->buf, path->len);
        if (dtype == DT_UNKNOWN)
                dtype = get_dtype(de, path->buf, path->len);
  
 -      /*
 -       * Do we want to see just the ignored files?
 -       * We still need to recurse into directories,
 -       * even if we don't ignore them, since the
 -       * directory may contain files that we do..
 -       */
 -      if (!exclude && (dir->flags & DIR_SHOW_IGNORED)) {
 -              if (dtype != DT_DIR)
 -                      return path_ignored;
 -      }
 -
        switch (dtype) {
        default:
                return path_ignored;
        case DT_DIR:
                strbuf_addch(path, '/');
 -              switch (treat_directory(dir, path->buf, path->len, simplify)) {
 +
 +              switch (treat_directory(dir, path->buf, path->len, exclude, simplify)) {
                case show_directory:
 -                      if (exclude != !!(dir->flags
 -                                        & DIR_SHOW_IGNORED))
 -                              return path_ignored;
                        break;
                case recurse_into_directory:
                        return path_recurse;
                break;
        case DT_REG:
        case DT_LNK:
 -              break;
 +              switch (treat_file(dir, path, exclude, &dtype)) {
 +              case 1:
 +                      return path_ignored;
 +              default:
 +                      break;
 +              }
        }
        return path_handled;
  }
@@@ -1584,17 -1366,12 +1585,17 @@@ int remove_dir_recursively(struct strbu
  void setup_standard_excludes(struct dir_struct *dir)
  {
        const char *path;
 +      char *xdg_path;
  
        dir->exclude_per_dir = ".gitignore";
        path = git_path("info/exclude");
 -      if (!access(path, R_OK))
 +      if (!excludes_file) {
 +              home_config_paths(NULL, &xdg_path, "ignore");
 +              excludes_file = xdg_path;
 +      }
 +      if (!access_or_warn(path, R_OK))
                add_excludes_from_file(dir, path);
 -      if (excludes_file && !access(excludes_file, R_OK))
 +      if (excludes_file && !access_or_warn(excludes_file, R_OK))
                add_excludes_from_file(dir, excludes_file);
  }
  
@@@ -1648,18 -1425,9 +1649,18 @@@ int init_pathspec(struct pathspec *path
  
                item->match = path;
                item->len = strlen(path);
 -              item->use_wildcard = !no_wildcard(path);
 -              if (item->use_wildcard)
 -                      pathspec->has_wildcard = 1;
 +              item->flags = 0;
 +              if (limit_pathspec_to_literal()) {
 +                      item->nowildcard_len = item->len;
 +              } else {
 +                      item->nowildcard_len = simple_length(path);
 +                      if (item->nowildcard_len < item->len) {
 +                              pathspec->has_wildcard = 1;
 +                              if (path[item->nowildcard_len] == '*' &&
 +                                  no_wildcard(path + item->nowildcard_len + 1))
 +                                      item->flags |= PATHSPEC_ONESTAR;
 +                      }
 +              }
        }
  
        qsort(pathspec->items, pathspec->nr,
@@@ -1673,41 -1441,3 +1674,41 @@@ void free_pathspec(struct pathspec *pat
        free(pathspec->items);
        pathspec->items = NULL;
  }
 +
 +int limit_pathspec_to_literal(void)
 +{
 +      static int flag = -1;
 +      if (flag < 0)
 +              flag = git_env_bool(GIT_LITERAL_PATHSPECS_ENVIRONMENT, 0);
 +      return flag;
 +}
 +
 +/*
 + * Frees memory within dir which was allocated for exclude lists and
 + * the exclude_stack.  Does not free dir itself.
 + */
 +void clear_directory(struct dir_struct *dir)
 +{
 +      int i, j;
 +      struct exclude_list_group *group;
 +      struct exclude_list *el;
 +      struct exclude_stack *stk;
 +
 +      for (i = EXC_CMDL; i <= EXC_FILE; i++) {
 +              group = &dir->exclude_list_group[i];
 +              for (j = 0; j < group->nr; j++) {
 +                      el = &group->el[j];
 +                      if (i == EXC_DIRS)
 +                              free((char *)el->src);
 +                      clear_exclude_list(el);
 +              }
 +              free(group->el);
 +      }
 +
 +      stk = dir->exclude_stack;
 +      while (stk) {
 +              struct exclude_stack *prev = stk->prev;
 +              free(stk);
 +              stk = prev;
 +      }
 +}
diff --combined git-compat-util.h
index dab545e02e17b834da63d911615bd2afa04a702c,b2c7638ae5995b2df694fcfea7d8614eee9f4353..cc2abeea0debcbe70c31320abb904e6d55cfe2bc
@@@ -74,8 -74,7 +74,8 @@@
  # define _XOPEN_SOURCE 500
  # endif
  #elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \
 -      !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__)
 +      !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \
 +      !defined(__TANDEM) && !defined(__QNX__)
  #define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
  #define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
  #endif
  #include <stdlib.h>
  #include <stdarg.h>
  #include <string.h>
 +#ifdef HAVE_STRINGS_H
 +#include <strings.h> /* for strcasecmp() */
 +#endif
  #include <errno.h>
  #include <limits.h>
 +#ifdef NEEDS_SYS_PARAM_H
  #include <sys/param.h>
 +#endif
  #include <sys/types.h>
  #include <dirent.h>
  #include <sys/time.h>
  #include <time.h>
  #include <signal.h>
+ #ifndef USE_WILDMATCH
  #include <fnmatch.h>
+ #endif
  #include <assert.h>
  #include <regex.h>
  #include <utime.h>
  #else
  #include <stdint.h>
  #endif
 +#ifdef NO_INTPTR_T
 +/*
 + * On I16LP32, ILP32 and LP64 "long" is the save bet, however
 + * on LLP86, IL33LLP64 and P64 it needs to be "long long",
 + * while on IP16 and IP16L32 it is "int" (resp. "short")
 + * Size needs to match (or exceed) 'sizeof(void *)'.
 + * We can't take "long long" here as not everybody has it.
 + */
 +typedef long intptr_t;
 +typedef unsigned long uintptr_t;
 +#endif
  #if defined(__CYGWIN__)
  #undef _XOPEN_SOURCE
  #include <grp.h>
  #endif
  #endif
  
 +/* used on Mac OS X */
 +#ifdef PRECOMPOSE_UNICODE
 +#include "compat/precompose_utf8.h"
 +#else
 +#define precompose_str(in,i_nfd2nfc)
 +#define precompose_argv(c,v)
 +#define probe_utf8_pathname_composition(a,b)
 +#endif
 +
 +#ifdef MKDIR_WO_TRAILING_SLASH
 +#define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b))
 +extern int compat_mkdir_wo_trailing_slash(const char*, mode_t);
 +#endif
 +
 +#ifdef NO_STRUCT_ITIMERVAL
 +struct itimerval {
 +      struct timeval it_interval;
 +      struct timeval it_value;
 +}
 +#endif
 +
 +#ifdef NO_SETITIMER
 +#define setitimer(which,value,ovalue)
 +#endif
 +
  #ifndef NO_LIBGEN_H
  #include <libgen.h>
  #else
@@@ -280,6 -240,17 +282,17 @@@ extern char *gitbasename(char *)
  
  #include "compat/bswap.h"
  
+ #ifdef USE_WILDMATCH
+ #include "wildmatch.h"
+ #define FNM_PATHNAME WM_PATHNAME
+ #define FNM_CASEFOLD WM_CASEFOLD
+ #define FNM_NOMATCH  WM_NOMATCH
+ static inline int fnmatch(const char *pattern, const char *string, int flags)
+ {
+       return wildmatch(pattern, string, flags, NULL);
+ }
+ #endif
  /* General helper functions */
  extern void vreportf(const char *prefix, const char *err, va_list params);
  extern void vwritef(int fd, const char *prefix, const char *err, va_list params);
@@@ -290,17 -261,6 +303,17 @@@ extern NORETURN void die_errno(const ch
  extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
  extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
  
 +/*
 + * Let callers be aware of the constant return value; this can help
 + * gcc with -Wuninitialized analysis. We have to restrict this trick to
 + * gcc, though, because of the variadic macro and the magic ## comma pasting
 + * behavior. But since we're only trying to help gcc, anyway, it's OK; other
 + * compilers will fall back to using the function as usual.
 + */
 +#if defined(__GNUC__) && ! defined(__clang__)
 +#define error(fmt, ...) (error((fmt), ##__VA_ARGS__), -1)
 +#endif
 +
  extern void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params));
  extern void set_error_routine(void (*routine)(const char *err, va_list params));
  
@@@ -424,10 -384,6 +437,10 @@@ void *gitmemmem(const void *haystack, s
                  const void *needle, size_t needlelen);
  #endif
  
 +#ifdef NO_GETPAGESIZE
 +#define getpagesize() sysconf(_SC_PAGESIZE)
 +#endif
 +
  #ifdef FREAD_READS_DIRECTORIES
  #ifdef fopen
  #undef fopen
@@@ -523,7 -479,6 +536,7 @@@ extern const char tolower_trans_tbl[256
  #undef isdigit
  #undef isalpha
  #undef isalnum
 +#undef isprint
  #undef islower
  #undef isupper
  #undef tolower
  #undef iscntrl
  #undef ispunct
  #undef isxdigit
 -#undef isprint
 +
  extern const unsigned char sane_ctype[256];
  #define GIT_SPACE 0x01
  #define GIT_DIGIT 0x02
  #define isdigit(x) sane_istest(x,GIT_DIGIT)
  #define isalpha(x) sane_istest(x,GIT_ALPHA)
  #define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
 +#define isprint(x) ((x) >= 0x20 && (x) <= 0x7e)
  #define islower(x) sane_iscase(x, 1)
  #define isupper(x) sane_iscase(x, 0)
  #define is_glob_special(x) sane_istest(x,GIT_GLOB_SPECIAL)
  #define ispunct(x) sane_istest(x, GIT_PUNCT | GIT_REGEX_SPECIAL | \
                GIT_GLOB_SPECIAL | GIT_PATHSPEC_MAGIC)
  #define isxdigit(x) (hexval_table[x] != -1)
 -#define isprint(x) (sane_istest(x, GIT_ALPHA | GIT_DIGIT | GIT_SPACE | \
 -              GIT_PUNCT | GIT_REGEX_SPECIAL | GIT_GLOB_SPECIAL | \
 -              GIT_PATHSPEC_MAGIC))
  #define tolower(x) sane_case((unsigned char)(x), 0x20)
  #define toupper(x) sane_case((unsigned char)(x), 0)
  #define is_pathspec_magic(x) sane_istest(x,GIT_PATHSPEC_MAGIC)
@@@ -664,16 -621,6 +677,16 @@@ int rmdir_or_warn(const char *path)
   */
  int remove_or_warn(unsigned int mode, const char *path);
  
 +/*
 + * Call access(2), but warn for any error except "missing file"
 + * (ENOENT or ENOTDIR).
 + */
 +int access_or_warn(const char *path, int mode);
 +int access_or_die(const char *path, int mode);
 +
 +/* Warn on an inaccessible file that ought to be accessible */
 +void warn_on_inaccessible(const char *path);
 +
  /* Get the passwd entry for the UID of the current process. */
  struct passwd *xgetpwuid_self(void);