Merge branch 'nd/setup'
authorJunio C Hamano <gitster@pobox.com>
Tue, 28 Dec 2010 19:26:55 +0000 (11:26 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 28 Dec 2010 19:26:55 +0000 (11:26 -0800)
* nd/setup: (47 commits)
setup_work_tree: adjust relative $GIT_WORK_TREE after moving cwd
git.txt: correct where --work-tree path is relative to
Revert "Documentation: always respect core.worktree if set"
t0001: test git init when run via an alias
Remove all logic from get_git_work_tree()
setup: rework setup_explicit_git_dir()
setup: clean up setup_discovered_git_dir()
t1020-subdirectory: test alias expansion in a subdirectory
setup: clean up setup_bare_git_dir()
setup: limit get_git_work_tree()'s to explicit setup case only
Use git_config_early() instead of git_config() during repo setup
Add git_config_early()
git-rev-parse.txt: clarify --git-dir
t1510: setup case #31
t1510: setup case #30
t1510: setup case #29
t1510: setup case #28
t1510: setup case #27
t1510: setup case #26
t1510: setup case #25
...

1  2 
.gitignore
Documentation/config.txt
Documentation/git.txt
Makefile
cache.h
config.c
environment.c
git.c
setup.c
t/t0001-init.sh
trace.c
diff --combined .gitignore
index 87b833c9d8940a61ff77ec6bd35241b3f85decb5,1dcc082a881e6a33e5208d15aa65ef08867caf81..3dd6ef7d259d8fe2811f68525b5309e97c79f4cc
  /git-remote-https
  /git-remote-ftp
  /git-remote-ftps
 +/git-remote-fd
 +/git-remote-ext
  /git-remote-testgit
  /git-repack
  /git-replace
  /test-sha1
  /test-sigchain
  /test-string-pool
+ /test-subprocess
  /test-svn-fe
  /test-treap
  /common-cmds.h
diff --combined Documentation/config.txt
index 54597f18979fb376e2f1d9ea29f5ac247e9df230,d85563d7644cf1acba633aa4fcb2544004f1d47d..a8759cff804c98a7f4d13634ce8775edd2315a0d
@@@ -317,24 -317,17 +317,17 @@@ false), while all other repositories ar
  = true).
  
  core.worktree::
-       Set the path to the root of the work tree.
+       Set the path to the working tree.  The value will not be
+       used in combination with repositories found automatically in
+       a .git directory (i.e. $GIT_DIR is not set).
        This can be overridden by the GIT_WORK_TREE environment
        variable and the '--work-tree' command line option. It can be
-       an absolute path or a relative path to the .git directory,
-       either specified by --git-dir or GIT_DIR, or automatically
-       discovered.
-       If --git-dir or GIT_DIR are specified but none of
+       an absolute path or relative path to the directory specified by
+       --git-dir or GIT_DIR.
+       Note: If --git-dir or GIT_DIR are specified but none of
        --work-tree, GIT_WORK_TREE and core.worktree is specified,
-       the current working directory is regarded as the root of the
-       work tree.
- +
- Note that this variable is honored even when set in a configuration
- file in a ".git" subdirectory of a directory, and its value differs
- from the latter directory (e.g. "/path/to/.git/config" has
- core.worktree set to "/different/path"), which is most likely a
- misconfiguration.  Running git commands in "/path/to" directory will
- still use "/different/path" as the root of the work tree and can cause
- great confusion to the users.
+       the current working directory is regarded as the top directory
+       of your working tree.
  
  core.logAllRefUpdates::
        Enable the reflog. Updates to a ref <ref> is logged to the file
@@@ -374,15 -367,6 +367,15 @@@ core.warnAmbiguousRefs:
        If true, git will warn you if the ref name you passed it is ambiguous
        and might match multiple refs in the .git/refs/ tree. True by default.
  
 +core.abbrevguard::
 +      Even though git makes sure that it uses enough hexdigits to show
 +      an abbreviated object name unambiguously, as more objects are
 +      added to the repository over time, a short name that used to be
 +      unique will stop being unique.  Git uses this many extra hexdigits
 +      that are more than necessary to make the object name currently
 +      unique, in the hope that its output will stay unique a bit longer.
 +      Defaults to 0.
 +
  core.compression::
        An integer -1..9, indicating a default compression level.
        -1 is the zlib default. 0 means no compression,
@@@ -522,9 -506,6 +515,9 @@@ core.whitespace:
    part of the line terminator, i.e. with it, `trailing-space`
    does not trigger if the character before such a carriage-return
    is not a whitespace (not enabled by default).
 +* `tabwidth=<n>` tells how many character positions a tab occupies; this
 +  is relevant for `indent-with-non-tab` and when git fixes `tab-in-indent`
 +  errors. The default tab width is 8. Allowed values are 1 to 63.
  
  core.fsyncobjectfiles::
        This boolean will enable 'fsync()' when writing object files.
@@@ -566,13 -547,9 +559,13 @@@ core.sparseCheckout:
        linkgit:git-read-tree[1] for more information.
  
  add.ignore-errors::
 +add.ignoreErrors::
        Tells 'git add' to continue adding files when some files cannot be
        added due to indexing errors. Equivalent to the '--ignore-errors'
 -      option of linkgit:git-add[1].
 +      option of linkgit:git-add[1].  Older versions of git accept only
 +      `add.ignore-errors`, which does not follow the usual naming
 +      convention for configuration variables.  Newer versions of git
 +      honor `add.ignoreErrors` as well.
  
  alias.*::
        Command aliases for the linkgit:git[1] command wrapper - e.g.
@@@ -617,9 -594,8 +610,9 @@@ branch.autosetupmerge:
        this behavior can be chosen per-branch using the `--track`
        and `--no-track` options. The valid settings are: `false` -- no
        automatic setup is done; `true` -- automatic setup is done when the
 -      starting point is a remote branch; `always` -- automatic setup is
 -      done when the starting point is either a local branch or remote
 +      starting point is a remote-tracking branch; `always` --
 +      automatic setup is done when the starting point is either a
 +      local branch or remote-tracking
        branch. This option defaults to true.
  
  branch.autosetuprebase::
        When `local`, rebase is set to true for tracked branches of
        other local branches.
        When `remote`, rebase is set to true for tracked branches of
 -      remote branches.
 +      remote-tracking branches.
        When `always`, rebase will be set to true for all tracking
        branches.
        See "branch.autosetupmerge" for details on how to set up a
@@@ -697,7 -673,7 +690,7 @@@ color.branch:
  color.branch.<slot>::
        Use customized color for branch coloration. `<slot>` is one of
        `current` (the current branch), `local` (a local branch),
 -      `remote` (a tracking branch in refs/remotes/), `plain` (other
 +      `remote` (a remote-tracking branch in refs/remotes/), `plain` (other
        refs).
  +
  The value for these configuration variables is a list of colors (at most
@@@ -725,7 -701,7 +718,7 @@@ color.diff.<slot>:
  color.decorate.<slot>::
        Use customized color for 'git log --decorate' output.  `<slot>` is one
        of `branch`, `remoteBranch`, `tag`, `stash` or `HEAD` for local
 -      branches, remote tracking branches, tags, stash and HEAD, respectively.
 +      branches, remote-tracking branches, tags, stash and HEAD, respectively.
  
  color.grep::
        When set to `always`, always highlight matches.  When `false` (or
@@@ -790,8 -766,7 +783,8 @@@ color.status.<slot>:
        one of `header` (the header text of the status message),
        `added` or `updated` (files which are added but not committed),
        `changed` (files which are changed but not added in the index),
 -      `untracked` (files which are not tracked by git), or
 +      `untracked` (files which are not tracked by git),
 +      `branch` (the current branch), or
        `nobranch` (the color the 'no branch' warning is shown in, defaulting
        to red). The values of these variables may be specified as in
        color.branch.<slot>.
@@@ -897,11 -872,6 +890,11 @@@ diff.wordRegex:
        sequences that match the regular expression are "words", all other
        characters are *ignorable* whitespace.
  
 +fetch.recurseSubmodules::
 +      A boolean value which changes the behavior for fetch and pull, the
 +      default is to not recursively fetch populated sumodules unless
 +      configured otherwise.
 +
  fetch.unpackLimit::
        If the number of objects fetched over the git native
        transfer is below this
@@@ -996,7 -966,7 +989,7 @@@ gc.packrefs:
        Running `git pack-refs` in a repository renders it
        unclonable by Git versions prior to 1.5.1.2 over dumb
        transports such as HTTP.  This variable determines whether
 -      'git gc' runs `git pack-refs`. This can be set to `nobare`
 +      'git gc' runs `git pack-refs`. This can be set to `notbare`
        to enable it within all non-bare repos or it can be set to a
        boolean value.  The default is `true`.
  
@@@ -1125,7 -1095,7 +1118,7 @@@ gui.newbranchtemplate:
        linkgit:git-gui[1].
  
  gui.pruneduringfetch::
 -      "true" if linkgit:git-gui[1] should prune tracking branches when
 +      "true" if linkgit:git-gui[1] should prune remote-tracking branches when
        performing a fetch. The default value is "false".
  
  gui.trustmtime::
@@@ -1554,13 -1524,11 +1547,13 @@@ pack.packSizeLimit:
        supported.
  
  pager.<cmd>::
 -      Allows turning on or off pagination of the output of a
 -      particular git subcommand when writing to a tty.  If
 -      `\--paginate` or `\--no-pager` is specified on the command line,
 -      it takes precedence over this option.  To disable pagination for
 -      all commands, set `core.pager` or `GIT_PAGER` to `cat`.
 +      If the value is boolean, turns on or off pagination of the
 +      output of a particular git subcommand when writing to a tty.
 +      Otherwise, turns on pagination for the subcommand using the
 +      pager specified by the value of `pager.<cmd>`.  If `\--paginate`
 +      or `\--no-pager` is specified on the command line, it takes
 +      precedence over this option.  To disable pagination for all
 +      commands, set `core.pager` or `GIT_PAGER` to `cat`.
  
  pretty.<name>::
        Alias for a --pretty= format string, as specified in
@@@ -1816,13 -1784,6 +1809,13 @@@ submodule.<name>.update:
        URL and other values found in the `.gitmodules` file.  See
        linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.
  
 +submodule.<name>.fetchRecurseSubmodules::
 +      This option can be used to enable/disable recursive fetching of this
 +      submodule. It can be overriden by using the --[no-]recurse-submodules
 +      command line option to "git fetch" and "git pull".
 +      This setting will override that from in the linkgit:gitmodules[5]
 +      file.
 +
  submodule.<name>.ignore::
        Defines under what circumstances "git status" and the diff family show
        a submodule as modified. When set to "all", it will never be considered
diff --combined Documentation/git.txt
index 012837145e86b144d4676c9e1517486226e137df,7433601f353849e889388e4322963d179d427165..72e98aaa0f4471ebb9c52c5cfe976dd893cb3abc
@@@ -44,39 -44,31 +44,39 @@@ unreleased) version of git, that is ava
  branch of the `git.git` repository.
  Documentation for older releases are available here:
  
 -* link:v1.7.3.2/git.html[documentation for release 1.7.3.2]
 +* link:v1.7.3.4/git.html[documentation for release 1.7.3.4]
  
  * release notes for
 +  link:RelNotes/1.7.3.4.txt[1.7.3.4],
 +  link:RelNotes/1.7.3.3.txt[1.7.3.3],
    link:RelNotes/1.7.3.2.txt[1.7.3.2],
    link:RelNotes/1.7.3.1.txt[1.7.3.1],
    link:RelNotes/1.7.3.txt[1.7.3].
  
 -* link:v1.7.2.3/git.html[documentation for release 1.7.2.3]
 +* link:v1.7.2.5/git.html[documentation for release 1.7.2.5]
  
  * release notes for
 +  link:RelNotes/1.7.2.5.txt[1.7.2.5],
 +  link:RelNotes/1.7.2.4.txt[1.7.2.4],
    link:RelNotes/1.7.2.3.txt[1.7.2.3],
    link:RelNotes/1.7.2.2.txt[1.7.2.2],
    link:RelNotes/1.7.2.1.txt[1.7.2.1],
    link:RelNotes/1.7.2.txt[1.7.2].
  
 -* link:v1.7.1.2/git.html[documentation for release 1.7.1.2]
 +* link:v1.7.1.4/git.html[documentation for release 1.7.1.4]
  
  * release notes for
 +  link:RelNotes/1.7.1.4.txt[1.7.1.4],
 +  link:RelNotes/1.7.1.3.txt[1.7.1.3],
    link:RelNotes/1.7.1.2.txt[1.7.1.2],
    link:RelNotes/1.7.1.1.txt[1.7.1.1],
    link:RelNotes/1.7.1.txt[1.7.1].
  
 -* link:v1.7.0.7/git.html[documentation for release 1.7.0.7]
 +* link:v1.7.0.9/git.html[documentation for release 1.7.0.9]
  
  * release notes for
 +  link:RelNotes/1.7.0.9.txt[1.7.0.9],
 +  link:RelNotes/1.7.0.8.txt[1.7.0.8],
    link:RelNotes/1.7.0.7.txt[1.7.0.7],
    link:RelNotes/1.7.0.6.txt[1.7.0.6],
    link:RelNotes/1.7.0.5.txt[1.7.0.5],
    link:RelNotes/1.7.0.1.txt[1.7.0.1],
    link:RelNotes/1.7.0.txt[1.7.0].
  
 -* link:v1.6.6.2/git.html[documentation for release 1.6.6.2]
 +* link:v1.6.6.3/git.html[documentation for release 1.6.6.3]
  
  * release notes for
 +  link:RelNotes/1.6.6.3.txt[1.6.6.3],
    link:RelNotes/1.6.6.2.txt[1.6.6.2],
    link:RelNotes/1.6.6.1.txt[1.6.6.1],
    link:RelNotes/1.6.6.txt[1.6.6].
  
 -* link:v1.6.5.8/git.html[documentation for release 1.6.5.8]
 +* link:v1.6.5.9/git.html[documentation for release 1.6.5.9]
  
  * release notes for
 +  link:RelNotes/1.6.5.9.txt[1.6.5.9],
    link:RelNotes/1.6.5.8.txt[1.6.5.8],
    link:RelNotes/1.6.5.7.txt[1.6.5.7],
    link:RelNotes/1.6.5.6.txt[1.6.5.6],
    link:RelNotes/1.6.5.1.txt[1.6.5.1],
    link:RelNotes/1.6.5.txt[1.6.5].
  
 -* link:v1.6.4.4/git.html[documentation for release 1.6.4.4]
 +* link:v1.6.4.5/git.html[documentation for release 1.6.4.5]
  
  * release notes for
 +  link:RelNotes/1.6.4.5.txt[1.6.4.5],
    link:RelNotes/1.6.4.4.txt[1.6.4.4],
    link:RelNotes/1.6.4.3.txt[1.6.4.3],
    link:RelNotes/1.6.4.2.txt[1.6.4.2],
@@@ -296,7 -285,7 +296,7 @@@ help ...`
        This can also be controlled by setting the GIT_WORK_TREE
        environment variable and the core.worktree configuration
        variable. It can be an absolute path or relative path to
-       the directory specified by --git-dir or GIT_DIR.
+       current working directory.
        Note: If --git-dir or GIT_DIR are specified but none of
        --work-tree, GIT_WORK_TREE and core.worktree is specified,
        the current working directory is regarded as the top directory
diff --combined Makefile
index ff351543754f231a92c8cf3aa3b12d6693ba119a,f96d990d5ac4556a1b5c0fc839931b078e98340f..775ee838c332c7311df34a98448fc3723c6bd95e
+++ b/Makefile
@@@ -70,11 -70,6 +70,11 @@@ all:
  #
  # Define NO_STRTOK_R if you don't have strtok_r in the C library.
  #
 +# Define NO_FNMATCH if you don't have fnmatch in the C library.
 +#
 +# Define NO_FNMATCH_CASEFOLD if your fnmatch function doesn't have the
 +# FNM_CASEFOLD GNU extension.
 +#
  # Define NO_LIBGEN_H if you don't have libgen.h.
  #
  # Define NEEDS_LIBGEN if your libgen needs -lgen when linking
  # 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 ASCIIDOC8 if you want to format documentation with AsciiDoc 8
 +# 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).
  #
 -# Define ASCIIDOC_NO_ROFF if your DocBook XSL escapes raw roff directives
 -# (versions 1.72 and later and 1.68.1 and earlier).
 +# Define ASCIIDOC_ROFF if your DocBook XSL does not escape raw roff directives
 +# (versions 1.68.1 through v1.72).
  #
  # Define GNU_ROFF if your target system uses GNU groff.  This forces
  # apostrophes to be ASCII so that cut&pasting examples to the shell
@@@ -406,7 -401,6 +406,7 @@@ EXTRA_PROGRAMS 
  # ... and all the rest that could be moved out of bindir to gitexecdir
  PROGRAMS += $(EXTRA_PROGRAMS)
  
 +PROGRAM_OBJS += daemon.o
  PROGRAM_OBJS += fast-import.o
  PROGRAM_OBJS += imap-send.o
  PROGRAM_OBJS += shell.o
@@@ -431,6 -425,7 +431,7 @@@ TEST_PROGRAMS_NEED_X += test-run-comman
  TEST_PROGRAMS_NEED_X += test-sha1
  TEST_PROGRAMS_NEED_X += test-sigchain
  TEST_PROGRAMS_NEED_X += test-string-pool
+ TEST_PROGRAMS_NEED_X += test-subprocess
  TEST_PROGRAMS_NEED_X += test-svn-fe
  TEST_PROGRAMS_NEED_X += test-treap
  TEST_PROGRAMS_NEED_X += test-index-version
@@@ -502,9 -497,6 +503,9 @@@ LIB_H += compat/bswap.
  LIB_H += compat/cygwin.h
  LIB_H += compat/mingw.h
  LIB_H += compat/win32/pthread.h
 +LIB_H += compat/win32/syslog.h
 +LIB_H += compat/win32/sys/poll.h
 +LIB_H += compat/win32/dirent.h
  LIB_H += csum-file.h
  LIB_H += decorate.h
  LIB_H += delta.h
@@@ -526,7 -518,6 +527,7 @@@ LIB_H += mailmap.
  LIB_H += merge-recursive.h
  LIB_H += notes.h
  LIB_H += notes-cache.h
 +LIB_H += notes-merge.h
  LIB_H += object.h
  LIB_H += pack.h
  LIB_H += pack-refs.h
@@@ -617,7 -608,6 +618,7 @@@ LIB_OBJS += merge-recursive.
  LIB_OBJS += name-hash.o
  LIB_OBJS += notes.o
  LIB_OBJS += notes-cache.o
 +LIB_OBJS += notes-merge.o
  LIB_OBJS += object.o
  LIB_OBJS += pack-check.o
  LIB_OBJS += pack-refs.o
@@@ -673,7 -663,6 +674,7 @@@ LIB_OBJS += write_or_die.
  LIB_OBJS += ws.o
  LIB_OBJS += wt-status.o
  LIB_OBJS += xdiff-interface.o
 +LIB_OBJS += zlib.o
  
  BUILTIN_OBJS += builtin/add.o
  BUILTIN_OBJS += builtin/annotate.o
@@@ -740,8 -729,6 +741,8 @@@ BUILTIN_OBJS += builtin/read-tree.
  BUILTIN_OBJS += builtin/receive-pack.o
  BUILTIN_OBJS += builtin/reflog.o
  BUILTIN_OBJS += builtin/remote.o
 +BUILTIN_OBJS += builtin/remote-ext.o
 +BUILTIN_OBJS += builtin/remote-fd.o
  BUILTIN_OBJS += builtin/replace.o
  BUILTIN_OBJS += builtin/rerere.o
  BUILTIN_OBJS += builtin/reset.o
@@@ -860,7 -847,6 +861,7 @@@ ifeq ($(uname_S),SunOS
        NO_MKDTEMP = YesPlease
        NO_MKSTEMPS = YesPlease
        NO_REGEX = YesPlease
 +      NO_FNMATCH_CASEFOLD = YesPlease
        ifeq ($(uname_R),5.6)
                SOCKLEN_T = int
                NO_HSTRERROR = YesPlease
@@@ -1003,7 -989,6 +1004,7 @@@ ifeq ($(uname_S),IRIX
        # 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
@@@ -1023,7 -1008,6 +1024,7 @@@ ifeq ($(uname_S),IRIX64
        # 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
@@@ -1069,7 -1053,6 +1070,7 @@@ ifeq ($(uname_S),Windows
        NO_STRCASESTR = YesPlease
        NO_STRLCPY = YesPlease
        NO_STRTOK_R = YesPlease
 +      NO_FNMATCH = YesPlease
        NO_MEMMEM = YesPlease
        # NEEDS_LIBICONV = YesPlease
        NO_ICONV = YesPlease
        NO_SVN_TESTS = YesPlease
        NO_PERL_MAKEMAKER = YesPlease
        RUNTIME_PREFIX = YesPlease
 -      NO_POSIX_ONLY_PROGRAMS = YesPlease
        NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
        NO_NSEC = YesPlease
        USE_WIN32_MMAP = 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/fnmatch/fnmatch.o compat/winansi.o compat/win32/pthread.o
 -      COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/fnmatch -Icompat/regex -Icompat/fnmatch -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
 +      COMPAT_OBJS = compat/msvc.o compat/winansi.o \
 +              compat/win32/pthread.o compat/win32/syslog.o \
 +              compat/win32/sys/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 = advapi32.lib shell32.lib wininet.lib ws2_32.lib
 +      EXTLIBS = user32.lib advapi32.lib shell32.lib wininet.lib ws2_32.lib
        PTHREAD_LIBS =
        lib =
  ifndef DEBUG
  endif
        X = .exe
  endif
 +ifeq ($(uname_S),Interix)
 +      NO_SYS_POLL_H = YesPlease
 +      NO_INTTYPES_H = YesPlease
 +      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
 +      endif
 +      ifeq ($(uname_R),5.2)
 +              NO_INET_NTOP = YesPlease
 +              NO_INET_PTON = YesPlease
 +      endif
 +endif
  ifneq (,$(findstring MINGW,$(uname_S)))
        pathsep = ;
        NO_PREAD = YesPlease
        NO_STRCASESTR = YesPlease
        NO_STRLCPY = YesPlease
        NO_STRTOK_R = YesPlease
 +      NO_FNMATCH = YesPlease
        NO_MEMMEM = YesPlease
        NEEDS_LIBICONV = YesPlease
        OLD_ICONV = YesPlease
        NO_SVN_TESTS = YesPlease
        NO_PERL_MAKEMAKER = YesPlease
        RUNTIME_PREFIX = YesPlease
 -      NO_POSIX_ONLY_PROGRAMS = YesPlease
        NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
        NO_NSEC = YesPlease
        USE_WIN32_MMAP = YesPlease
        NO_PYTHON = YesPlease
        BLK_SHA1 = YesPlease
        ETAGS_TARGET = ETAGS
 -      COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch -Icompat/win32
 +      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/fnmatch/fnmatch.o compat/winansi.o \
 -              compat/win32/pthread.o
 +      COMPAT_OBJS += compat/mingw.o compat/winansi.o \
 +              compat/win32/pthread.o compat/win32/syslog.o \
 +              compat/win32/sys/poll.o compat/win32/dirent.o
        EXTLIBS += -lws2_32
        PTHREAD_LIBS =
        X = .exe
@@@ -1289,6 -1247,9 +1290,6 @@@ ifdef ZLIB_PAT
  endif
  EXTLIBS += -lz
  
 -ifndef NO_POSIX_ONLY_PROGRAMS
 -      PROGRAM_OBJS += daemon.o
 -endif
  ifndef NO_OPENSSL
        OPENSSL_LIBSSL = -lssl
        ifdef OPENSSLDIR
        BLK_SHA1 = 1
        OPENSSL_LIBSSL =
  endif
 +ifdef NO_OPENSSL
 +      LIB_4_CRYPTO =
 +else
  ifdef NEEDS_SSL_WITH_CRYPTO
        LIB_4_CRYPTO = $(OPENSSL_LINK) -lcrypto -lssl
  else
        LIB_4_CRYPTO = $(OPENSSL_LINK) -lcrypto
  endif
 +endif
  ifdef NEEDS_LIBICONV
        ifdef ICONVDIR
                BASIC_CFLAGS += -I$(ICONVDIR)/include
@@@ -1386,17 -1343,6 +1387,17 @@@ ifdef NO_STRTOK_
        COMPAT_CFLAGS += -DNO_STRTOK_R
        COMPAT_OBJS += compat/strtok_r.o
  endif
 +ifdef NO_FNMATCH
 +      COMPAT_CFLAGS += -Icompat/fnmatch
 +      COMPAT_CFLAGS += -DNO_FNMATCH
 +      COMPAT_OBJS += compat/fnmatch/fnmatch.o
 +else
 +ifdef NO_FNMATCH_CASEFOLD
 +      COMPAT_CFLAGS += -Icompat/fnmatch
 +      COMPAT_CFLAGS += -DNO_FNMATCH_CASEFOLD
 +      COMPAT_OBJS += compat/fnmatch/fnmatch.o
 +endif
 +endif
  ifdef NO_SETENV
        COMPAT_CFLAGS += -DNO_SETENV
        COMPAT_OBJS += compat/setenv.o
@@@ -1415,15 -1361,6 +1416,15 @@@ endi
  ifdef NO_SYS_SELECT_H
        BASIC_CFLAGS += -DNO_SYS_SELECT_H
  endif
 +ifdef NO_SYS_POLL_H
 +      BASIC_CFLAGS += -DNO_SYS_POLL_H
 +endif
 +ifdef NO_INTTYPES_H
 +      BASIC_CFLAGS += -DNO_INTTYPES_H
 +endif
 +ifdef NO_INITGROUPS
 +      BASIC_CFLAGS += -DNO_INITGROUPS
 +endif
  ifdef NO_MMAP
        COMPAT_CFLAGS += -DNO_MMAP
        COMPAT_OBJS += compat/mmap.o
@@@ -1461,11 -1398,9 +1462,11 @@@ endi
  endif
  ifdef NO_INET_NTOP
        LIB_OBJS += compat/inet_ntop.o
 +      BASIC_CFLAGS += -DNO_INET_NTOP
  endif
  ifdef NO_INET_PTON
        LIB_OBJS += compat/inet_pton.o
 +      BASIC_CFLAGS += -DNO_INET_PTON
  endif
  
  ifdef NO_ICONV
@@@ -1480,10 -1415,6 +1481,10 @@@ ifdef NO_DEFLATE_BOUN
        BASIC_CFLAGS += -DNO_DEFLATE_BOUND
  endif
  
 +ifdef NO_POSIX_GOODIES
 +      BASIC_CFLAGS += -DNO_POSIX_GOODIES
 +endif
 +
  ifdef BLK_SHA1
        SHA1_HEADER = "block-sha1/sha1.h"
        LIB_OBJS += block-sha1/sha1.o
@@@ -1588,8 -1519,8 +1589,8 @@@ ifndef 
  endif
  endif
  
 -ifdef ASCIIDOC8
 -      export ASCIIDOC8
 +ifdef ASCIIDOC7
 +      export ASCIIDOC7
  endif
  
  # Shell quote (do not use $(call) to accommodate ancient setups);
@@@ -1681,8 -1612,6 +1682,8 @@@ git$X: git.o $(BUILTIN_OBJS) $(GITLIBS
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ git.o \
                $(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
  
 +help.o: common-cmds.h
 +
  builtin/help.o: common-cmds.h
  builtin/help.s builtin/help.o: EXTRA_CPPFLAGS = \
        '-DGIT_HTML_PATH="$(htmldir_SQ)"' \
@@@ -1838,8 -1767,6 +1839,8 @@@ XDIFF_OBJS = xdiff/xdiffi.o xdiff/xprep
        xdiff/xmerge.o xdiff/xpatience.o
  VCSSVN_OBJS = vcs-svn/string_pool.o vcs-svn/line_buffer.o \
        vcs-svn/repo_tree.o vcs-svn/fast_export.o vcs-svn/svndump.o
 +VCSSVN_TEST_OBJS = test-obj-pool.o test-string-pool.o \
 +      test-line-buffer.o test-treap.o
  OBJECTS := $(GIT_OBJS) $(XDIFF_OBJS) $(VCSSVN_OBJS)
  
  dep_files := $(foreach f,$(OBJECTS),$(dir $f).depend/$(notdir $f).d)
@@@ -1948,26 -1875,25 +1949,26 @@@ builtin/branch.o builtin/checkout.o bui
  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/grep.o: thread-utils.h
 +builtin/grep.o builtin/pack-objects.o transport-helper.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
 -builtin/pack-objects.o: thread-utils.h
  connect.o transport.o http-backend.o: url.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
 +http.o http-walker.o http-push.o http-fetch.o remote-curl.o: http.h url.h
  
  xdiff-interface.o $(XDIFF_OBJS): \
        xdiff/xinclude.h xdiff/xmacros.h xdiff/xdiff.h xdiff/xtypes.h \
        xdiff/xutils.h xdiff/xprepare.h xdiff/xdiffi.h xdiff/xemit.h
  
 -$(VCSSVN_OBJS): \
 +$(VCSSVN_OBJS) $(VCSSVN_TEST_OBJS): $(LIB_H) \
        vcs-svn/obj_pool.h vcs-svn/trp.h vcs-svn/string_pool.h \
        vcs-svn/line_buffer.h vcs-svn/repo_tree.h vcs-svn/fast_export.h \
        vcs-svn/svndump.h
 +
 +test-svn-fe.o: vcs-svn/svndump.h
  endif
  
  exec_cmd.s exec_cmd.o: EXTRA_CPPFLAGS = \
@@@ -2002,7 -1928,7 +2003,7 @@@ git-%$X: %.o $(GITLIBS
  
  git-imap-send$X: imap-send.o $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
 -              $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL)
 +              $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL) $(LIB_4_CRYPTO)
  
  git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
diff --combined cache.h
index 32170c293d8f2e303b246cd5892f4d0b5d848861,123dd4bb93ebfd387a79bd6a4ccf012257a8b0b0..d83d68c859904fadbe2501cabd8575be09131d7b
+++ b/cache.h
@@@ -170,26 -170,26 +170,26 @@@ struct cache_entry 
   *
   * In-memory only flags
   */
 -#define CE_UPDATE    (0x10000)
 -#define CE_REMOVE    (0x20000)
 -#define CE_UPTODATE  (0x40000)
 -#define CE_ADDED     (0x80000)
 +#define CE_UPDATE            (1 << 16)
 +#define CE_REMOVE            (1 << 17)
 +#define CE_UPTODATE          (1 << 18)
 +#define CE_ADDED             (1 << 19)
  
 -#define CE_HASHED    (0x100000)
 -#define CE_UNHASHED  (0x200000)
 -#define CE_CONFLICTED (0x800000)
 +#define CE_HASHED            (1 << 20)
 +#define CE_UNHASHED          (1 << 21)
 +#define CE_WT_REMOVE         (1 << 22) /* remove in work directory */
 +#define CE_CONFLICTED        (1 << 23)
  
 -#define CE_WT_REMOVE (0x400000) /* remove in work directory */
 -
 -#define CE_UNPACKED  (0x1000000)
 +#define CE_UNPACKED          (1 << 24)
 +#define CE_NEW_SKIP_WORKTREE (1 << 25)
  
  /*
   * Extended on-disk flags
   */
 -#define CE_INTENT_TO_ADD 0x20000000
 -#define CE_SKIP_WORKTREE 0x40000000
 +#define CE_INTENT_TO_ADD     (1 << 29)
 +#define CE_SKIP_WORKTREE     (1 << 30)
  /* CE_EXTENDED2 is for future extension */
 -#define CE_EXTENDED2 0x80000000
 +#define CE_EXTENDED2         (1 << 31)
  
  #define CE_EXTENDED_FLAGS (CE_INTENT_TO_ADD | CE_SKIP_WORKTREE)
  
@@@ -428,7 -428,7 +428,7 @@@ extern const char **get_pathspec(const 
  extern void setup_work_tree(void);
  extern const char *setup_git_directory_gently(int *);
  extern const char *setup_git_directory(void);
 -extern const char *prefix_path(const char *prefix, int len, const char *path);
 +extern char *prefix_path(const char *prefix, int len, const char *path);
  extern const char *prefix_filename(const char *prefix, int len, const char *path);
  extern int check_filename(const char *prefix, const char *name);
  extern void verify_filename(const char *prefix, const char *name);
@@@ -545,7 -545,6 +545,7 @@@ extern int assume_unchanged
  extern int prefer_symlink_refs;
  extern int log_all_ref_updates;
  extern int warn_ambiguous_refs;
 +extern int unique_abbrev_extra_length;
  extern int shared_repository;
  extern const char *apply_default_whitespace;
  extern const char *apply_default_ignorewhitespace;
@@@ -860,7 -859,7 +860,7 @@@ struct cache_def 
  
  extern int has_symlink_leading_path(const char *name, int len);
  extern int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
 -extern int has_symlink_or_noent_leading_path(const char *name, int len);
 +extern int check_leading_path(const char *name, int len);
  extern int has_dirs_only_path(const char *name, int len, int prefix_len);
  extern void schedule_dir_for_removal(const char *name, int len);
  extern void remove_scheduled_dirs(void);
@@@ -987,6 -986,7 +987,7 @@@ extern int git_config_parse_parameter(c
  extern int git_config_parse_environment(void);
  extern int git_config_from_parameters(config_fn_t fn, void *data);
  extern int git_config(config_fn_t fn, void *);
+ extern int git_config_early(config_fn_t fn, void *, const char *repo_config);
  extern int git_parse_ulong(const char *, unsigned long *);
  extern int git_config_int(const char *, const char *);
  extern unsigned long git_config_ulong(const char *, const char *);
@@@ -1004,9 -1004,6 +1005,9 @@@ extern int git_env_bool(const char *, i
  extern int git_config_system(void);
  extern int git_config_global(void);
  extern int config_error_nonbool(const char *);
 +extern const char *get_log_output_encoding(void);
 +extern const char *get_commit_output_encoding(void);
 +
  extern const char *config_exclusive_filename;
  
  #define MAX_GITNAME (1000)
@@@ -1066,6 -1063,7 +1067,7 @@@ __attribute__((format (printf, 1, 2))
  extern void trace_printf(const char *format, ...);
  __attribute__((format (printf, 2, 3)))
  extern void trace_argv_printf(const char **argv, const char *format, ...);
+ extern void trace_repo_setup(const char *prefix);
  
  /* convert.c */
  /* returns 1 if *dst was used */
@@@ -1091,17 -1089,15 +1093,17 @@@ void shift_tree_by(const unsigned char 
  /*
   * whitespace rules.
   * used by both diff and apply
 + * last two digits are tab width
   */
 -#define WS_BLANK_AT_EOL         01
 -#define WS_SPACE_BEFORE_TAB   02
 -#define WS_INDENT_WITH_NON_TAB        04
 -#define WS_CR_AT_EOL           010
 -#define WS_BLANK_AT_EOF        020
 -#define WS_TAB_IN_INDENT       040
 +#define WS_BLANK_AT_EOL         0100
 +#define WS_SPACE_BEFORE_TAB     0200
 +#define WS_INDENT_WITH_NON_TAB  0400
 +#define WS_CR_AT_EOL           01000
 +#define WS_BLANK_AT_EOF        02000
 +#define WS_TAB_IN_INDENT       04000
  #define WS_TRAILING_SPACE      (WS_BLANK_AT_EOL|WS_BLANK_AT_EOF)
 -#define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB)
 +#define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB|8)
 +#define WS_TAB_WIDTH_MASK        077
  extern unsigned whitespace_rule_cfg;
  extern unsigned whitespace_rule(const char *);
  extern unsigned parse_whitespace_rule(const char *);
@@@ -1110,7 -1106,6 +1112,7 @@@ extern void ws_check_emit(const char *l
  extern char *whitespace_error_string(unsigned ws);
  extern void ws_fix_copy(struct strbuf *, const char *, int, unsigned, int *);
  extern int ws_blank_line(const char *line, int len, unsigned ws_rule);
 +#define ws_tab_width(rule)     ((rule) & WS_TAB_WIDTH_MASK)
  
  /* ls-files */
  int report_path_error(const char *ps_matched, const char **pathspec, int prefix_offset);
@@@ -1124,7 -1119,6 +1126,7 @@@ const char *split_cmdline_strerror(int 
  /* git.c */
  struct startup_info {
        int have_repository;
 +      const char *prefix;
  };
  extern struct startup_info *startup_info;
  
diff --combined config.c
index d73b090b6a60d05b18309755dee4ce3b6e055b2d,c431f41c5a0d0645a53242e046350ff95a8b48f5..625e0518767712583f917762634c2fc852c4d2eb
+++ b/config.c
@@@ -410,7 -410,7 +410,7 @@@ unsigned long git_config_ulong(const ch
        return ret;
  }
  
 -int git_config_maybe_bool(const char *name, const char *value)
 +static int git_config_maybe_bool_text(const char *name, const char *value)
  {
        if (!value)
                return 1;
        return -1;
  }
  
 +int git_config_maybe_bool(const char *name, const char *value)
 +{
 +      long v = git_config_maybe_bool_text(name, value);
 +      if (0 <= v)
 +              return v;
 +      if (git_parse_long(value, &v))
 +              return !!v;
 +      return -1;
 +}
 +
  int git_config_bool_or_int(const char *name, const char *value, int *is_bool)
  {
 -      int v = git_config_maybe_bool(name, value);
 +      int v = git_config_maybe_bool_text(name, value);
        if (0 <= v) {
                *is_bool = 1;
                return v;
@@@ -499,13 -489,6 +499,13 @@@ static int git_default_core_config(cons
                return 0;
        }
  
 +      if (!strcmp(var, "core.abbrevguard")) {
 +              unique_abbrev_extra_length = git_config_int(var, value);
 +              if (unique_abbrev_extra_length < 0)
 +                      unique_abbrev_extra_length = 0;
 +              return 0;
 +      }
 +
        if (!strcmp(var, "core.bare")) {
                is_bare_repository_cfg = git_config_bool(var, value);
                return 0;
@@@ -852,10 -835,9 +852,9 @@@ int git_config_from_parameters(config_f
        return 0;
  }
  
- int git_config(config_fn_t fn, void *data)
+ int git_config_early(config_fn_t fn, void *data, const char *repo_config)
  {
        int ret = 0, found = 0;
-       char *repo_config = NULL;
        const char *home = NULL;
  
        /* Setting $GIT_CONFIG makes git read _only_ the given config file. */
                free(user_config);
        }
  
-       repo_config = git_pathdup("config");
-       if (!access(repo_config, R_OK)) {
+       if (repo_config && !access(repo_config, R_OK)) {
                ret += git_config_from_file(fn, repo_config, data);
                found += 1;
        }
-       free(repo_config);
  
        ret += git_config_from_parameters(fn, data);
        if (config_parameters)
                found += 1;
  
 -      if (found == 0)
 -              return -1;
 -      return ret;
 +      return ret == 0 ? found : ret;
  }
  
+ int git_config(config_fn_t fn, void *data)
+ {
+       char *repo_config = NULL;
+       int ret;
+       repo_config = git_pathdup("config");
+       ret = git_config_early(fn, data, repo_config);
+       if (repo_config)
+               free(repo_config);
+       return ret;
+ }
  /*
   * Find all the stuff for git_config_set() below.
   */
diff --combined environment.c
index c79f2a9b561de77e27abd7ee26831e2a58beb259,149c132304fbffda4c942aef898932433263adcb..9564475f429312a467a020106f7443112367d5da
@@@ -21,7 -21,6 +21,7 @@@ int prefer_symlink_refs
  int is_bare_repository_cfg = -1; /* unspecified */
  int log_all_ref_updates = -1; /* unspecified */
  int warn_ambiguous_refs = 1;
 +int unique_abbrev_extra_length;
  int repository_format_version;
  const char *git_commit_encoding;
  const char *git_log_output_encoding;
@@@ -88,7 -87,6 +88,7 @@@ const char * const local_repo_env[LOCAL
  static void setup_git_env(void)
  {
        git_dir = getenv(GIT_DIR_ENVIRONMENT);
 +      git_dir = git_dir ? xstrdup(git_dir) : NULL;
        if (!git_dir) {
                git_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT);
                git_dir = git_dir ? xstrdup(git_dir) : NULL;
@@@ -139,30 -137,20 +139,20 @@@ static int git_work_tree_initialized
   */
  void set_git_work_tree(const char *new_work_tree)
  {
-       if (is_bare_repository_cfg >= 0)
-               die("cannot set work tree after initialization");
+       if (git_work_tree_initialized) {
+               new_work_tree = make_absolute_path(new_work_tree);
+               if (strcmp(new_work_tree, work_tree))
+                       die("internal error: work tree has already been set\n"
+                           "Current worktree: %s\nNew worktree: %s",
+                           work_tree, new_work_tree);
+               return;
+       }
        git_work_tree_initialized = 1;
-       free(work_tree);
        work_tree = xstrdup(make_absolute_path(new_work_tree));
-       is_bare_repository_cfg = 0;
  }
  
  const char *get_git_work_tree(void)
  {
-       if (!git_work_tree_initialized) {
-               work_tree = getenv(GIT_WORK_TREE_ENVIRONMENT);
-               /* core.bare = true overrides implicit and config work tree */
-               if (!work_tree && is_bare_repository_cfg < 1) {
-                       work_tree = git_work_tree_cfg;
-                       /* make_absolute_path also normalizes the path */
-                       if (work_tree && !is_absolute_path(work_tree))
-                               work_tree = xstrdup(make_absolute_path(git_path("%s", work_tree)));
-               } else if (work_tree)
-                       work_tree = xstrdup(make_absolute_path(work_tree));
-               git_work_tree_initialized = 1;
-               if (work_tree)
-                       is_bare_repository_cfg = 0;
-       }
        return work_tree;
  }
  
@@@ -173,43 -161,6 +163,43 @@@ char *get_object_directory(void
        return git_object_dir;
  }
  
 +int odb_mkstemp(char *template, size_t limit, const char *pattern)
 +{
 +      int fd;
 +      /*
 +       * we let the umask do its job, don't try to be more
 +       * restrictive except to remove write permission.
 +       */
 +      int mode = 0444;
 +      snprintf(template, limit, "%s/%s",
 +               get_object_directory(), pattern);
 +      fd = git_mkstemp_mode(template, mode);
 +      if (0 <= fd)
 +              return fd;
 +
 +      /* slow path */
 +      /* some mkstemp implementations erase template on failure */
 +      snprintf(template, limit, "%s/%s",
 +               get_object_directory(), pattern);
 +      safe_create_leading_directories(template);
 +      return xmkstemp_mode(template, mode);
 +}
 +
 +int odb_pack_keep(char *name, size_t namesz, unsigned char *sha1)
 +{
 +      int fd;
 +
 +      snprintf(name, namesz, "%s/pack/pack-%s.keep",
 +               get_object_directory(), sha1_to_hex(sha1));
 +      fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
 +      if (0 <= fd)
 +              return fd;
 +
 +      /* slow path */
 +      safe_create_leading_directories(name);
 +      return open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
 +}
 +
  char *get_index_file(void)
  {
        if (!git_index_file)
@@@ -231,14 -182,3 +221,14 @@@ int set_git_dir(const char *path
        setup_git_env();
        return 0;
  }
 +
 +const char *get_log_output_encoding(void)
 +{
 +      return git_log_output_encoding ? git_log_output_encoding
 +              : get_commit_output_encoding();
 +}
 +
 +const char *get_commit_output_encoding(void)
 +{
 +      return git_commit_encoding ? git_commit_encoding : "UTF-8";
 +}
diff --combined git.c
index d532576cdff244fcd3945ef4fcc580e1bf0b04ae,6793178210db64ae59d3a4d401f32d6d3bd5b1a1..68334f6a3134bb76a8ffc59e4da773400c59a388
--- 1/git.c
--- 2/git.c
+++ b/git.c
@@@ -19,22 -19,14 +19,22 @@@ static struct startup_info git_startup_
  static int use_pager = -1;
  struct pager_config {
        const char *cmd;
 -      int val;
 +      int want;
 +      char *value;
  };
  
  static int pager_command_config(const char *var, const char *value, void *data)
  {
        struct pager_config *c = data;
 -      if (!prefixcmp(var, "pager.") && !strcmp(var + 6, c->cmd))
 -              c->val = git_config_bool(var, value);
 +      if (!prefixcmp(var, "pager.") && !strcmp(var + 6, c->cmd)) {
 +              int b = git_config_maybe_bool(var, value);
 +              if (b >= 0)
 +                      c->want = b;
 +              else {
 +                      c->want = 1;
 +                      c->value = xstrdup(value);
 +              }
 +      }
        return 0;
  }
  
@@@ -43,12 -35,9 +43,12 @@@ int check_pager_config(const char *cmd
  {
        struct pager_config c;
        c.cmd = cmd;
 -      c.val = -1;
 +      c.want = -1;
 +      c.value = NULL;
        git_config(pager_command_config, &c);
 -      return c.val;
 +      if (c.value)
 +              pager_program = c.value;
 +      return c.want;
  }
  
  static void commit_pager_choice(void) {
@@@ -275,6 -264,10 +275,10 @@@ static int run_builtin(struct cmd_struc
                        use_pager = check_pager_config(p->cmd);
                if (use_pager == -1 && p->option & USE_PAGER)
                        use_pager = 1;
+               if ((p->option & (RUN_SETUP | RUN_SETUP_GENTLY)) &&
+                   startup_info->have_repository) /* get_git_dir() may set up repo, avoid that */
+                       trace_repo_setup(prefix);
        }
        commit_pager_choice();
  
@@@ -385,8 -378,6 +389,8 @@@ static void handle_internal_command(in
                { "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 },
                { "replace", cmd_replace, RUN_SETUP },
                { "repo-config", cmd_config, RUN_SETUP_GENTLY },
                { "rerere", cmd_rerere, RUN_SETUP },
diff --combined setup.c
index 91887a40b79d3bc2c82479bf7f09580c4c468665,be550af42a12a29d3e10a2d6cbfcc3287d46cbbc..3d732697af600ccc3c6017844c73e1d3b0dac738
+++ b/setup.c
@@@ -4,7 -4,7 +4,7 @@@
  static int inside_git_dir = -1;
  static int inside_work_tree = -1;
  
 -const char *prefix_path(const char *prefix, int len, const char *path)
 +char *prefix_path(const char *prefix, int len, const char *path)
  {
        const char *orig = path;
        char *sanitized = xmalloc(len + strlen(path) + 1);
@@@ -46,7 -46,7 +46,7 @@@ const char *prefix_filename(const char 
  {
        static char path[PATH_MAX];
  #ifndef WIN32
 -      if (!pfx || !*pfx || is_absolute_path(arg))
 +      if (!pfx_len || is_absolute_path(arg))
                return arg;
        memcpy(path, pfx, pfx_len);
        strcpy(path + pfx_len, arg);
@@@ -55,7 -55,7 +55,7 @@@
        /* don't add prefix to absolute paths, but still replace '\' by '/' */
        if (is_absolute_path(arg))
                pfx_len = 0;
 -      else
 +      else if (pfx_len)
                memcpy(path, pfx, pfx_len);
        strcpy(path + pfx_len, arg);
        for (p = path + pfx_len; *p; p++)
@@@ -208,24 -208,6 +208,6 @@@ int is_inside_work_tree(void
        return inside_work_tree;
  }
  
- /*
-  * set_work_tree() is only ever called if you set GIT_DIR explicitly.
-  * The old behaviour (which we retain here) is to set the work tree root
-  * to the cwd, unless overridden by the config, the command line, or
-  * GIT_WORK_TREE.
-  */
- static const char *set_work_tree(const char *dir)
- {
-       char buffer[PATH_MAX + 1];
-       if (!getcwd(buffer, sizeof(buffer)))
-               die ("Could not get the current working directory");
-       git_work_tree_cfg = xstrdup(buffer);
-       inside_work_tree = 1;
-       return NULL;
- }
  void setup_work_tree(void)
  {
        const char *work_tree, *git_dir;
                git_dir = make_absolute_path(git_dir);
        if (!work_tree || chdir(work_tree))
                die("This operation must be run in a work tree");
+       /*
+        * Make sure subsequent git processes find correct worktree
+        * if $GIT_WORK_TREE is set relative
+        */
+       if (getenv(GIT_WORK_TREE_ENVIRONMENT))
+               setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
        set_git_dir(make_relative_path(git_dir, work_tree));
        initialized = 1;
  }
  
- static int check_repository_format_gently(int *nongit_ok)
+ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
  {
-       git_config(check_repository_format_version, NULL);
+       char repo_config[PATH_MAX+1];
+       /*
+        * git_config() can't be used here because it calls git_pathdup()
+        * to get $GIT_CONFIG/config. That call will make setup_git_env()
+        * set git_dir to ".git".
+        *
+        * We are in gitdir setup, no git dir has been found useable yet.
+        * Use a gentler version of git_config() to check if this repo
+        * is a good one.
+        */
+       snprintf(repo_config, PATH_MAX, "%s/config", gitdir);
+       git_config_early(check_repository_format_version, NULL, repo_config);
        if (GIT_REPO_VERSION < repository_format_version) {
                if (!nongit_ok)
                        die ("Expected git repo version <= %d, found %d",
@@@ -314,64 -316,115 +316,115 @@@ const char *read_gitfile_gently(const c
  }
  
  static const char *setup_explicit_git_dir(const char *gitdirenv,
-                               const char *work_tree_env, int *nongit_ok)
+                                         char *cwd, int len,
+                                         int *nongit_ok)
  {
-       static char buffer[1024 + 1];
-       const char *retval;
+       const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
+       const char *worktree;
+       char *gitfile;
  
        if (PATH_MAX - 40 < strlen(gitdirenv))
                die("'$%s' too big", GIT_DIR_ENVIRONMENT);
+       gitfile = (char*)read_gitfile_gently(gitdirenv);
+       if (gitfile) {
+               gitfile = xstrdup(gitfile);
+               gitdirenv = gitfile;
+       }
        if (!is_git_directory(gitdirenv)) {
                if (nongit_ok) {
                        *nongit_ok = 1;
+                       free(gitfile);
                        return NULL;
                }
                die("Not a git repository: '%s'", gitdirenv);
        }
-       if (!work_tree_env) {
-               retval = set_work_tree(gitdirenv);
-               /* config may override worktree */
-               if (check_repository_format_gently(nongit_ok))
-                       return NULL;
-               return retval;
+       if (check_repository_format_gently(gitdirenv, nongit_ok)) {
+               free(gitfile);
+               return NULL;
        }
-       if (check_repository_format_gently(nongit_ok))
+       /* #3, #7, #11, #15, #19, #23, #27, #31 (see t1510) */
+       if (work_tree_env)
+               set_git_work_tree(work_tree_env);
+       else if (is_bare_repository_cfg > 0) {
+               if (git_work_tree_cfg) /* #22.2, #30 */
+                       die("core.bare and core.worktree do not make sense");
+               /* #18, #26 */
+               set_git_dir(gitdirenv);
+               free(gitfile);
                return NULL;
-       retval = get_relative_cwd(buffer, sizeof(buffer) - 1,
-                       get_git_work_tree());
-       if (!retval || !*retval)
+       }
+       else if (git_work_tree_cfg) { /* #6, #14 */
+               if (is_absolute_path(git_work_tree_cfg))
+                       set_git_work_tree(git_work_tree_cfg);
+               else {
+                       char core_worktree[PATH_MAX];
+                       if (chdir(gitdirenv))
+                               die_errno("Could not chdir to '%s'", gitdirenv);
+                       if (chdir(git_work_tree_cfg))
+                               die_errno("Could not chdir to '%s'", git_work_tree_cfg);
+                       if (!getcwd(core_worktree, PATH_MAX))
+                               die_errno("Could not get directory '%s'", git_work_tree_cfg);
+                       if (chdir(cwd))
+                               die_errno("Could not come back to cwd");
+                       set_git_work_tree(core_worktree);
+               }
+       }
+       else /* #2, #10 */
+               set_git_work_tree(".");
+       /* set_git_work_tree() must have been called by now */
+       worktree = get_git_work_tree();
+       /* both get_git_work_tree() and cwd are already normalized */
+       if (!strcmp(cwd, worktree)) { /* cwd == worktree */
+               set_git_dir(gitdirenv);
+               free(gitfile);
                return NULL;
-       set_git_dir(make_absolute_path(gitdirenv));
-       if (chdir(work_tree_env) < 0)
-               die_errno ("Could not chdir to '%s'", work_tree_env);
-       strcat(buffer, "/");
-       return retval;
- }
+       }
  
- static int cwd_contains_git_dir(const char **gitfile_dirp)
- {
-       const char *gitfile_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT);
-       *gitfile_dirp = gitfile_dir;
-       if (gitfile_dir) {
-               if (set_git_dir(gitfile_dir))
-                       die("Repository setup failed");
-               return 1;
+       if (!prefixcmp(cwd, worktree) &&
+           cwd[strlen(worktree)] == '/') { /* cwd inside worktree */
+               set_git_dir(make_absolute_path(gitdirenv));
+               if (chdir(worktree))
+                       die_errno("Could not chdir to '%s'", worktree);
+               cwd[len++] = '/';
+               cwd[len] = '\0';
+               free(gitfile);
+               return cwd + strlen(worktree) + 1;
        }
-       return is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT);
+       /* cwd outside worktree */
+       set_git_dir(gitdirenv);
+       free(gitfile);
+       return NULL;
  }
  
- static const char *setup_discovered_git_dir(const char *work_tree_env,
-               int offset, int len, char *cwd, int *nongit_ok)
+ static const char *setup_discovered_git_dir(const char *gitdir,
+                                           char *cwd, int offset, int len,
+                                           int *nongit_ok)
  {
-       int root_len;
+       if (check_repository_format_gently(gitdir, nongit_ok))
+               return NULL;
  
-       inside_git_dir = 0;
-       if (!work_tree_env)
-               inside_work_tree = 1;
-       root_len = offset_1st_component(cwd);
-       git_work_tree_cfg = xstrndup(cwd, offset > root_len ? offset : root_len);
-       if (check_repository_format_gently(nongit_ok))
+       /* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */
+       if (is_bare_repository_cfg > 0) {
+               set_git_dir(offset == len ? gitdir : make_absolute_path(gitdir));
+               if (chdir(cwd))
+                       die_errno("Could not come back to cwd");
                return NULL;
+       }
+       /* #0, #1, #5, #8, #9, #12, #13 */
+       set_git_work_tree(".");
+       if (strcmp(gitdir, DEFAULT_GIT_DIR_ENVIRONMENT))
+               set_git_dir(gitdir);
+       inside_git_dir = 0;
+       inside_work_tree = 1;
        if (offset == len)
                return NULL;
  
        return cwd + offset;
  }
  
- static const char *setup_bare_git_dir(const char *work_tree_env,
              int offset, int len, char *cwd, int *nongit_ok)
+ /* #16.1, #17.1, #20.1, #21.1, #22.1 (see t1510) */
static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongit_ok)
  {
        int root_len;
  
+       if (check_repository_format_gently(".", nongit_ok))
+               return NULL;
        inside_git_dir = 1;
-       if (!work_tree_env)
-               inside_work_tree = 0;
+       inside_work_tree = 0;
        if (offset != len) {
                if (chdir(cwd))
                        die_errno("Cannot come back to cwd");
                root_len = offset_1st_component(cwd);
                cwd[offset > root_len ? offset : root_len] = '\0';
                set_git_dir(cwd);
-       } else
+       }
+       else
                set_git_dir(".");
-       check_repository_format_gently(nongit_ok);
        return NULL;
  }
  
@@@ -428,11 -483,10 +483,10 @@@ static dev_t get_device_or_die(const ch
   */
  static const char *setup_git_directory_gently_1(int *nongit_ok)
  {
-       const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
        const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT);
        static char cwd[PATH_MAX+1];
-       const char *gitdirenv;
-       const char *gitfile_dir;
+       const char *gitdirenv, *ret;
+       char *gitfile;
        int len, offset, ceil_offset;
        dev_t current_device = 0;
        int one_filesystem = 1;
        if (nongit_ok)
                *nongit_ok = 0;
  
+       if (!getcwd(cwd, sizeof(cwd)-1))
+               die_errno("Unable to read current working directory");
+       offset = len = strlen(cwd);
        /*
         * If GIT_DIR is set explicitly, we're not going
         * to do any discovery, but we still do repository
         */
        gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
        if (gitdirenv)
-               return setup_explicit_git_dir(gitdirenv, work_tree_env, nongit_ok);
-       if (!getcwd(cwd, sizeof(cwd)-1))
-               die_errno("Unable to read current working directory");
+               return setup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok);
  
        ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs);
        if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
         * - ../../.git/
         *   etc.
         */
-       offset = len = strlen(cwd);
        one_filesystem = !git_env_bool("GIT_DISCOVERY_ACROSS_FILESYSTEM", 0);
        if (one_filesystem)
                current_device = get_device_or_die(".", NULL);
        for (;;) {
-               if (cwd_contains_git_dir(&gitfile_dir))
-                       return setup_discovered_git_dir(work_tree_env, offset,
-                                                       len, cwd, nongit_ok);
+               gitfile = (char*)read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT);
+               if (gitfile)
+                       gitdirenv = gitfile = xstrdup(gitfile);
+               else {
+                       if (is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT))
+                               gitdirenv = DEFAULT_GIT_DIR_ENVIRONMENT;
+               }
+               if (gitdirenv) {
+                       ret = setup_discovered_git_dir(gitdirenv,
+                                                      cwd, offset, len,
+                                                      nongit_ok);
+                       free(gitfile);
+                       return ret;
+               }
+               free(gitfile);
                if (is_git_directory("."))
-                       return setup_bare_git_dir(work_tree_env, offset,
-                                                       len, cwd, nongit_ok);
+                       return setup_bare_git_dir(cwd, offset, len, nongit_ok);
                while (--offset > ceil_offset && cwd[offset] != '/');
                if (offset <= ceil_offset)
                        return setup_nongit(cwd, nongit_ok);
@@@ -512,10 -580,8 +580,10 @@@ const char *setup_git_directory_gently(
        const char *prefix;
  
        prefix = setup_git_directory_gently_1(nongit_ok);
 -      if (startup_info)
 +      if (startup_info) {
                startup_info->have_repository = !nongit_ok || !*nongit_ok;
 +              startup_info->prefix = prefix;
 +      }
        return prefix;
  }
  
@@@ -592,7 -658,7 +660,7 @@@ int check_repository_format_version(con
  
  int check_repository_format(void)
  {
-       return check_repository_format_gently(NULL);
+       return check_repository_format_gently(get_git_dir(), NULL);
  }
  
  /*
   */
  const char *setup_git_directory(void)
  {
-       const char *retval = setup_git_directory_gently(NULL);
-       /* If the work tree is not the default one, recompute prefix */
-       if (inside_work_tree < 0) {
-               static char buffer[PATH_MAX + 1];
-               char *rel;
-               if (retval && chdir(retval))
-                       die_errno ("Could not jump back into original cwd");
-               rel = get_relative_cwd(buffer, PATH_MAX, get_git_work_tree());
-               if (rel && *rel && chdir(get_git_work_tree()))
-                       die_errno ("Could not jump to working directory");
-               return rel && *rel ? strcat(rel, "/") : NULL;
-       }
-       return retval;
+       return setup_git_directory_gently(NULL);
  }
diff --combined t/t0001-init.sh
index d44194c35fe5de72af0721a05bb1038f1720b4ac,28c1858c2b6834ed5a21285609f97b7a28a3e9a5..af8b9c52a9d4c899a05f8d2877de005cb4d1437d
@@@ -25,7 -25,7 +25,7 @@@ check_config () 
  
  test_expect_success 'plain' '
        (
 -              unset GIT_DIR GIT_WORK_TREE
 +              sane_unset GIT_DIR GIT_WORK_TREE &&
                mkdir plain &&
                cd plain &&
                git init
        check_config plain/.git false unset
  '
  
+ test_expect_success 'plain nested in bare' '
+       (
+               unset GIT_DIR GIT_WORK_TREE &&
+               git init --bare bare-ancestor.git &&
+               cd bare-ancestor.git &&
+               mkdir plain-nested &&
+               cd plain-nested &&
+               git init
+       ) &&
+       check_config bare-ancestor.git/plain-nested/.git false unset
+ '
+ test_expect_success 'plain through aliased command, outside any git repo' '
+       (
+               unset GIT_DIR GIT_WORK_TREE GIT_CONFIG_NOGLOBAL &&
+               HOME=$(pwd)/alias-config &&
+               export HOME &&
+               mkdir alias-config &&
+               echo "[alias] aliasedinit = init" >alias-config/.gitconfig &&
+               GIT_CEILING_DIRECTORIES=$(pwd) &&
+               export GIT_CEILING_DIRECTORIES &&
+               mkdir plain-aliased &&
+               cd plain-aliased &&
+               git aliasedinit
+       ) &&
+       check_config plain-aliased/.git false unset
+ '
+ test_expect_failure 'plain nested through aliased command' '
+       (
+               unset GIT_DIR GIT_WORK_TREE &&
+               git init plain-ancestor-aliased &&
+               cd plain-ancestor-aliased &&
+               echo "[alias] aliasedinit = init" >>.git/config &&
+               mkdir plain-nested &&
+               cd plain-nested &&
+               git aliasedinit
+       ) &&
+       check_config plain-ancestor-aliased/plain-nested/.git false unset
+ '
+ test_expect_failure 'plain nested in bare through aliased command' '
+       (
+               unset GIT_DIR GIT_WORK_TREE &&
+               git init --bare bare-ancestor-aliased.git &&
+               cd bare-ancestor-aliased.git &&
+               echo "[alias] aliasedinit = init" >>config &&
+               mkdir plain-nested &&
+               cd plain-nested &&
+               git aliasedinit
+       ) &&
+       check_config bare-ancestor-aliased.git/plain-nested/.git false unset
+ '
  test_expect_success 'plain with GIT_WORK_TREE' '
        if (
 -              unset GIT_DIR
 +              sane_unset GIT_DIR &&
                mkdir plain-wt &&
                cd plain-wt &&
                GIT_WORK_TREE=$(pwd) git init
  
  test_expect_success 'plain bare' '
        (
 -              unset GIT_DIR GIT_WORK_TREE GIT_CONFIG
 +              sane_unset GIT_DIR GIT_WORK_TREE GIT_CONFIG &&
                mkdir plain-bare-1 &&
                cd plain-bare-1 &&
                git --bare init
  
  test_expect_success 'plain bare with GIT_WORK_TREE' '
        if (
 -              unset GIT_DIR GIT_CONFIG
 +              sane_unset GIT_DIR GIT_CONFIG &&
                mkdir plain-bare-2 &&
                cd plain-bare-2 &&
                GIT_WORK_TREE=$(pwd) git --bare init
  test_expect_success 'GIT_DIR bare' '
  
        (
 -              unset GIT_CONFIG
 +              sane_unset GIT_CONFIG &&
                mkdir git-dir-bare.git &&
                GIT_DIR=git-dir-bare.git git init
        ) &&
  test_expect_success 'init --bare' '
  
        (
 -              unset GIT_DIR GIT_WORK_TREE GIT_CONFIG
 +              sane_unset GIT_DIR GIT_WORK_TREE GIT_CONFIG &&
                mkdir init-bare.git &&
                cd init-bare.git &&
                git init --bare
  test_expect_success 'GIT_DIR non-bare' '
  
        (
 -              unset GIT_CONFIG
 +              sane_unset GIT_CONFIG &&
                mkdir non-bare &&
                cd non-bare &&
                GIT_DIR=.git git init
  test_expect_success 'GIT_DIR & GIT_WORK_TREE (1)' '
  
        (
 -              unset GIT_CONFIG
 +              sane_unset GIT_CONFIG &&
                mkdir git-dir-wt-1.git &&
                GIT_WORK_TREE=$(pwd) GIT_DIR=git-dir-wt-1.git git init
        ) &&
  test_expect_success 'GIT_DIR & GIT_WORK_TREE (2)' '
  
        if (
 -              unset GIT_CONFIG
 +              sane_unset GIT_CONFIG &&
                mkdir git-dir-wt-2.git &&
                GIT_WORK_TREE=$(pwd) GIT_DIR=git-dir-wt-2.git git --bare init
        )
  test_expect_success 'reinit' '
  
        (
 -              unset GIT_CONFIG GIT_WORK_TREE GIT_CONFIG
 +              sane_unset GIT_CONFIG GIT_WORK_TREE GIT_CONFIG &&
  
                mkdir again &&
                cd again &&
@@@ -175,8 -231,8 +231,8 @@@ test_expect_success 'init with init.tem
                git config -f "$test_config"  init.templatedir "${HOME}/templatedir-source" &&
                mkdir templatedir-set &&
                cd templatedir-set &&
 -              unset GIT_CONFIG_NOGLOBAL &&
 -              unset GIT_TEMPLATE_DIR &&
 +              sane_unset GIT_CONFIG_NOGLOBAL &&
 +              sane_unset GIT_TEMPLATE_DIR &&
                NO_SET_GIT_TEMPLATE_DIR=t &&
                export NO_SET_GIT_TEMPLATE_DIR &&
                git init
  test_expect_success 'init --bare/--shared overrides system/global config' '
        (
                test_config="$HOME"/.gitconfig &&
 -              unset GIT_CONFIG_NOGLOBAL &&
 +              sane_unset GIT_CONFIG_NOGLOBAL &&
                git config -f "$test_config" core.bare false &&
                git config -f "$test_config" core.sharedRepository 0640 &&
                mkdir init-bare-shared-override &&
  test_expect_success 'init honors global core.sharedRepository' '
        (
                test_config="$HOME"/.gitconfig &&
 -              unset GIT_CONFIG_NOGLOBAL &&
 +              sane_unset GIT_CONFIG_NOGLOBAL &&
                git config -f "$test_config" core.sharedRepository 0666 &&
                mkdir shared-honor-global &&
                cd shared-honor-global &&
diff --combined trace.c
index 0fb2a2c64b63ab0067edff124b8f3d2c7175c70e,bdb5d2fa77ed06bd5ea3ef33b827a6bd11618268..02279b82c48eeb9b6e084b10dc2646eec5efbc01
+++ b/trace.c
  #include "cache.h"
  #include "quote.h"
  
 -void do_nothing(size_t unused)
 -{
 -}
 -
  /* Get a trace file descriptor from GIT_TRACE env variable. */
  static int get_trace_fd(int *need_close)
  {
@@@ -72,7 -76,7 +72,7 @@@ void trace_printf(const char *fmt, ...
        if (!fd)
                return;
  
 -      set_try_to_free_routine(do_nothing);    /* is never reset */
 +      set_try_to_free_routine(NULL);  /* is never reset */
        strbuf_init(&buf, 64);
        va_start(ap, fmt);
        len = vsnprintf(buf.buf, strbuf_avail(&buf), fmt, ap);
@@@ -104,7 -108,7 +104,7 @@@ void trace_argv_printf(const char **arg
        if (!fd)
                return;
  
 -      set_try_to_free_routine(do_nothing);    /* is never reset */
 +      set_try_to_free_routine(NULL);  /* is never reset */
        strbuf_init(&buf, 64);
        va_start(ap, fmt);
        len = vsnprintf(buf.buf, strbuf_avail(&buf), fmt, ap);
        if (need_close)
                close(fd);
  }
+ static const char *quote_crnl(const char *path)
+ {
+       static char new_path[PATH_MAX];
+       const char *p2 = path;
+       char *p1 = new_path;
+       if (!path)
+               return NULL;
+       while (*p2) {
+               switch (*p2) {
+               case '\\': *p1++ = '\\'; *p1++ = '\\'; break;
+               case '\n': *p1++ = '\\'; *p1++ = 'n'; break;
+               case '\r': *p1++ = '\\'; *p1++ = 'r'; break;
+               default:
+                       *p1++ = *p2;
+               }
+               p2++;
+       }
+       *p1 = '\0';
+       return new_path;
+ }
+ /* FIXME: move prefix to startup_info struct and get rid of this arg */
+ void trace_repo_setup(const char *prefix)
+ {
+       char cwd[PATH_MAX];
+       char *trace = getenv("GIT_TRACE");
+       if (!trace || !strcmp(trace, "") ||
+           !strcmp(trace, "0") || !strcasecmp(trace, "false"))
+               return;
+       if (!getcwd(cwd, PATH_MAX))
+               die("Unable to get current working directory");
+       trace_printf("setup: git_dir: %s\n", quote_crnl(get_git_dir()));
+       trace_printf("setup: worktree: %s\n", quote_crnl(get_git_work_tree()));
+       trace_printf("setup: cwd: %s\n", quote_crnl(cwd));
+       trace_printf("setup: prefix: %s\n", quote_crnl(prefix));
+ }