Merge branch 'tb/unicode-6.3-zero-width' into maint
authorJunio C Hamano <gitster@pobox.com>
Thu, 8 May 2014 17:00:45 +0000 (10:00 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 8 May 2014 17:00:45 +0000 (10:00 -0700)
Some more Unicode codepoints defined in Unicode 6.3 as having zero
width have been taught to our display column counting logic.

* tb/unicode-6.3-zero-width:
utf8.c: partially update to version 6.3

150 files changed:
Documentation/CodingGuidelines
Documentation/RelNotes/1.9.1.txt [new file with mode: 0644]
Documentation/RelNotes/1.9.2.txt [new file with mode: 0644]
Documentation/config.txt
Documentation/diff-generate-patch.txt
Documentation/diff-options.txt
Documentation/everyday.txt
Documentation/git-add.txt
Documentation/git-count-objects.txt
Documentation/git-diff.txt
Documentation/git-http-backend.txt
Documentation/git-prune.txt
Documentation/git-push.txt
Documentation/git-read-tree.txt
Documentation/git-reset.txt
Documentation/git-show-branch.txt
Documentation/git-show-ref.txt
Documentation/git.txt
Documentation/howto/rebase-from-internal-branch.txt
Documentation/howto/revert-a-faulty-merge.txt
Documentation/howto/revert-branch-rebase.txt
Documentation/merge-options.txt
Documentation/merge-strategies.txt
Documentation/pretty-formats.txt
Documentation/pretty-options.txt
Documentation/rev-list-options.txt
Documentation/technical/api-gitattributes.txt
Documentation/technical/pack-protocol.txt
Documentation/technical/protocol-capabilities.txt
Documentation/technical/protocol-common.txt
Documentation/user-manual.txt
GIT-VERSION-GEN
Makefile
RelNotes
builtin/add.c
builtin/apply.c
builtin/check-attr.c
builtin/checkout.c
builtin/clean.c
builtin/clone.c
builtin/commit.c
builtin/gc.c
builtin/grep.c
builtin/index-pack.c
builtin/log.c
builtin/ls-files.c
builtin/ls-tree.c
builtin/merge.c
builtin/mv.c
builtin/pack-objects.c
builtin/receive-pack.c
builtin/reset.c
builtin/rev-parse.c
builtin/rm.c
builtin/update-index.c
builtin/update-ref.c
cache.h
column.c
commit.h
compat/gmtime.c [new file with mode: 0644]
config.c
config.mak.uname
contrib/examples/git-checkout.sh
contrib/examples/git-commit.sh
contrib/examples/git-reset.sh
contrib/fast-import/import-directories.perl
contrib/svn-fe/svn-fe.txt
date.c
delta.h
diff-lib.c
diff-no-index.c
diff.c
diffcore.h
dir.c
dir.h
entry.c
fetch-pack.c
fsck.c
git-add--interactive.perl
git-am.sh
git-compat-util.h
git-difftool.perl
git-rebase--interactive.sh
git-stash.sh
gitweb/gitweb.perl
http.h
merge-recursive.c
path.c
pathspec.c
perl/Git/SVN.pm
perl/Git/SVN/Migration.pm
pkt-line.h
po/fr.po
preload-index.c
pretty.c
read-cache.c
remote.c
rerere.c
resolve-undo.c
revision.c
run-command.c
run-command.h
sha1_file.c
shallow.c
t/lib-httpd.sh
t/lib-terminal.sh
t/t0003-attributes.sh
t/t1001-read-tree-m-2way.sh
t/t1400-update-ref.sh
t/t1450-fsck.sh
t/t3030-merge-recursive.sh
t/t4005-diff-rename-2.sh
t/t4009-diff-rename-4.sh
t/t4010-diff-pathspec.sh
t/t4020-diff-external.sh
t/t4035-diff-quiet.sh
t/t4212-log-corrupt.sh
t/t5304-prune.sh
t/t5510-fetch.sh
t/t5516-fetch-push.sh
t/t5537-fetch-shallow.sh
t/t5538-push-shallow.sh
t/t5539-fetch-http-shallow.sh [new file with mode: 0755]
t/t5540-http-push-webdav.sh [new file with mode: 0755]
t/t5540-http-push.sh [deleted file]
t/t5541-http-push-smart.sh [new file with mode: 0755]
t/t5541-http-push.sh [deleted file]
t/t5550-http-fetch-dumb.sh [new file with mode: 0755]
t/t5550-http-fetch.sh [deleted file]
t/t5551-http-fetch-smart.sh [new file with mode: 0755]
t/t5551-http-fetch.sh [deleted file]
t/t5560-http-backend-noserver.sh
t/t5561-http-backend.sh
t/t6036-recursive-corner-cases.sh
t/t6131-pathspec-icase.sh
t/t7001-mv.sh
t/t7060-wtstatus.sh
t/t7102-reset.sh
t/t7104-reset.sh
t/t7300-clean.sh
t/t7505-prepare-commit-msg-hook.sh
t/t7512-status-help.sh
t/t7514-commit-patch.sh [new file with mode: 0755]
t/t7800-difftool.sh
t/t9400-git-cvsserver-server.sh
t/test-lib.sh
test-chmtime.c
upload-pack.c
wt-status.c
wt-status.h
index ef67b53f721f28e5442c00273dec5f1582f555be..b99fa87f6853775c6c021de2fab1c320e5175561 100644 (file)
@@ -91,13 +91,13 @@ For shell scripts specifically (not exhaustive):
    E.g.: my_function () {
 
  - As to use of grep, stick to a subset of BRE (namely, no \{m,n\},
-   [::], [==], nor [..]) for portability.
+   [::], [==], or [..]) for portability.
 
    - We do not use \{m,n\};
 
    - We do not use -E;
 
-   - We do not use ? nor + (which are \{0,1\} and \{1,\}
+   - We do not use ? or + (which are \{0,1\} and \{1,\}
      respectively in BRE) but that goes without saying as these
      are ERE elements not BRE (note that \? and \+ are not even part
      of BRE -- making them accessible from BRE is a GNU extension).
diff --git a/Documentation/RelNotes/1.9.1.txt b/Documentation/RelNotes/1.9.1.txt
new file mode 100644 (file)
index 0000000..5b06020
--- /dev/null
@@ -0,0 +1,59 @@
+Git v1.9.1 Release Notes
+========================
+
+Fixes since v1.9.0
+------------------
+
+ * "git clean -d pathspec" did not use the given pathspec correctly
+   and ended up cleaning too much.
+
+ * "git difftool" misbehaved when the repository is bound to the
+   working tree with the ".git file" mechanism, where a textual file
+   ".git" tells us where it is.
+
+ * "git push" did not pay attention to branch.*.pushremote if it is
+   defined earlier than remote.pushdefault; the order of these two
+   variables in the configuration file should not matter, but it did
+   by mistake.
+
+ * Codepaths that parse timestamps in commit objects have been
+   tightened.
+
+ * "git diff --external-diff" incorrectly fed the submodule directory
+   in the working tree to the external diff driver when it knew it is
+   the same as one of the versions being compared.
+
+ * "git reset" needs to refresh the index when working in a working
+   tree (it can also be used to match the index to the HEAD in an
+   otherwise bare repository), but it failed to set up the working
+   tree properly, causing GIT_WORK_TREE to be ignored.
+
+ * "git check-attr" when working on a repository with a working tree
+   did not work well when the working tree was specified via the
+   --work-tree (and obviously with --git-dir) option.
+
+ * "merge-recursive" was broken in 1.7.7 era and stopped working in
+   an empty (temporary) working tree, when there are renames
+   involved.  This has been corrected.
+
+ * "git rev-parse" was loose in rejecting command line arguments
+   that do not make sense, e.g. "--default" without the required
+   value for that option.
+
+ * include.path variable (or any variable that expects a path that
+   can use ~username expansion) in the configuration file is not a
+   boolean, but the code failed to check it.
+
+ * "git diff --quiet -- pathspec1 pathspec2" sometimes did not return
+   correct status value.
+
+ * Attempting to deepen a shallow repository by fetching over smart
+   HTTP transport failed in the protocol exchange, when no-done
+   extension was used.  The fetching side waited for the list of
+   shallow boundary commits after the sending end stopped talking to
+   it.
+
+ * Allow "git cmd path/", when the 'path' is where a submodule is
+   bound to the top-level working tree, to match 'path', despite the
+   extra and unnecessary trailing slash (such a slash is often
+   given by command line completion).
diff --git a/Documentation/RelNotes/1.9.2.txt b/Documentation/RelNotes/1.9.2.txt
new file mode 100644 (file)
index 0000000..47a34ca
--- /dev/null
@@ -0,0 +1,67 @@
+Git v1.9.2 Release Notes
+========================
+
+Fixes since v1.9.1
+------------------
+
+ * Documentation and in-code comments had many instances of mistaken
+   use of "nor", which have been corrected.
+
+ * "git fetch --prune", when the right-hand-side of multiple fetch
+   refspecs overlap (e.g. storing "refs/heads/*" to
+   "refs/remotes/origin/*", while storing "refs/frotz/*" to
+   "refs/remotes/origin/fr/*"), aggressively thought that lack of
+   "refs/heads/fr/otz" on the origin site meant we should remove
+   "refs/remotes/origin/fr/otz" from us, without checking their
+   "refs/frotz/otz" first.
+
+   Note that such a configuration is inherently unsafe (think what
+   should happen when "refs/heads/fr/otz" does appear on the origin
+   site), but that is not a reason not to be extra careful.
+
+ * "git update-ref --stdin" did not fail a request to create a ref
+   when the ref already existed.
+
+ * "git diff --no-index -Mq a b" fell into an infinite loop.
+
+ * When it is not necessary to edit a commit log message (e.g. "git
+   commit -m" is given a message without specifying "-e"), we used to
+   disable the spawning of the editor by overriding GIT_EDITOR, but
+   this means all the uses of the editor, other than to edit the
+   commit log message, are also affected.
+
+ * "git status --porcelain --branch" showed its output with labels
+   "ahead/behind/gone" translated to the user's locale.
+
+ * "git mv" that moves a submodule forgot to adjust the array that
+   uses to keep track of which submodules were to be moved to update
+   its configuration.
+
+ * Length limit for the pathname used when removing a path in a deep
+   subdirectory has been removed to avoid buffer overflows.
+
+ * The test helper lib-terminal always run an actual test_expect_*
+   when included, which screwed up with the use of skil-all that may
+   have to be done later.
+
+ * "git index-pack" used a wrong variable to name the keep-file in an
+   error message when the file cannot be written or closed.
+
+ * "rebase -i" produced a broken insn sheet when the title of a commit
+   happened to contain '\n' (or ended with '\c') due to a careless use
+   of 'echo'.
+
+ * There were a few instances of 'git-foo' remaining in the
+   documentation that should have been spelled 'git foo'.
+
+ * Serving objects from a shallow repository needs to write a
+   new file to hold the temporary shallow boundaries but it was not
+   cleaned when we exit due to die() or a signal.
+
+ * When "git stash pop" stops after failing to apply the stash
+   (e.g. due to conflicting changes), the stash is not dropped. State
+   that explicitly in the output to let the users know.
+
+ * The labels in "git status" output that describe the nature of
+   conflicts (e.g. "both deleted") were limited to 20 bytes, which was
+   too short for some l10n (e.g. fr).
index 5f4d7939ed1ec267e7f282624e5bb480e72d7a33..c26a7c8469826c2650f03e310b8aa360e44c35c6 100644 (file)
@@ -78,8 +78,8 @@ be escaped: use `\"` for `"` and `\\` for `\`.
 
 The following escape sequences (beside `\"` and `\\`) are recognized:
 `\n` for newline character (NL), `\t` for horizontal tabulation (HT, TAB)
-and `\b` for backspace (BS).  No other char escape sequence, nor octal
-char sequences are valid.
+and `\b` for backspace (BS).  Other char escape sequences (including octal
+escape sequences) are invalid.
 
 Variable values ending in a `\` are continued on the next line in the
 customary UNIX fashion.
@@ -827,7 +827,7 @@ color.diff::
        commands will only use color when output is to the terminal.
        Defaults to false.
 +
-This does not affect linkgit:git-format-patch[1] nor the
+This does not affect linkgit:git-format-patch[1] or the
 'git-diff-{asterisk}' plumbing commands.  Can be overridden on the
 command line with the `--color[=<when>]` option.
 
index 55f499a160094d3135ba2e09fc558ef186fdaef2..843a20bac2bb50916210fa8b055201bfcd1aabd9 100644 (file)
@@ -174,7 +174,7 @@ added, from the point of view of that parent).
 In the above example output, the function signature was changed
 from both files (hence two `-` removals from both file1 and
 file2, plus `++` to mean one line that was added does not appear
-in either file1 nor file2).  Also eight other lines are the same
+in either file1 or file2).  Also eight other lines are the same
 from file1 but do not appear in file2 (hence prefixed with `+`).
 
 When shown by `git diff-tree -c`, it compares the parents of a
index 9b37b2a10b94449b73aeceadae175d52ee081e4e..6cb083aae58018084c8da689bf2bfe5ccc136de5 100644 (file)
@@ -358,7 +358,7 @@ endif::git-log[]
 --irreversible-delete::
        Omit the preimage for deletes, i.e. print only the header but not
        the diff between the preimage and `/dev/null`. The resulting patch
-       is not meant to be applied with `patch` nor `git apply`; this is
+       is not meant to be applied with `patch` or `git apply`; this is
        solely for people who want to just concentrate on reviewing the
        text after the change. In addition, the output obviously lack
        enough information to apply such a patch in reverse, even manually,
index 2a18c1f6f24fbe7d78f17f662440c9b6d903e55e..b2548ef4e6758867b31a24b0a3a6c20769a3461a 100644 (file)
@@ -263,7 +263,7 @@ that are not quite ready.
 <5> create topic branch as needed and apply, again with my
 sign-offs.
 <6> rebase internal topic branch that has not been merged to the
-master, nor exposed as a part of a stable branch.
+master or exposed as a part of a stable branch.
 <7> restart `pu` every time from the next.
 <8> and bundle topic branches still cooking.
 <9> backport a critical fix.
index 48754cbc67a2cc3819fac272cdef9d9d0d76c0d7..f3ab3748bc4311b44099ad650521adcb667085de 100644 (file)
@@ -296,9 +296,9 @@ patch::
 
        y - stage this hunk
        n - do not stage this hunk
-       q - quit; do not stage this hunk nor any of the remaining ones
+       q - quit; do not stage this hunk or any of the remaining ones
        a - stage this hunk and all later hunks in the file
-       d - do not stage this hunk nor any of the later hunks in the file
+       d - do not stage this hunk or any of the later hunks in the file
        g - select a hunk to go to
        / - search for a hunk matching the given regex
        j - leave this hunk undecided, see next undecided hunk
index b300e846f13d6a7f340286b4624dc3b0da4ac740..2ff35683e5daac368f959ad6f53d22a77d0d5185 100644 (file)
@@ -33,8 +33,8 @@ size-pack: disk space consumed by the packs, in KiB (unless -H is specified)
 prune-packable: the number of loose objects that are also present in
 the packs. These objects could be pruned using `git prune-packed`.
 +
-garbage: the number of files in object database that are not valid
-loose objects nor valid packs
+garbage: the number of files in object database that are neither valid loose
+objects nor valid packs
 +
 size-garbage: disk space consumed by garbage files, in KiB (unless -H is
 specified)
index 56fb7e532227fa8a69b9e9ada92a1d8eb330c7d6..bbab35fcaff35ccd5459251550924a42ce2c871e 100644 (file)
@@ -158,8 +158,8 @@ $ git diff --name-status                <2>
 $ git diff arch/i386 include/asm-i386   <3>
 ------------
 +
-<1> Show only modification, rename and copy, but not addition
-nor deletion.
+<1> Show only modification, rename, and copy, but not addition
+or deletion.
 <2> Show only names and the nature of change, but not actual
 diff output.
 <3> Limit diff output to named subtrees.
index e8c13f60aea59c1c0575f1c0802a11fcc35ecb3c..d422ba4b59acf31151f149c8067c18e541e5bdb2 100644 (file)
@@ -191,7 +191,7 @@ ScriptAlias /git/ /var/www/cgi-bin/gitweb.cgi/
 ----------------------------------------------------------------
 
 Lighttpd::
-       Ensure that `mod_cgi`, `mod_alias, `mod_auth`, `mod_setenv` are
+       Ensure that `mod_cgi`, `mod_alias`, `mod_auth`, `mod_setenv` are
        loaded, then set `GIT_PROJECT_ROOT` appropriately and redirect
        all requests to the CGI:
 +
index 058ac0dc854bfd55a13dd0776beaf36b37e8b8a9..7a493c80f776092265abd4fb2575639e683bcf5c 100644 (file)
@@ -56,7 +56,7 @@ OPTIONS
 EXAMPLE
 -------
 
-To prune objects not used by your repository nor another that
+To prune objects not used by your repository or another that
 borrows from your repository via its
 `.git/objects/info/alternates`:
 
index 2b7f4f939f38626dbd796b808cc21285ad5c8c3d..d0b9e2f235e5ec8e71f7d9b03f684db96fa50f30 100644 (file)
@@ -385,7 +385,7 @@ will now start building on top of B.
 The command by default does not allow an update that is not a fast-forward
 to prevent such loss of history.
 
-If you do not want to lose your work (history from X to B) nor the work by
+If you do not want to lose your work (history from X to B) or the work by
 the other person (history from X to A), you would need to first fetch the
 history from the repository, create a history that contains changes done
 by both parties, and push the result back.
index c4bde6509e5a2f652dca9345a3a28e9e674c216a..056c0dba81292ae63fedf2d911bce8f5fa3f7d19 100644 (file)
@@ -57,7 +57,7 @@ OPTIONS
 -n::
 --dry-run::
        Check if the command would error out, without updating the index
-       nor the files in the working tree for real.
+       or the files in the working tree for real.
 
 -v::
        Show the progress of checking files out.
index f445cb38fa26a6daa62b5be7f65122948ca669ab..24bf4d55f97b44876e72db355dba301f93c9005c 100644 (file)
@@ -21,7 +21,7 @@ to HEAD in all forms.
 
 'git reset' [-q] [<tree-ish>] [--] <paths>...::
        This form resets the index entries for all <paths> to their
-       state at <tree-ish>.  (It does not affect the working tree, nor
+       state at <tree-ish>.  (It does not affect the working tree or
        the current branch.)
 +
 This means that `git reset <paths>` is the opposite of `git add
@@ -51,7 +51,7 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode.
 +
 --
 --soft::
-       Does not touch the index file nor the working tree at all (but
+       Does not touch the index file or the working tree at all (but
        resets the head to <commit>, just like all modes do). This leaves
        all your changed files "Changes to be committed", as 'git status'
        would put it.
@@ -115,7 +115,7 @@ and changes with these files are distracting.
 <2> Somebody asks you to pull, and the changes sounds worthy of merging.
 <3> However, you already dirtied the index (i.e. your index does
 not match the HEAD commit).  But you know the pull you are going
-to make does not affect frotz.c nor filfre.c, so you revert the
+to make does not affect frotz.c or filfre.c, so you revert the
 index changes for these two files.  Your changes in working tree
 remain there.
 <4> Then you can pull and merge, leaving frotz.c and filfre.c
index a515648ab018b849897dd3506183f57359be598a..b91d4e545b07e21931ac44a04cffea8824c8c7a2 100644 (file)
@@ -25,7 +25,7 @@ and/or refs/tags) semi-visually.
 It cannot show more than 29 branches and commits at a time.
 
 It uses `showbranch.default` multi-valued configuration items if
-no <rev> nor <glob> is given on the command line.
+no <rev> or <glob> is given on the command line.
 
 
 OPTIONS
index ffd1b03a9c0ee583effe6200fbabd327e7ac60f6..2a6f89b235f10ea6d41047a2a42a133531ea3cab 100644 (file)
@@ -89,7 +89,7 @@ OPTIONS
        Show references matching one or more patterns. Patterns are matched from
        the end of the full name, and only complete parts are matched, e.g.
        'master' matches 'refs/heads/master', 'refs/remotes/origin/master',
-       'refs/tags/jedi/master' but not 'refs/heads/mymaster' nor
+       'refs/tags/jedi/master' but not 'refs/heads/mymaster' or
        'refs/remotes/master/jedi'.
 
 OUTPUT
index 02bbc084b8d72b33af08a6fee7d8f1943e870e24..f5b511ddbb2478d3a479d12c3a2f6cb21e5e83f7 100644 (file)
@@ -43,9 +43,11 @@ unreleased) version of Git, that is available from 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v1.9.0/git.html[documentation for release 1.9.0]
+* link:v1.9.2/git.html[documentation for release 1.9.2]
 
 * release notes for
+  link:RelNotes/1.9.2.txt[1.9.2],
+  link:RelNotes/1.9.1.txt[1.9.1],
   link:RelNotes/1.9.0.txt[1.9.0].
 
 * link:v1.8.5.5/git.html[documentation for release 1.8.5.5]
index 19ab604f1f859fa3a40e8bd0da2675548056a2c5..02cb5f758d6f65c61e216c89fa758f7345526f96 100644 (file)
@@ -139,7 +139,7 @@ You fetch from upstream, but not merge.
     $ git fetch upstream
 
 This leaves the updated upstream head in .git/FETCH_HEAD but
-does not touch your .git/HEAD nor .git/refs/heads/master.
+does not touch your .git/HEAD or .git/refs/heads/master.
 You run "git rebase" now.
 
     $ git rebase FETCH_HEAD master
index acf3e477e59f1bab9addde756274afe15d39a8ed..462255ed5d8053cbb4dadeec224cb81d14c4ada6 100644 (file)
@@ -54,7 +54,7 @@ where C and D are to fix what was broken in A and B, and you may already
 have some other changes on the mainline after W.
 
 If you merge the updated side branch (with D at its tip), none of the
-changes made in A nor B will be in the result, because they were reverted
+changes made in A or B will be in the result, because they were reverted
 by W.  That is what Alan saw.
 
 Linus explains the situation:
@@ -90,7 +90,7 @@ with:
     $ git revert W
 
 This history would (ignoring possible conflicts between what W and W..Y
-changed) be equivalent to not having W nor Y at all in the history:
+changed) be equivalent to not having W or Y at all in the history:
 
  ---o---o---o---M---x---x-------x----
               /
index 85f69dbac9187ff504d4656cfab5efe074223161..149508e13bdacf70488b1a7049bf6aef502c36e3 100644 (file)
@@ -137,7 +137,7 @@ $ make clean test ;# make sure it did not cause other breakage.
 ------------------------------------------------
 
 Everything is in the good order.  I do not need the temporary branch
-nor tag anymore, so remove them:
+or tag anymore, so remove them:
 
 ------------------------------------------------
 $ rm -f .git/refs/tags/pu-anchor
index e1343155fad7b2709d2f3700ea3d5b4c4d1a7a89..f08e9b80c562faa1de2408cd4cfdb7253d3be1f2 100644 (file)
@@ -63,14 +63,13 @@ merge.
 
 --squash::
 --no-squash::
-       Produce the working tree and index state as if a real
-       merge happened (except for the merge information),
-       but do not actually make a commit or
-       move the `HEAD`, nor record `$GIT_DIR/MERGE_HEAD` to
-       cause the next `git commit` command to create a merge
-       commit.  This allows you to create a single commit on
-       top of the current branch whose effect is the same as
-       merging another branch (or more in case of an octopus).
+       Produce the working tree and index state as if a real merge
+       happened (except for the merge information), but do not actually
+       make a commit, move the `HEAD`, or record `$GIT_DIR/MERGE_HEAD`
+       (to cause the next `git commit` command to create a merge
+       commit).  This allows you to create a single commit on top of
+       the current branch whose effect is the same as merging another
+       branch (or more in case of an octopus).
 +
 With --no-squash perform the merge and commit the result. This
 option can be used to override --squash.
index fb6e593e7c6f287612f30be6206c0492d77e38d3..feabc1ccf41507eca9e836cb0c825068c35b644e 100644 (file)
@@ -1,10 +1,10 @@
 MERGE STRATEGIES
 ----------------
 
-The merge mechanism ('git-merge' and 'git-pull' commands) allows the
+The merge mechanism (`git merge` and `git pull` commands) allows the
 backend 'merge strategies' to be chosen with `-s` option.  Some strategies
 can also take their own options, which can be passed by giving `-X<option>`
-arguments to 'git-merge' and/or 'git-pull'.
+arguments to `git merge` and/or `git pull`.
 
 resolve::
        This can only resolve two heads (i.e. the current branch
index 1d174fd0b6fa7f9fae3eb1523c8c6e2192e71e45..85d63532a3e165110717ca2602e9dd806f10bd9f 100644 (file)
@@ -78,7 +78,7 @@ The 'raw' format shows the entire commit exactly as
 stored in the commit object.  Notably, the SHA-1s are
 displayed in full, regardless of whether --abbrev or
 --no-abbrev are used, and 'parents' information show the
-true parent commits, without taking grafts nor history
+true parent commits, without taking grafts or history
 simplification into account.
 
 * 'format:<string>'
index eea0e306a83834e75f44c1b932e5a7747195f85c..8569e29d08784cb5eb053af919e4b7514b1c296b 100644 (file)
@@ -39,7 +39,7 @@ people using 80-column terminals.
        Show the notes (see linkgit:git-notes[1]) that annotate the
        commit, when showing the commit log message.  This is the default
        for `git log`, `git show` and `git whatchanged` commands when
-       there is no `--pretty`, `--format` nor `--oneline` option given
+       there is no `--pretty`, `--format`or `--oneline` option given
        on the command line.
 +
 By default, the notes shown are from the notes refs listed in the
index 03533af7152e8b137cd3d885de3ec273b91d4791..47c8dcca9d16031ff531118ebf4b8b6fe575e7ce 100644 (file)
@@ -237,7 +237,7 @@ list.
        reflog entries from the most recent one to older ones.
        When this option is used you cannot specify commits to
        exclude (that is, '{caret}commit', 'commit1..commit2',
-       nor 'commit1\...commit2' notations cannot be used).
+       and 'commit1\...commit2' notations cannot be used).
 +
 With `--pretty` format other than `oneline` (for obvious reasons),
 this causes the output to have two extra lines of information
index ce363b6305ec117810d66308b0066814871f54e1..260266867768a549e58e540eaa95d3bbe422e5c0 100644 (file)
@@ -99,7 +99,7 @@ static void setup_check(void)
                The attribute is Unset, by listing the name of the
                attribute prefixed with a dash - for the path.
        } else if (ATTR_UNSET(value)) {
-               The attribute is not set nor unset for the path.
+               The attribute is neither set nor unset for the path.
        } else if (!strcmp(value, "input")) {
                If none of ATTR_TRUE(), ATTR_FALSE(), or ATTR_UNSET() is
                true, the value is a string set in the gitattributes
index c73b62f5e1ced76d783dcd5e7aef64016ca1fb4c..18dea8d15fa159b719a38588a0a346e58120ac61 100644 (file)
@@ -237,10 +237,10 @@ The client now sends the maximum commit history depth it wants for
 this transaction, which is the number of commits it wants from the
 tip of the history, if any, as a 'deepen' line.  A depth of 0 is the
 same as not making a depth request. The client does not want to receive
-any commits beyond this depth, nor objects needed only to complete
-those commits. Commits whose parents are not received as a result are
-defined as shallow and marked as such in the server. This information
-is sent back to the client in the next step.
+any commits beyond this depth, nor does it want objects needed only to
+complete those commits. Commits whose parents are not received as a
+result are defined as shallow and marked as such in the server. This
+information is sent back to the client in the next step.
 
 Once all the 'want's and 'shallow's (and optional 'deepen') are
 transferred, clients MUST send a flush-pkt, to tell the server side
@@ -338,7 +338,8 @@ during a prior round.  This helps to ensure that at least one common
 ancestor is found before we give up entirely.
 
 Once the 'done' line is read from the client, the server will either
-send a final 'ACK obj-id' or it will send a 'NAK'. The server only sends
+send a final 'ACK obj-id' or it will send a 'NAK'. 'obj-id' is the object
+name of the last commit determined to be common. The server only sends
 ACK after 'done' if there is at least one common base and multi_ack or
 multi_ack_detailed is enabled. The server always sends NAK after 'done'
 if there is no common base found.
index e3e792476e7a6b7554582469b2c5ac172b2f17dd..e17434384724662aabb60d7fceed40a433207608 100644 (file)
@@ -69,6 +69,24 @@ ends.
 Without multi_ack the client would have sent that c-b-a chain anyway,
 interleaved with S-R-Q.
 
+multi_ack_detailed
+------------------
+This is an extension of multi_ack that permits client to better
+understand the server's in-memory state. See pack-protocol.txt,
+section "Packfile Negotiation" for more information.
+
+no-done
+-------
+This capability should only be used with the smart HTTP protocol. If
+multi_ack_detailed and no-done are both present, then the sender is
+free to immediately send a pack following its first "ACK obj-id ready"
+message.
+
+Without no-done in the smart HTTP protocol, the server session would
+end and the client has to make another trip to send "done" before
+the server can send the pack. no-done removes the last round and
+thus slightly reduces latency.
+
 thin-pack
 ---------
 
index fb7ff084f8e55a06b349db6f7e47c3f64a886a0e..889985f7076da80f94c02b4a7e2760633d500980 100644 (file)
@@ -39,7 +39,7 @@ More specifically, they:
   caret `^`, colon `:`, question-mark `?`, asterisk `*`,
   or open bracket `[` anywhere.
 
-. They cannot end with a slash `/` nor a dot `.`.
+. They cannot end with a slash `/` or a dot `.`.
 
 . They cannot end with the sequence `.lock`.
 
index d4f980446250befbd788394598de599824630d2f..022e74e616400664e7cf59ace487c8b53d6f5cab 100644 (file)
@@ -4074,7 +4074,7 @@ the `HEAD` tree, and stage 3 to the `$target` tree.
 
 Earlier we said that trivial merges are done inside
 `git read-tree -m`.  For example, if the file did not change
-from `$orig` to `HEAD` nor `$target`, or if the file changed
+from `$orig` to `HEAD` or `$target`, or if the file changed
 from `$orig` to `HEAD` and `$orig` to `$target` the same way,
 obviously the final outcome is what is in `HEAD`.  What the
 above example shows is that file `hello.c` was changed from
index 2b97352dd3b113b46bbd53248315ab91f0a9356b..5d2bf82085bdc77a300ac75b0953bb0202f3060e 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.9.0
+DEF_VER=v1.9.2
 
 LF='
 '
index dddaf4f287cf5cd5e99ad2587d53ba7582c51e29..33aa15b0e34622a4af09c089f37d47223627f507 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -159,7 +159,7 @@ all::
 #
 # 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_INTPTR_T if you don't have intptr_t or uintptr_t.
 #
 # Define NO_UINTMAX_T if you don't have uintmax_t.
 #
@@ -342,6 +342,9 @@ all::
 # 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.
+#
+# Define GMTIME_UNRELIABLE_ERRORS if your gmtime() function does not
+# return NULL when it receives a bogus time_t.
 
 GIT-VERSION-FILE: FORCE
        @$(SHELL_PATH) ./GIT-VERSION-GEN
@@ -1494,6 +1497,11 @@ ifneq (,$(XDL_FAST_HASH))
        BASIC_CFLAGS += -DXDL_FAST_HASH
 endif
 
+ifdef GMTIME_UNRELIABLE_ERRORS
+       COMPAT_OBJS += compat/gmtime.o
+       BASIC_CFLAGS += -DGMTIME_UNRELIABLE_ERRORS
+endif
+
 ifeq ($(TCLTK_PATH),)
 NO_TCLTK = NoThanks
 endif
index bb52cf9476df53ddb9788f16082e2e92e76a4db5..58c32c35250bcdeb46b0d6340ec3d246a5e6298c 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/1.9.0.txt
\ No newline at end of file
+Documentation/RelNotes/1.9.2.txt
\ No newline at end of file
index 2a2722fa10aa981695b21984e7c425c35b4f18d0..672adc01ffc07fa97c305f9110cfa3995658b922 100644 (file)
@@ -208,8 +208,7 @@ static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec,
        i = dir->nr;
        while (--i >= 0) {
                struct dir_entry *entry = *src++;
-               if (match_pathspec_depth(pathspec, entry->name, entry->len,
-                                        prefix, seen))
+               if (dir_path_match(entry, pathspec, prefix, seen))
                        *dst++ = entry;
                else if (flag & WARN_IMPLICIT_DOT)
                        /*
index b0d0986226ccb7fa06b08bacba6269b8834e8dd6..6013e1913c05a57ed935a17504ebe079f46cc8ad 100644 (file)
@@ -4061,7 +4061,7 @@ static int write_out_one_reject(struct patch *patch)
                return error(_("cannot open %s: %s"), namebuf, strerror(errno));
 
        /* Normal git tools never deal with .rej, so do not pretend
-        * this is a git patch by saying --git nor give extended
+        * this is a git patch by saying --git or giving extended
         * headers.  While at it, maybe please "kompare" that wants
         * the trailing TAB and some garbage at the end of line ;-).
         */
index e9af7b2bfb932d75cdface880be9814885068a50..5600ec3f6165ae04682f30481142452438f856af 100644 (file)
@@ -102,6 +102,9 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
        struct git_attr_check *check;
        int cnt, i, doubledash, filei;
 
+       if (!is_bare_repository())
+               setup_work_tree();
+
        git_config(git_default_config, NULL);
 
        argc = parse_options(argc, argv, prefix, check_attr_options,
index 5df3837e3102e2f7d432ec11bb4685535bfaa0ac..63151e08a4d1b4180e797fd33e23a9bf75c2f79e 100644 (file)
@@ -53,10 +53,10 @@ struct checkout_opts {
 static int post_checkout_hook(struct commit *old, struct commit *new,
                              int changed)
 {
-       return run_hook(NULL, "post-checkout",
-                       sha1_to_hex(old ? old->object.sha1 : null_sha1),
-                       sha1_to_hex(new ? new->object.sha1 : null_sha1),
-                       changed ? "1" : "0", NULL);
+       return run_hook_le(NULL, "post-checkout",
+                          sha1_to_hex(old ? old->object.sha1 : null_sha1),
+                          sha1_to_hex(new ? new->object.sha1 : null_sha1),
+                          changed ? "1" : "0", NULL);
        /* "new" can be NULL when checking out from the index before
           a commit exists. */
 
@@ -297,8 +297,7 @@ static int checkout_paths(const struct checkout_opts *opts,
                 * match_pathspec() for _all_ entries when
                 * opts->source_tree != NULL.
                 */
-               if (match_pathspec_depth(&opts->pathspec, ce->name, ce_namelen(ce),
-                                  0, ps_matched))
+               if (ce_path_match(ce, &opts->pathspec, ps_matched))
                        ce->ce_flags |= CE_MATCHED;
        }
 
@@ -896,7 +895,7 @@ static int parse_branchname_arg(int argc, const char **argv,
         *       between A and B, A...B names that merge base.
         *
         *   (b) If <something> is _not_ a commit, either "--" is present
-        *       or <something> is not a path, no -t nor -b was given, and
+        *       or <something> is not a path, no -t or -b was given, and
         *       and there is a tracking branch whose name is <something>
         *       in one and only one remote, then this is a short-hand to
         *       fork local <something> from that remote-tracking branch.
index 2f26297142fde89ec842d4e01665b3ebb24a9b59..977a068f110a5ecfaeb3b680325f11a86be52251 100644 (file)
@@ -903,11 +903,11 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 
        if (!interactive && !dry_run && !force) {
                if (config_set)
-                       die(_("clean.requireForce set to true and neither -i, -n nor -f given; "
+                       die(_("clean.requireForce set to true and neither -i, -n, nor -f given; "
                                  "refusing to clean"));
                else
-                       die(_("clean.requireForce defaults to true and neither -i, -n nor -f given; "
-                                 "refusing to clean"));
+                       die(_("clean.requireForce defaults to true and neither -i, -n, nor -f given;"
+                                 " refusing to clean"));
        }
 
        if (force > 1)
@@ -933,48 +933,28 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 
        for (i = 0; i < dir.nr; i++) {
                struct dir_entry *ent = dir.entries[i];
-               int len, pos;
                int matches = 0;
-               const struct cache_entry *ce;
                struct stat st;
                const char *rel;
 
-               /*
-                * Remove the '/' at the end that directory
-                * walking adds for directory entries.
-                */
-               len = ent->len;
-               if (len && ent->name[len-1] == '/')
-                       len--;
-               pos = cache_name_pos(ent->name, len);
-               if (0 <= pos)
-                       continue;       /* exact match */
-               pos = -pos - 1;
-               if (pos < active_nr) {
-                       ce = active_cache[pos];
-                       if (ce_namelen(ce) == len &&
-                           !memcmp(ce->name, ent->name, len))
-                               continue; /* Yup, this one exists unmerged */
-               }
+               if (!cache_name_is_other(ent->name, ent->len))
+                       continue;
 
                if (lstat(ent->name, &st))
                        die_errno("Cannot lstat '%s'", ent->name);
 
                if (pathspec.nr)
-                       matches = match_pathspec_depth(&pathspec, ent->name,
-                                                      len, 0, NULL);
+                       matches = dir_path_match(ent, &pathspec, 0, NULL);
 
-               if (S_ISDIR(st.st_mode)) {
-                       if (remove_directories || (matches == MATCHED_EXACTLY)) {
-                               rel = relative_path(ent->name, prefix, &buf);
-                               string_list_append(&del_list, rel);
-                       }
-               } else {
-                       if (pathspec.nr && !matches)
-                               continue;
-                       rel = relative_path(ent->name, prefix, &buf);
-                       string_list_append(&del_list, rel);
-               }
+               if (pathspec.nr && !matches)
+                       continue;
+
+               if (S_ISDIR(st.st_mode) && !remove_directories &&
+                   matches != MATCHED_EXACTLY)
+                       continue;
+
+               rel = relative_path(ent->name, prefix, &buf);
+               string_list_append(&del_list, rel);
        }
 
        if (interactive && del_list.nr > 0)
index 43e772ccdbaba3172f7ee1a969f92b300cb9d5a1..9b3c04d914b3d318f723c2d3ded403fca9503c07 100644 (file)
@@ -660,8 +660,8 @@ static int checkout(void)
            commit_locked_index(lock_file))
                die(_("unable to write new index file"));
 
-       err |= run_hook(NULL, "post-checkout", sha1_to_hex(null_sha1),
-                       sha1_to_hex(sha1), "1", NULL);
+       err |= run_hook_le(NULL, "post-checkout", sha1_to_hex(null_sha1),
+                          sha1_to_hex(sha1), "1", NULL);
 
        if (!err && option_recursive)
                err = run_command_v_opt(argv_submodule, RUN_GIT_CMD);
index 3767478c6ddb02cf8a4a418f8911102aeaacfbe8..7d711eafa698d933291beaa00b485397c7efb256 100644 (file)
@@ -234,7 +234,7 @@ static int list_paths(struct string_list *list, const char *with_tree,
 
                if (ce->ce_flags & CE_UPDATE)
                        continue;
-               if (!match_pathspec_depth(pattern, ce->name, ce_namelen(ce), 0, m))
+               if (!ce_path_match(ce, pattern, m))
                        continue;
                item = string_list_insert(list, ce->name);
                if (ce_skip_worktree(ce))
@@ -612,7 +612,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
        /* This checks and barfs if author is badly specified */
        determine_author_info(author_ident);
 
-       if (!no_verify && run_hook(index_file, "pre-commit", NULL))
+       if (!no_verify && run_commit_hook(use_editor, index_file, "pre-commit", NULL))
                return 0;
 
        if (squash_message) {
@@ -866,8 +866,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
                return 0;
        }
 
-       if (run_hook(index_file, "prepare-commit-msg",
-                    git_path(commit_editmsg), hook_arg1, hook_arg2, NULL))
+       if (run_commit_hook(use_editor, index_file, "prepare-commit-msg",
+                           git_path(commit_editmsg), hook_arg1, hook_arg2, NULL))
                return 0;
 
        if (use_editor) {
@@ -883,7 +883,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
        }
 
        if (!no_verify &&
-           run_hook(index_file, "commit-msg", git_path(commit_editmsg), NULL)) {
+           run_commit_hook(use_editor, index_file, "commit-msg", git_path(commit_editmsg), NULL)) {
                return 0;
        }
 
@@ -1067,8 +1067,6 @@ static int parse_and_validate_options(int argc, const char *argv[],
                use_editor = 0;
        if (0 <= edit_flag)
                use_editor = edit_flag;
-       if (!use_editor)
-               setenv("GIT_EDITOR", ":", 1);
 
        /* Sanity check options */
        if (amend && !current_head)
@@ -1123,7 +1121,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
        if (argc == 0 && only && amend)
                only_include_assumed = _("Clever... amending the last one with dirty index.");
        if (argc > 0 && !also && !only)
-               only_include_assumed = _("Explicit paths specified without -i nor -o; assuming --only paths...");
+               only_include_assumed = _("Explicit paths specified without -i or -o; assuming --only paths...");
        if (!cleanup_arg || !strcmp(cleanup_arg, "default"))
                cleanup_mode = use_editor ? CLEANUP_ALL : CLEANUP_SPACE;
        else if (!strcmp(cleanup_arg, "verbatim"))
@@ -1445,6 +1443,29 @@ static int run_rewrite_hook(const unsigned char *oldsha1,
        return finish_command(&proc);
 }
 
+int run_commit_hook(int editor_is_used, const char *index_file, const char *name, ...)
+{
+       const char *hook_env[3] =  { NULL };
+       char index[PATH_MAX];
+       va_list args;
+       int ret;
+
+       snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
+       hook_env[0] = index;
+
+       /*
+        * Let the hook know that no editor will be launched.
+        */
+       if (!editor_is_used)
+               hook_env[1] = "GIT_EDITOR=:";
+
+       va_start(args, name);
+       ret = run_hook_ve(hook_env, name, args);
+       va_end(args);
+
+       return ret;
+}
+
 int cmd_commit(int argc, const char **argv, const char *prefix)
 {
        static struct wt_status s;
@@ -1669,7 +1690,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                     "not exceeded, and then \"git reset HEAD\" to recover."));
 
        rerere(0);
-       run_hook(get_index_file(), "post-commit", NULL);
+       run_commit_hook(use_editor, get_index_file(), "post-commit", NULL);
        if (amend && !no_post_rewrite) {
                struct notes_rewrite_cfg *cfg;
                cfg = init_copy_notes_for_rewrite("amend");
index c19545d49e217400ee1736183c870557b9c9d54b..7fa717a3b6ab08bb5b4d5549eeb96f07460f95e6 100644 (file)
@@ -179,7 +179,7 @@ static int need_to_gc(void)
        else if (!too_many_loose_objects())
                return 0;
 
-       if (run_hook(NULL, "pre-auto-gc", NULL))
+       if (run_hook_le(NULL, "pre-auto-gc", NULL))
                return 0;
        return 1;
 }
index 63f86032d91f00fc607f7d3b26ec941bb7a4c76c..69ac2d8797ec32dc206425db0a2f3d7356810cfe 100644 (file)
@@ -379,7 +379,7 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int
                const struct cache_entry *ce = active_cache[nr];
                if (!S_ISREG(ce->ce_mode))
                        continue;
-               if (!match_pathspec_depth(pathspec, ce->name, ce_namelen(ce), 0, NULL))
+               if (!ce_path_match(ce, pathspec, NULL))
                        continue;
                /*
                 * If CE_VALID is on, we assume worktree file and its cache entry
@@ -524,9 +524,7 @@ static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec,
 
        fill_directory(&dir, pathspec);
        for (i = 0; i < dir.nr; i++) {
-               const char *name = dir.entries[i]->name;
-               int namelen = strlen(name);
-               if (!match_pathspec_depth(pathspec, name, namelen, 0, NULL))
+               if (!dir_path_match(dir.entries[i], pathspec, 0, NULL))
                        continue;
                hit |= grep_file(opt, dir.entries[i]->name);
                if (hit && opt->status_only)
index 2f37a38fbcdf131ab5897e47728c5773ba36b861..fa74972886cc8e6c0f6308e28de26a13cae6a2b7 100644 (file)
@@ -1291,7 +1291,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
                if (keep_fd < 0) {
                        if (errno != EEXIST)
                                die_errno(_("cannot write keep file '%s'"),
-                                         keep_name);
+                                         keep_name ? keep_name : name);
                } else {
                        if (keep_msg_len > 0) {
                                write_or_die(keep_fd, keep_msg, keep_msg_len);
@@ -1299,7 +1299,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
                        }
                        if (close(keep_fd) != 0)
                                die_errno(_("cannot close written keep file '%s'"),
-                                   keep_name);
+                                         keep_name ? keep_name : name);
                        report = "keep";
                }
        }
index b97373da3b2687e18b5eba96382049382d1536fd..39e883635279ad21f3ddd7b224f484b9b04700b0 100644 (file)
@@ -503,7 +503,7 @@ static void show_rev_tweak_rev(struct rev_info *rev, struct setup_revision_opt *
                /* There was no "-m" on the command line */
                rev->ignore_merges = 0;
                if (!rev->first_parent_only && !rev->combine_merges) {
-                       /* No "--first-parent", "-c", nor "--cc" */
+                       /* No "--first-parent", "-c", or "--cc" */
                        rev->combine_merges = 1;
                        rev->dense_combined_merges = 1;
                }
index e1cf6d8547d4aa7f548fb80f0efb8f4e7b1d9c8e..47c38808a26a4602f8bd2c7d87f67770a625c679 100644 (file)
@@ -64,7 +64,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
        if (len >= ent->len)
                die("git ls-files: internal error - directory entry not superset of prefix");
 
-       if (!match_pathspec_depth(&pathspec, ent->name, ent->len, len, ps_matched))
+       if (!dir_path_match(ent, &pathspec, len, ps_matched))
                return;
 
        fputs(tag, stdout);
@@ -139,7 +139,9 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce)
        if (len >= ce_namelen(ce))
                die("git ls-files: internal error - cache entry not superset of prefix");
 
-       if (!match_pathspec_depth(&pathspec, ce->name, ce_namelen(ce), len, ps_matched))
+       if (!match_pathspec(&pathspec, ce->name, ce_namelen(ce),
+                           len, ps_matched,
+                           S_ISDIR(ce->ce_mode) || S_ISGITLINK(ce->ce_mode)))
                return;
 
        if (tag && *tag && show_valid_bit &&
@@ -195,7 +197,8 @@ static void show_ru_info(void)
                len = strlen(path);
                if (len < max_prefix_len)
                        continue; /* outside of the prefix */
-               if (!match_pathspec_depth(&pathspec, path, len, max_prefix_len, ps_matched))
+               if (!match_pathspec(&pathspec, path, len,
+                                   max_prefix_len, ps_matched, 0))
                        continue; /* uninterested */
                for (i = 0; i < 3; i++) {
                        if (!ui->mode[i])
index 65ec93184614619cac925c17ef3ebc90cd30a82c..51184dfa2efa46323e79c4504121bf5fe948a6d2 100644 (file)
@@ -171,7 +171,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
         * show_recursive() rolls its own matching code and is
         * generally ignorant of 'struct pathspec'. The magic mask
         * cannot be lifted until it is converted to use
-        * match_pathspec_depth() or tree_entry_interesting()
+        * match_pathspec() or tree_entry_interesting()
         */
        parse_pathspec(&pathspec, PATHSPEC_GLOB | PATHSPEC_ICASE,
                       PATHSPEC_PREFER_CWD,
index e576a7fdc619303a65e859920a1ab6936db2626c..b11a528ce5580d5e5b9b61f291e0d829a735ae6a 100644 (file)
@@ -421,7 +421,7 @@ static void finish(struct commit *head_commit,
        }
 
        /* Run a post-merge hook */
-       run_hook(NULL, "post-merge", squash ? "1" : "0", NULL);
+       run_hook_le(NULL, "post-merge", squash ? "1" : "0", NULL);
 
        strbuf_release(&reflog_message);
 }
@@ -821,8 +821,8 @@ static void prepare_to_commit(struct commit_list *remoteheads)
        if (0 < option_edit)
                strbuf_commented_addf(&msg, _(merge_editor_comment), comment_line_char);
        write_merge_msg(&msg);
-       if (run_hook(get_index_file(), "prepare-commit-msg",
-                    git_path("MERGE_MSG"), "merge", NULL, NULL))
+       if (run_commit_hook(0 < option_edit, get_index_file(), "prepare-commit-msg",
+                           git_path("MERGE_MSG"), "merge", NULL))
                abort_commit(remoteheads, NULL);
        if (0 < option_edit) {
                if (launch_editor(git_path("MERGE_MSG"), NULL, NULL))
index 21c46d1636e6e87dd9eaaca60ac08ebbbc4efec3..45e57f307b799490a949d60b37f8cff1a1e5d07f 100644 (file)
@@ -179,6 +179,9 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
                                                modes = xrealloc(modes,
                                                                (argc + last - first)
                                                                * sizeof(enum update_mode));
+                                               submodule_gitfile = xrealloc(submodule_gitfile,
+                                                               (argc + last - first)
+                                                               * sizeof(char *));
                                        }
 
                                        dst = add_slash(dst);
@@ -192,6 +195,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
                                                        prefix_path(dst, dst_len,
                                                                path + length + 1);
                                                modes[argc + j] = INDEX;
+                                               submodule_gitfile[argc + j] = NULL;
                                        }
                                        argc += last - first;
                                }
@@ -227,6 +231,11 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
                                        memmove(destination + i,
                                                destination + i + 1,
                                                (argc - i) * sizeof(char *));
+                                       memmove(modes + i, modes + i + 1,
+                                               (argc - i) * sizeof(enum update_mode));
+                                       memmove(submodule_gitfile + i,
+                                               submodule_gitfile + i + 1,
+                                               (argc - i) * sizeof(char *));
                                        i--;
                                }
                        } else
index 541667f1026d7ba62be8e029c31138d5661f65c7..ef1f20ea94ff9567d23f7cef5203020d9365d5bd 100644 (file)
@@ -999,7 +999,7 @@ static int pbase_tree_cache_ix_incr(int ix)
 static struct pbase_tree {
        struct pbase_tree *next;
        /* This is a phony "cache" entry; we are not
-        * going to evict it nor find it through _get()
+        * going to evict it or find it through _get()
         * mechanism -- this is for the toplevel node that
         * would almost always change with any commit.
         */
index 85bba356fab7743506f00bb0c5ca955eb9112bd5..c3230817db4a7676eb74335b254f30597e66edd9 100644 (file)
@@ -828,14 +828,10 @@ static void execute_commands(struct command *commands,
                }
        }
 
-       if (shallow_update) {
-               if (!checked_connectivity)
-                       error("BUG: run 'git fsck' for safety.\n"
-                             "If there are errors, try to remove "
-                             "the reported refs above");
-               if (alt_shallow_file && *alt_shallow_file)
-                       unlink(alt_shallow_file);
-       }
+       if (shallow_update && !checked_connectivity)
+               error("BUG: run 'git fsck' for safety.\n"
+                     "If there are errors, try to remove "
+                     "the reported refs above");
 }
 
 static struct command *read_head_info(struct sha1_array *shallow)
@@ -1087,10 +1083,6 @@ static void update_shallow_info(struct command *commands,
                        cmd->skip_update = 1;
                }
        }
-       if (alt_shallow_file && *alt_shallow_file) {
-               unlink(alt_shallow_file);
-               alt_shallow_file = NULL;
-       }
        free(ref_status);
 }
 
index 60048030dd4d05e9938f298002d02afc31528bf1..a9913443580846b7c401c8c4517890ad91fe8ded 100644 (file)
@@ -320,7 +320,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
        if (reset_type == NONE)
                reset_type = MIXED; /* by default */
 
-       if (reset_type != SOFT && reset_type != MIXED)
+       if (reset_type != SOFT && (reset_type != MIXED || get_git_work_tree()))
                setup_work_tree();
 
        if (reset_type == MIXED && is_bare_repository())
@@ -340,8 +340,9 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
                        int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
                        if (read_from_tree(&pathspec, sha1))
                                return 1;
-                       refresh_index(&the_index, flags, NULL, NULL,
-                                     _("Unstaged changes after reset:"));
+                       if (get_git_work_tree())
+                               refresh_index(&the_index, flags, NULL, NULL,
+                                             _("Unstaged changes after reset:"));
                } else {
                        int err = reset_index(sha1, reset_type, quiet);
                        if (reset_type == KEEP && !err)
index aaeb611a9729938251b1c679e35c446bb737ff4f..45901df37103f37418d7558adb8ace36c8b56aeb 100644 (file)
@@ -547,15 +547,17 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                                continue;
                        }
                        if (!strcmp(arg, "--default")) {
-                               def = argv[i+1];
-                               i++;
+                               def = argv[++i];
+                               if (!def)
+                                       die("--default requires an argument");
                                continue;
                        }
                        if (!strcmp(arg, "--prefix")) {
-                               prefix = argv[i+1];
+                               prefix = argv[++i];
+                               if (!prefix)
+                                       die("--prefix requires an argument");
                                startup_info->prefix = prefix;
                                output_prefix = 1;
-                               i++;
                                continue;
                        }
                        if (!strcmp(arg, "--revs-only")) {
@@ -738,9 +740,12 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                                continue;
                        }
                        if (!strcmp(arg, "--resolve-git-dir")) {
-                               const char *gitdir = resolve_gitdir(argv[i+1]);
+                               const char *gitdir = argv[++i];
                                if (!gitdir)
-                                       die("not a gitdir '%s'", argv[i+1]);
+                                       die("--resolve-git-dir requires an argument");
+                               gitdir = resolve_gitdir(gitdir);
+                               if (!gitdir)
+                                       die("not a gitdir '%s'", argv[i]);
                                puts(gitdir);
                                continue;
                        }
index 3a0e0eaab7d1fd8a298bb2519776abede5c685e2..05642184c5d89addae1900660ad99e5f29c324f2 100644 (file)
@@ -308,7 +308,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 
        for (i = 0; i < active_nr; i++) {
                const struct cache_entry *ce = active_cache[i];
-               if (!match_pathspec_depth(&pathspec, ce->name, ce_namelen(ce), 0, seen))
+               if (!ce_path_match(ce, &pathspec, seen))
                        continue;
                ALLOC_GROW(list.entry, list.nr + 1, list.alloc);
                list.entry[list.nr].name = ce->name;
index e3a10d706d406845b74b2cc0c9e9a120be6adce0..aaa6f78f1629311257291ba1075ddd7c7dd1a3ed 100644 (file)
@@ -12,6 +12,7 @@
 #include "resolve-undo.h"
 #include "parse-options.h"
 #include "pathspec.h"
+#include "dir.h"
 
 /*
  * Default to not allowing changes to the list of files. The
@@ -564,7 +565,7 @@ static int do_reupdate(int ac, const char **av,
                struct cache_entry *old = NULL;
                int save_nr;
 
-               if (ce_stage(ce) || !ce_path_match(ce, &pathspec))
+               if (ce_stage(ce) || !ce_path_match(ce, &pathspec, NULL))
                        continue;
                if (has_head)
                        old = read_one_ent(NULL, head_sha1,
index 1292cfea11d87e8c98ba64ffae9d6a1aeffaca9f..5c208bb1fc4f6c467842b37157435e87fe1415cd 100644 (file)
@@ -147,6 +147,7 @@ static void parse_cmd_create(const char *next)
        struct ref_update *update;
 
        update = update_alloc();
+       update->have_old = 1;
 
        if ((next = parse_first_arg(next, &ref)) != NULL && ref.buf[0])
                update_store_ref_name(update, ref.buf);
diff --git a/cache.h b/cache.h
index dc040fb1aa99b7970e85e5b175e60f862ff6a74a..ebe9a405d811b2cc6b64109db135bb8ca4096e9e 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -487,7 +487,7 @@ extern int remove_file_from_index(struct index_state *, const char *path);
 #define ADD_CACHE_IMPLICIT_DOT 32      /* internal to "git add -u/-A" */
 extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags);
 extern int add_file_to_index(struct index_state *, const char *path, int flags);
-extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);
+extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, unsigned int refresh_options);
 extern int ce_same_name(const struct cache_entry *a, const struct cache_entry *b);
 extern int index_name_is_other(const struct index_state *, const char *, int);
 extern void *read_blob_data_from_index(struct index_state *, const char *, unsigned long *);
@@ -498,11 +498,13 @@ extern void *read_blob_data_from_index(struct index_state *, const char *, unsig
 #define CE_MATCH_RACY_IS_DIRTY         02
 /* do stat comparison even if CE_SKIP_WORKTREE is true */
 #define CE_MATCH_IGNORE_SKIP_WORKTREE  04
+/* ignore non-existent files during stat update  */
+#define CE_MATCH_IGNORE_MISSING                0x08
+/* enable stat refresh */
+#define CE_MATCH_REFRESH               0x10
 extern int ie_match_stat(const struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
 extern int ie_modified(const struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
 
-extern int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec);
-
 #define HASH_WRITE_OBJECT 1
 #define HASH_FORMAT_CHECK 2
 extern int index_fd(unsigned char *sha1, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
@@ -959,6 +961,7 @@ void datestamp(char *buf, int bufsize);
 unsigned long approxidate_careful(const char *, int *);
 unsigned long approxidate_relative(const char *date, const struct timeval *now);
 enum date_mode parse_date_format(const char *format);
+int date_overflows(unsigned long date);
 
 #define IDENT_STRICT          1
 #define IDENT_NO_DATE         2
index 9367ba5db589e63b770c431121176ff046603d06..8d1ce88d1493cf18436b03f843c6d90190d47bb2 100644 (file)
--- a/column.c
+++ b/column.c
@@ -311,8 +311,8 @@ static int parse_config(unsigned int *colopts, const char *value)
                value += strspn(value, sep);
        }
        /*
-        * Setting layout implies "always" if neither always, never
-        * nor auto is specified.
+        * If none of "always", "never", and "auto" is specified, then setting
+        * layout implies "always".
         *
         * Current value in COL_ENABLE_MASK is disregarded. This means if
         * you set column.ui = auto and pass --column=row, then "auto"
index 16d9c4351395ac55d6856d8d92d24ce7064df974..a9f177ba488a7002409eb2cdee1f7e9c3673529f 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -209,7 +209,7 @@ extern int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
 extern void setup_alternate_shallow(struct lock_file *shallow_lock,
                                    const char **alternate_shallow_file,
                                    const struct sha1_array *extra);
-extern char *setup_temporary_shallow(const struct sha1_array *extra);
+extern const char *setup_temporary_shallow(const struct sha1_array *extra);
 extern void advertise_shallow_grafts(int);
 
 struct shallow_info {
@@ -304,4 +304,7 @@ extern void check_commit_signature(const struct commit* commit, struct signature
 
 int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused);
 
+LAST_ARG_MUST_BE_NULL
+extern int run_commit_hook(int editor_is_used, const char *index_file, const char *name, ...);
+
 #endif /* COMMIT_H */
diff --git a/compat/gmtime.c b/compat/gmtime.c
new file mode 100644 (file)
index 0000000..e8362dd
--- /dev/null
@@ -0,0 +1,29 @@
+#include "../git-compat-util.h"
+#undef gmtime
+#undef gmtime_r
+
+struct tm *git_gmtime(const time_t *timep)
+{
+       static struct tm result;
+       return git_gmtime_r(timep, &result);
+}
+
+struct tm *git_gmtime_r(const time_t *timep, struct tm *result)
+{
+       struct tm *ret;
+
+       memset(result, 0, sizeof(*result));
+       ret = gmtime_r(timep, result);
+
+       /*
+        * Rather than NULL, FreeBSD gmtime simply leaves the "struct tm"
+        * untouched when it encounters overflow. Since "mday" cannot otherwise
+        * be zero, we can test this very quickly.
+        */
+       if (ret && !ret->tm_mday) {
+               ret = NULL;
+               errno = EOVERFLOW;
+       }
+
+       return ret;
+}
index d969a5aefc2bca92938d3fd7f6a507e884ce2b7f..314d8ee740bea488d8c79d80b3d91530ad15252d 100644 (file)
--- a/config.c
+++ b/config.c
@@ -84,8 +84,12 @@ static int handle_path_include(const char *path, struct config_include_data *inc
 {
        int ret = 0;
        struct strbuf buf = STRBUF_INIT;
-       char *expanded = expand_user_path(path);
+       char *expanded;
 
+       if (!path)
+               return config_error_nonbool("include.path");
+
+       expanded = expand_user_path(path);
        if (!expanded)
                return error("Could not expand include path '%s'", path);
        path = expanded;
index 7d31fad241761e41de655de6f42ddfb8c87ea4f2..efaed94d5d69439dc3612345679302577e68a25a 100644 (file)
@@ -188,6 +188,7 @@ ifeq ($(uname_S),FreeBSD)
        endif
        PYTHON_PATH = /usr/local/bin/python
        HAVE_PATHS_H = YesPlease
+       GMTIME_UNRELIABLE_ERRORS = UnfortunatelyYes
 endif
 ifeq ($(uname_S),OpenBSD)
        NO_STRCASESTR = YesPlease
index 1a7689a48f07a6ed2bb156f745bfea19a10e3eb9..d2c1f98b8628e2b807bc49ff310097686f3da6e6 100755 (executable)
@@ -168,7 +168,7 @@ cd_to_toplevel
 # branch.  However, if "git checkout HEAD" detaches the HEAD
 # from the current branch, even though that may be logically
 # correct, it feels somewhat funny.  More importantly, we do not
-# want "git checkout" nor "git checkout -f" to detach HEAD.
+# want "git checkout" or "git checkout -f" to detach HEAD.
 
 detached=
 detach_warn=
index 23ffb028d1ece96d8c363ddeacca83d2b20b628f..4aab1a6d2161186227779ca5e793ed727c64d9db 100755 (executable)
@@ -280,7 +280,7 @@ case "$#,$also,$only,$amend" in
 0,,,*)
        ;;
 *,,,*)
-       only_include_assumed="# Explicit paths specified without -i nor -o; assuming --only paths..."
+       only_include_assumed="# Explicit paths specified without -i or -o; assuming --only paths..."
        also=
        ;;
 esac
index bafeb52cd113ad8a07ffd1912191f2bc17a7ef7a..cb1bbf3b90e911ac5fea09e00d6e0189b8ee7104 100755 (executable)
@@ -40,7 +40,7 @@ case "$1" in --) shift ;; esac
 
 # git reset --mixed tree [--] paths... can be used to
 # load chosen paths from the tree into the index without
-# affecting the working tree nor HEAD.
+# affecting the working tree or HEAD.
 if test $# != 0
 then
        test "$reset_type" = "--mixed" ||
@@ -60,7 +60,7 @@ then
        update=-u
 fi
 
-# Soft reset does not touch the index file nor the working tree
+# Soft reset does not touch the index file or the working tree
 # at all, but requires them in a good order.  Other resets reset
 # the index file to the tree object we are switching to.
 if test "$reset_type" = "--soft"
index 7f3afa5ac4a4ca979a4e5dd63ebc59344f20857b..4dec1f18e425bd755052ca5645651eec47821cc0 100755 (executable)
@@ -109,8 +109,8 @@ =head3 Revision contents section
 be removed.
 
 If an on-disk revision is incomplete, you can point to files from
-a previous revision. There are no restriction as to where the source
-files are located, nor to the names of them.
+a previous revision. There are no restrictions on where the source
+files are located, nor on their names.
 
  [3.files]
  ; the key is the path inside the repository, the value is the path
index 1128ab2ce46c42c5b5c9bf2adb3425ebc2720944..a3425f4770c5cd829b72134080b05aeb1174ff33 100644 (file)
@@ -40,8 +40,8 @@ manual page.
 NOTES
 -----
 Subversion dumps do not record a separate author and committer for
-each revision, nor a separate display name and email address for
-each author.  Like git-svn(1), 'svn-fe' will use the name
+each revision, nor do they record a separate display name and email
+address for each author.  Like git-svn(1), 'svn-fe' will use the name
 
 ---------
 user <user@UUID>
diff --git a/date.c b/date.c
index 83b4166344b31ea615603acaeb95a873f2c05077..e1a2cee5688a64555d7820e8e02e3e86839c9641 100644 (file)
--- a/date.c
+++ b/date.c
@@ -184,8 +184,10 @@ const char *show_date(unsigned long time, int tz, enum date_mode mode)
                tz = local_tzoffset(time);
 
        tm = time_to_tm(time, tz);
-       if (!tm)
-               return NULL;
+       if (!tm) {
+               tm = time_to_tm(0, 0);
+               tz = 0;
+       }
 
        strbuf_reset(&timebuf);
        if (mode == DATE_SHORT)
@@ -1113,3 +1115,20 @@ unsigned long approxidate_careful(const char *date, int *error_ret)
        gettimeofday(&tv, NULL);
        return approxidate_str(date, &tv, error_ret);
 }
+
+int date_overflows(unsigned long t)
+{
+       time_t sys;
+
+       /* If we overflowed our unsigned long, that's bad... */
+       if (t == ULONG_MAX)
+               return 1;
+
+       /*
+        * ...but we also are going to feed the result to system
+        * functions that expect time_t, which is often "signed long".
+        * Make sure that we fit into time_t, as well.
+        */
+       sys = t;
+       return t != sys || (t < 1) != (sys < 1);
+}
diff --git a/delta.h b/delta.h
index b9d333dd5a1c64ab35159ed608cf942951504f84..9b67531dfa4e6511d0c7a4d6d400a3d3719603bc 100644 (file)
--- a/delta.h
+++ b/delta.h
@@ -9,7 +9,7 @@ struct delta_index;
  *
  * This returns a pointer to a struct delta_index that should be passed to
  * subsequent create_delta() calls, or to free_delta_index().  A NULL pointer
- * is returned on failure.  The given buffer must not be freed nor altered
+ * is returned on failure.  The given buffer must not be freed or altered
  * before free_delta_index() is called.  The returned pointer must be freed
  * using free_delta_index().
  */
index 346cac651da725af07a304194d8d8e04b2f080b7..2eddc66bbd5cf37e4649e219a28c951ed134557c 100644 (file)
@@ -11,6 +11,7 @@
 #include "unpack-trees.h"
 #include "refs.h"
 #include "submodule.h"
+#include "dir.h"
 
 /*
  * diff-files
@@ -108,7 +109,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
                if (diff_can_quit_early(&revs->diffopt))
                        break;
 
-               if (!ce_path_match(ce, &revs->prune_data))
+               if (!ce_path_match(ce, &revs->prune_data, NULL))
                        continue;
 
                if (ce_stage(ce)) {
@@ -438,7 +439,7 @@ static int oneway_diff(const struct cache_entry * const *src,
        if (tree == o->df_conflict_entry)
                tree = NULL;
 
-       if (ce_path_match(idx ? idx : tree, &revs->prune_data)) {
+       if (ce_path_match(idx ? idx : tree, &revs->prune_data, NULL)) {
                do_oneway_diff(o, idx, tree);
                if (diff_can_quit_early(&revs->diffopt)) {
                        o->exiting_early = 1;
index 33e5982a1c61a5726580f40df0a07dadc7e2aaf1..798477f7e5b19e3141bd8a1e63bc650f13ad2e39 100644 (file)
@@ -202,7 +202,7 @@ void diff_no_index(struct rev_info *revs,
                        i++;
                else {
                        j = diff_opt_parse(&revs->diffopt, argv + i, argc - i);
-                       if (!j)
+                       if (j <= 0)
                                die("invalid diff option/value: %s", argv[i]);
                        i += j;
                }
diff --git a/diff.c b/diff.c
index 8e4a6a910519b2bb6d6a0337682ab402f2650997..635dee244d767bffc689550fd3e32d0ac1a37fea 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -2845,8 +2845,9 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
                remove_tempfile_installed = 1;
        }
 
-       if (!one->sha1_valid ||
-           reuse_worktree_file(name, one->sha1, 1)) {
+       if (!S_ISGITLINK(one->mode) &&
+           (!one->sha1_valid ||
+            reuse_worktree_file(name, one->sha1, 1))) {
                struct stat st;
                if (lstat(name, &st) < 0) {
                        if (errno == ENOENT)
@@ -3941,7 +3942,7 @@ static int diff_scoreopt_parse(const char *opt)
                }
        }
        if (cmd != 'M' && cmd != 'C' && cmd != 'B')
-               return -1; /* that is not a -M, -C nor -B option */
+               return -1; /* that is not a -M, -Cor -B option */
 
        opt1 = parse_rename_score(&opt);
        if (cmd != 'B')
@@ -4697,6 +4698,38 @@ static int diff_filespec_is_identical(struct diff_filespec *one,
        return !memcmp(one->data, two->data, one->size);
 }
 
+static int diff_filespec_check_stat_unmatch(struct diff_filepair *p)
+{
+       if (p->done_skip_stat_unmatch)
+               return p->skip_stat_unmatch_result;
+
+       p->done_skip_stat_unmatch = 1;
+       p->skip_stat_unmatch_result = 0;
+       /*
+        * 1. Entries that come from stat info dirtiness
+        *    always have both sides (iow, not create/delete),
+        *    one side of the object name is unknown, with
+        *    the same mode and size.  Keep the ones that
+        *    do not match these criteria.  They have real
+        *    differences.
+        *
+        * 2. At this point, the file is known to be modified,
+        *    with the same mode and size, and the object
+        *    name of one side is unknown.  Need to inspect
+        *    the identical contents.
+        */
+       if (!DIFF_FILE_VALID(p->one) || /* (1) */
+           !DIFF_FILE_VALID(p->two) ||
+           (p->one->sha1_valid && p->two->sha1_valid) ||
+           (p->one->mode != p->two->mode) ||
+           diff_populate_filespec(p->one, 1) ||
+           diff_populate_filespec(p->two, 1) ||
+           (p->one->size != p->two->size) ||
+           !diff_filespec_is_identical(p->one, p->two)) /* (2) */
+               p->skip_stat_unmatch_result = 1;
+       return p->skip_stat_unmatch_result;
+}
+
 static void diffcore_skip_stat_unmatch(struct diff_options *diffopt)
 {
        int i;
@@ -4707,27 +4740,7 @@ static void diffcore_skip_stat_unmatch(struct diff_options *diffopt)
        for (i = 0; i < q->nr; i++) {
                struct diff_filepair *p = q->queue[i];
 
-               /*
-                * 1. Entries that come from stat info dirtiness
-                *    always have both sides (iow, not create/delete),
-                *    one side of the object name is unknown, with
-                *    the same mode and size.  Keep the ones that
-                *    do not match these criteria.  They have real
-                *    differences.
-                *
-                * 2. At this point, the file is known to be modified,
-                *    with the same mode and size, and the object
-                *    name of one side is unknown.  Need to inspect
-                *    the identical contents.
-                */
-               if (!DIFF_FILE_VALID(p->one) || /* (1) */
-                   !DIFF_FILE_VALID(p->two) ||
-                   (p->one->sha1_valid && p->two->sha1_valid) ||
-                   (p->one->mode != p->two->mode) ||
-                   diff_populate_filespec(p->one, 1) ||
-                   diff_populate_filespec(p->two, 1) ||
-                   (p->one->size != p->two->size) ||
-                   !diff_filespec_is_identical(p->one, p->two)) /* (2) */
+               if (diff_filespec_check_stat_unmatch(p))
                        diff_q(&outq, p);
                else {
                        /*
@@ -4890,6 +4903,7 @@ void diff_change(struct diff_options *options,
                 unsigned old_dirty_submodule, unsigned new_dirty_submodule)
 {
        struct diff_filespec *one, *two;
+       struct diff_filepair *p;
 
        if (S_ISGITLINK(old_mode) && S_ISGITLINK(new_mode) &&
            is_submodule_ignored(concatpath, options))
@@ -4916,10 +4930,16 @@ void diff_change(struct diff_options *options,
        fill_filespec(two, new_sha1, new_sha1_valid, new_mode);
        one->dirty_submodule = old_dirty_submodule;
        two->dirty_submodule = new_dirty_submodule;
+       p = diff_queue(&diff_queued_diff, one, two);
 
-       diff_queue(&diff_queued_diff, one, two);
-       if (!DIFF_OPT_TST(options, DIFF_FROM_CONTENTS))
-               DIFF_OPT_SET(options, HAS_CHANGES);
+       if (DIFF_OPT_TST(options, DIFF_FROM_CONTENTS))
+               return;
+
+       if (DIFF_OPT_TST(options, QUICK) && options->skip_stat_unmatch &&
+           !diff_filespec_check_stat_unmatch(p))
+               return;
+
+       DIFF_OPT_SET(options, HAS_CHANGES);
 }
 
 struct diff_filepair *diff_unmerge(struct diff_options *options, const char *path)
index 79de8cf28dc6919f069ae44f7f036a46264452e9..1315cfd4ef0fbe0aeb0cae9a14bf09fd53212124 100644 (file)
@@ -68,6 +68,8 @@ struct diff_filepair {
        unsigned broken_pair : 1;
        unsigned renamed_pair : 1;
        unsigned is_unmerged : 1;
+       unsigned done_skip_stat_unmatch : 1;
+       unsigned skip_stat_unmatch_result : 1;
 };
 #define DIFF_PAIR_UNMERGED(p) ((p)->is_unmerged)
 
diff --git a/dir.c b/dir.c
index b35b6330f850f610b582b189d7e4d6a9ba4495db..98bb50fbabb69d25443df8ca4d29e11dea746a60 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -195,6 +195,9 @@ int within_depth(const char *name, int namelen,
        return 1;
 }
 
+#define DO_MATCH_EXCLUDE   1
+#define DO_MATCH_DIRECTORY 2
+
 /*
  * Does 'match' match the given name?
  * A match is found if
@@ -208,7 +211,7 @@ int within_depth(const char *name, int namelen,
  * It returns 0 when there is no match.
  */
 static int match_pathspec_item(const struct pathspec_item *item, int prefix,
-                              const char *name, int namelen)
+                              const char *name, int namelen, unsigned flags)
 {
        /* name/namelen has prefix cut off by caller */
        const char *match = item->match + prefix;
@@ -218,7 +221,7 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,
         * The normal call pattern is:
         * 1. prefix = common_prefix_len(ps);
         * 2. prune something, or fill_directory
-        * 3. match_pathspec_depth()
+        * 3. match_pathspec()
         *
         * 'prefix' at #1 may be shorter than the command's prefix and
         * it's ok for #2 to match extra files. Those extras will be
@@ -257,7 +260,11 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,
 
                if (match[matchlen-1] == '/' || name[matchlen] == '/')
                        return MATCHED_RECURSIVELY;
-       }
+       } else if ((flags & DO_MATCH_DIRECTORY) &&
+                  match[matchlen - 1] == '/' &&
+                  namelen == matchlen - 1 &&
+                  !ps_strncmp(item, match, name, namelen))
+               return MATCHED_EXACTLY;
 
        if (item->nowildcard_len < item->len &&
            !git_fnmatch(item, match, name,
@@ -282,12 +289,12 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,
  * pathspec did not match any names, which could indicate that the
  * user mistyped the nth pathspec.
  */
-static int match_pathspec_depth_1(const struct pathspec *ps,
-                                 const char *name, int namelen,
-                                 int prefix, char *seen,
-                                 int exclude)
+static int do_match_pathspec(const struct pathspec *ps,
+                            const char *name, int namelen,
+                            int prefix, char *seen,
+                            unsigned flags)
 {
-       int i, retval = 0;
+       int i, retval = 0, exclude = flags & DO_MATCH_EXCLUDE;
 
        GUARD_PATHSPEC(ps,
                       PATHSPEC_FROMTOP |
@@ -327,7 +334,8 @@ static int match_pathspec_depth_1(const struct pathspec *ps,
                 */
                if (seen && ps->items[i].magic & PATHSPEC_EXCLUDE)
                        seen[i] = MATCHED_FNMATCH;
-               how = match_pathspec_item(ps->items+i, prefix, name, namelen);
+               how = match_pathspec_item(ps->items+i, prefix, name,
+                                         namelen, flags);
                if (ps->recursive &&
                    (ps->magic & PATHSPEC_MAXDEPTH) &&
                    ps->max_depth != -1 &&
@@ -350,15 +358,19 @@ static int match_pathspec_depth_1(const struct pathspec *ps,
        return retval;
 }
 
-int match_pathspec_depth(const struct pathspec *ps,
-                        const char *name, int namelen,
-                        int prefix, char *seen)
+int match_pathspec(const struct pathspec *ps,
+                  const char *name, int namelen,
+                  int prefix, char *seen, int is_dir)
 {
        int positive, negative;
-       positive = match_pathspec_depth_1(ps, name, namelen, prefix, seen, 0);
+       unsigned flags = is_dir ? DO_MATCH_DIRECTORY : 0;
+       positive = do_match_pathspec(ps, name, namelen,
+                                    prefix, seen, flags);
        if (!(ps->magic & PATHSPEC_EXCLUDE) || !positive)
                return positive;
-       negative = match_pathspec_depth_1(ps, name, namelen, prefix, seen, 1);
+       negative = do_match_pathspec(ps, name, namelen,
+                                    prefix, seen,
+                                    flags | DO_MATCH_EXCLUDE);
        return negative ? 0 : positive;
 }
 
diff --git a/dir.h b/dir.h
index 9b7e4e77d8b11bab92a91a6ce3e8920e50d23f9b..55e53456afab4c9fb8441144ac7393458b553006 100644 (file)
--- a/dir.h
+++ b/dir.h
@@ -132,9 +132,9 @@ struct dir_struct {
 extern int simple_length(const char *match);
 extern int no_wildcard(const char *string);
 extern char *common_prefix(const struct pathspec *pathspec);
-extern int match_pathspec_depth(const struct pathspec *pathspec,
-                               const char *name, int namelen,
-                               int prefix, char *seen);
+extern int match_pathspec(const struct pathspec *pathspec,
+                         const char *name, int namelen,
+                         int prefix, char *seen, int is_dir);
 extern int within_depth(const char *name, int namelen, int depth, int max_depth);
 
 extern int fill_directory(struct dir_struct *dir, const struct pathspec *pathspec);
@@ -205,4 +205,22 @@ extern int git_fnmatch(const struct pathspec_item *item,
                       const char *pattern, const char *string,
                       int prefix);
 
+static inline int ce_path_match(const struct cache_entry *ce,
+                               const struct pathspec *pathspec,
+                               char *seen)
+{
+       return match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, seen,
+                             S_ISDIR(ce->ce_mode) || S_ISGITLINK(ce->ce_mode));
+}
+
+static inline int dir_path_match(const struct dir_entry *ent,
+                                const struct pathspec *pathspec,
+                                int prefix, char *seen)
+{
+       int has_trailing_dir = ent->len && ent->name[ent->len - 1] == '/';
+       int len = has_trailing_dir ? ent->len - 1 : ent->len;
+       return match_pathspec(pathspec, ent->name, len, prefix, seen,
+                             has_trailing_dir);
+}
+
 #endif
diff --git a/entry.c b/entry.c
index 7b7aa8167adade20f38cfb2709e02b3ed31f11a4..77c688262477e783b4bcbc237ef281eecab0661d 100644 (file)
--- a/entry.c
+++ b/entry.c
@@ -44,33 +44,33 @@ static void create_directories(const char *path, int path_len,
        free(buf);
 }
 
-static void remove_subtree(const char *path)
+static void remove_subtree(struct strbuf *path)
 {
-       DIR *dir = opendir(path);
+       DIR *dir = opendir(path->buf);
        struct dirent *de;
-       char pathbuf[PATH_MAX];
-       char *name;
+       int origlen = path->len;
 
        if (!dir)
-               die_errno("cannot opendir '%s'", path);
-       strcpy(pathbuf, path);
-       name = pathbuf + strlen(path);
-       *name++ = '/';
+               die_errno("cannot opendir '%s'", path->buf);
        while ((de = readdir(dir)) != NULL) {
                struct stat st;
+
                if (is_dot_or_dotdot(de->d_name))
                        continue;
-               strcpy(name, de->d_name);
-               if (lstat(pathbuf, &st))
-                       die_errno("cannot lstat '%s'", pathbuf);
+
+               strbuf_addch(path, '/');
+               strbuf_addstr(path, de->d_name);
+               if (lstat(path->buf, &st))
+                       die_errno("cannot lstat '%s'", path->buf);
                if (S_ISDIR(st.st_mode))
-                       remove_subtree(pathbuf);
-               else if (unlink(pathbuf))
-                       die_errno("cannot unlink '%s'", pathbuf);
+                       remove_subtree(path);
+               else if (unlink(path->buf))
+                       die_errno("cannot unlink '%s'", path->buf);
+               strbuf_setlen(path, origlen);
        }
        closedir(dir);
-       if (rmdir(path))
-               die_errno("cannot rmdir '%s'", path);
+       if (rmdir(path->buf))
+               die_errno("cannot rmdir '%s'", path->buf);
 }
 
 static int create_file(const char *path, unsigned int mode)
@@ -245,27 +245,25 @@ static int check_path(const char *path, int len, struct stat *st, int skiplen)
 int checkout_entry(struct cache_entry *ce,
                   const struct checkout *state, char *topath)
 {
-       static struct strbuf path_buf = STRBUF_INIT;
-       char *path;
+       static struct strbuf path = STRBUF_INIT;
        struct stat st;
-       int len;
 
        if (topath)
                return write_entry(ce, topath, state, 1);
 
-       strbuf_reset(&path_buf);
-       strbuf_add(&path_buf, state->base_dir, state->base_dir_len);
-       strbuf_add(&path_buf, ce->name, ce_namelen(ce));
-       path = path_buf.buf;
-       len = path_buf.len;
+       strbuf_reset(&path);
+       strbuf_add(&path, state->base_dir, state->base_dir_len);
+       strbuf_add(&path, ce->name, ce_namelen(ce));
 
-       if (!check_path(pathlen, &st, state->base_dir_len)) {
+       if (!check_path(path.buf, path.len, &st, state->base_dir_len)) {
                unsigned changed = ce_match_stat(ce, &st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE);
                if (!changed)
                        return 0;
                if (!state->force) {
                        if (!state->quiet)
-                               fprintf(stderr, "%s already exists, no checkout\n", path);
+                               fprintf(stderr,
+                                       "%s already exists, no checkout\n",
+                                       path.buf);
                        return -1;
                }
 
@@ -280,12 +278,14 @@ int checkout_entry(struct cache_entry *ce,
                        if (S_ISGITLINK(ce->ce_mode))
                                return 0;
                        if (!state->force)
-                               return error("%s is a directory", path);
-                       remove_subtree(path);
-               } else if (unlink(path))
-                       return error("unable to unlink old '%s' (%s)", path, strerror(errno));
+                               return error("%s is a directory", path.buf);
+                       remove_subtree(&path);
+               } else if (unlink(path.buf))
+                       return error("unable to unlink old '%s' (%s)",
+                                    path.buf, strerror(errno));
        } else if (state->not_new)
                return 0;
-       create_directories(path, len, state);
-       return write_entry(ce, path, state, 0);
+
+       create_directories(path.buf, path.len, state);
+       return write_entry(ce, path.buf, state, 0);
 }
index 90fdd49821a1d6d3e104124444e37ac4b9b03fa2..90d47da8a902f24bb6a7ae63654a104626751b1e 100644 (file)
@@ -439,7 +439,8 @@ static int find_common(struct fetch_pack_args *args,
        }
        strbuf_release(&req_buf);
 
-       consume_shallow_list(args, fd[0]);
+       if (!got_ready || !no_done)
+               consume_shallow_list(args, fd[0]);
        while (flushes || multi_ack) {
                int ack = get_ack(fd[0], result_sha1);
                if (ack) {
@@ -947,17 +948,6 @@ static void update_shallow(struct fetch_pack_args *args,
        if (!si->shallow || !si->shallow->nr)
                return;
 
-       if (alternate_shallow_file) {
-               /*
-                * The temporary shallow file is only useful for
-                * index-pack and unpack-objects because it may
-                * contain more roots than we want. Delete it.
-                */
-               if (*alternate_shallow_file)
-                       unlink(alternate_shallow_file);
-               free((char *)alternate_shallow_file);
-       }
-
        if (args->cloning) {
                /*
                 * remote is shallow, but this is a clone, there are
diff --git a/fsck.c b/fsck.c
index 99c049767484288f273f036b57683df04c1ef0df..64bf279fd7e42da1921a65d725007c52c7ddc5fb 100644 (file)
--- a/fsck.c
+++ b/fsck.c
@@ -245,6 +245,8 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
 
 static int fsck_ident(char **ident, struct object *obj, fsck_error error_func)
 {
+       char *end;
+
        if (**ident == '<')
                return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing space before email");
        *ident += strcspn(*ident, "<>\n");
@@ -264,10 +266,11 @@ static int fsck_ident(char **ident, struct object *obj, fsck_error error_func)
        (*ident)++;
        if (**ident == '0' && (*ident)[1] != ' ')
                return error_func(obj, FSCK_ERROR, "invalid author/committer line - zero-padded date");
-       *ident += strspn(*ident, "0123456789");
-       if (**ident != ' ')
+       if (date_overflows(strtoul(*ident, &end, 10)))
+               return error_func(obj, FSCK_ERROR, "invalid author/committer line - date causes integer overflow");
+       if (end == *ident || *end != ' ')
                return error_func(obj, FSCK_ERROR, "invalid author/committer line - bad date");
-       (*ident)++;
+       *ident = end + 1;
        if ((**ident != '+' && **ident != '-') ||
            !isdigit((*ident)[1]) ||
            !isdigit((*ident)[2]) ||
@@ -287,9 +290,6 @@ static int fsck_commit(struct commit *commit, fsck_error error_func)
        int parents = 0;
        int err;
 
-       if (commit->date == ULONG_MAX)
-               return error_func(&commit->object, FSCK_ERROR, "invalid author/committer line");
-
        if (memcmp(buffer, "tree ", 5))
                return error_func(&commit->object, FSCK_ERROR, "invalid format - expected 'tree' line");
        if (get_sha1_hex(buffer+5, tree_sha1) || buffer[45] != '\n')
index 24bb1ab9929d2cbf117051ed0e4edeb37b0efaea..32c2f9cf88201b2dc2b94b9c97633c8c67d8c6c5 100755 (executable)
@@ -1156,9 +1156,9 @@ sub help_patch_cmd {
        print colored $help_color, <<EOF ;
 y - $verb this hunk$target
 n - do not $verb this hunk$target
-q - quit; do not $verb this hunk nor any of the remaining ones
+q - quit; do not $verb this hunk or any of the remaining ones
 a - $verb this hunk and all later hunks in the file
-d - do not $verb this hunk nor any of the later hunks in the file
+d - do not $verb this hunk or any of the later hunks in the file
 g - select a hunk to go to
 / - search for a hunk matching the given regex
 j - leave this hunk undecided, see next undecided hunk
index bbea43075be030c272ef0d8e4cb9c25a179d4e53..e92e5bb121d50d21f104c3f66e90a7c1db5f34a6 100755 (executable)
--- a/git-am.sh
+++ b/git-am.sh
@@ -523,7 +523,7 @@ Use \"git am --abort\" to remove it.")"
                esac
        fi
 
-       # Make sure we are not given --skip, --continue, nor --abort
+       # Make sure we are not given --skip, --continue, or --abort
        test "$skip$resolved$abort" = "" ||
                die "$(gettext "Resolve operation not in progress, we are not resuming.")"
 
index cbd86c37f51c00679498107d1a05131c19afa36e..d493a8c67ac1a91c40dfff0023c6ecf14155c09a 100644 (file)
@@ -721,4 +721,11 @@ void warn_on_inaccessible(const char *path);
 /* Get the passwd entry for the UID of the current process. */
 struct passwd *xgetpwuid_self(void);
 
+#ifdef GMTIME_UNRELIABLE_ERRORS
+struct tm *git_gmtime(const time_t *);
+struct tm *git_gmtime_r(const time_t *, struct tm *);
+#define gmtime git_gmtime
+#define gmtime_r git_gmtime_r
+#endif
+
 #endif
index e57d3d1295a5ba0a9c02c19df512c909a0631baa..18ca61e8d0493bde9c21ed337043bc72fa5c73a7 100755 (executable)
@@ -39,24 +39,10 @@ sub usage
 
 sub find_worktree
 {
-       my ($repo) = @_;
-
        # Git->repository->wc_path() does not honor changes to the working
        # tree location made by $ENV{GIT_WORK_TREE} or the 'core.worktree'
        # config variable.
-       my $worktree;
-       my $env_worktree = $ENV{GIT_WORK_TREE};
-       my $core_worktree = Git::config('core.worktree');
-
-       if (defined($env_worktree) and (length($env_worktree) > 0)) {
-               $worktree = $env_worktree;
-       } elsif (defined($core_worktree) and (length($core_worktree) > 0)) {
-               $worktree = $core_worktree;
-       } else {
-               $worktree = $repo->wc_path();
-       }
-
-       return $worktree;
+       return Git::command_oneline('rev-parse', '--show-toplevel');
 }
 
 sub print_tool_help
@@ -418,7 +404,7 @@ sub dir_diff
        my $rc;
        my $error = 0;
        my $repo = Git->repository();
-       my $workdir = find_worktree($repo);
+       my $workdir = find_worktree();
        my ($a, $b, $tmpdir, @worktree) =
                setup_dir_diff($repo, $workdir, $symlinks);
 
index 43c19e0829ca727501ba7e4d29c952bc286ccb77..43631b472311d0feb13f4d62c6355baeedbdb040 100644 (file)
@@ -739,7 +739,7 @@ rearrange_squash () {
                                        ;;
                                esac
                        done
-                       echo "$sha1 $action $prefix $rest"
+                       printf '%s %s %s %s\n' "$sha1" "$action" "$prefix" "$rest"
                        # if it's a single word, try to resolve to a full sha1 and
                        # emit a second copy. This allows us to match on both message
                        # and on sha1 prefix
index f0a94abf1434c65d27caf4cd674f89de62e9333c..4798bcf0e51b705005215e9a6339310defe16d03 100755 (executable)
@@ -512,8 +512,14 @@ apply_stash () {
 pop_stash() {
        assert_stash_ref "$@"
 
-       apply_stash "$@" &&
-       drop_stash "$@"
+       if apply_stash "$@"
+       then
+               drop_stash "$@"
+       else
+               status=$?
+               say "The stash is kept in case you need it again."
+               exit $status
+       fi
 }
 
 drop_stash () {
index 3bc0f0b5ca0995910e0e517b545b5fb9af626a8b..52108b925526764f78be017afc47003036469346 100755 (executable)
@@ -1490,7 +1490,7 @@ sub is_valid_pathname {
        my $input = shift;
 
        return undef unless defined $input;
-       # no '.' or '..' as elements of path, i.e. no '.' nor '..'
+       # no '.' or '..' as elements of path, i.e. no '.' or '..'
        # at the beginning, at the end, and between slashes.
        # also this catches doubled slashes
        if ($input =~ m!(^|/)(|\.|\.\.)(/|$)!) {
diff --git a/http.h b/http.h
index cd37d5881cb0e63e52bd33d0b49bed49645340f5..a766066dfde652d13bbd30f1bb83928b1e727f22 100644 (file)
--- a/http.h
+++ b/http.h
@@ -13,8 +13,7 @@
 /*
  * We detect based on the cURL version if multi-transfer is
  * usable in this implementation and define this symbol accordingly.
- * This is not something Makefile should set nor users should pass
- * via CFLAGS.
+ * This shouldn't be set by the Makefile or by the user (e.g. via CFLAGS).
  */
 #undef USE_CURL_MULTI
 
index 8400a8e937d8303ecc2ace1136a0700187865f58..41770929420da4cba934b0b86b9cd2f55f9cab31 100644 (file)
@@ -201,7 +201,9 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
                const char *path, int stage, int refresh, int options)
 {
        struct cache_entry *ce;
-       ce = make_cache_entry(mode, sha1 ? sha1 : null_sha1, path, stage, refresh);
+       ce = make_cache_entry(mode, sha1 ? sha1 : null_sha1, path, stage,
+                             (refresh ? (CE_MATCH_REFRESH |
+                                         CE_MATCH_IGNORE_MISSING) : 0 ));
        if (!ce)
                return error(_("addinfo_cache failed for path '%s'"), path);
        return add_cache_entry(ce, options);
diff --git a/path.c b/path.c
index 24594c41120bebab1e04f5bc4bd8fc484ea71b97..f9c5062427e7d8170a1e2e597fcf22ae517a865e 100644 (file)
--- a/path.c
+++ b/path.c
@@ -265,12 +265,12 @@ static struct passwd *getpw_str(const char *username, size_t len)
 char *expand_user_path(const char *path)
 {
        struct strbuf user_path = STRBUF_INIT;
-       const char *first_slash = strchrnul(path, '/');
        const char *to_copy = path;
 
        if (path == NULL)
                goto return_null;
        if (path[0] == '~') {
+               const char *first_slash = strchrnul(path, '/');
                const char *username = path + 1;
                size_t username_len = first_slash - username;
                if (username_len == 0) {
index 6cb9fd3014a424d11647e48de3b841012ccc2ffe..80430999553d8fda8d095b007bb08c1999bf6993 100644 (file)
@@ -33,7 +33,7 @@ void add_pathspec_matches_against_index(const struct pathspec *pathspec,
                return;
        for (i = 0; i < active_nr; i++) {
                const struct cache_entry *ce = active_cache[i];
-               match_pathspec_depth(pathspec, ce->name, ce_namelen(ce), 0, seen);
+               ce_path_match(ce, pathspec, seen);
        }
 }
 
index 6e804a271ca4c6b38b9769f16ace4fb9bc0b88cd..a59564fb34fbedd4915da2afd7d4b8f1fd40bb49 100644 (file)
@@ -480,8 +480,8 @@ sub refname {
        # It cannot end with a slash /, we'll throw up on this because
        # SVN can't have directories with a slash in their name, either:
        if ($refname =~ m{/$}) {
-               die "ref: '$refname' ends with a trailing slash, this is ",
-                   "not permitted by git nor Subversion\n";
+               die "ref: '$refname' ends with a trailing slash; this is ",
+                   "not permitted by git or Subversion\n";
        }
 
        # It cannot have ASCII control character space, tilde ~, caret ^,
@@ -1191,7 +1191,7 @@ sub do_fetch {
                # we can have a branch that was deleted, then re-added
                # under the same name but copied from another path, in
                # which case we'll have multiple parents (we don't
-               # want to break the original ref, nor lose copypath info):
+               # want to break the original ref or lose copypath info):
                if (my $log_entry = $self->find_parent_branch($paths, $rev)) {
                        push @{$log_entry->{parents}}, $lc;
                        return $log_entry;
index 30daf354655f0b4cc02d08e7ba5af43133a09b95..cf6ffa7581310986b7618da36346dc499a9fb098 100644 (file)
@@ -1,6 +1,6 @@
 package Git::SVN::Migration;
 # these version numbers do NOT correspond to actual version numbers
-# of git nor git-svn.  They are just relative.
+# of git or git-svn.  They are just relative.
 #
 # v0 layout: .git/$id/info/url, refs/heads/$id-HEAD
 #
index 0a838d1656171019c07fe802d615ecaf78412003..3cb9d91baaa5bbd09e1ca55e8754e1c4edb6bd97 100644 (file)
@@ -28,10 +28,10 @@ void packet_buf_write(struct strbuf *buf, const char *fmt, ...) __attribute__((f
  * Read a packetized line into the buffer, which must be at least size bytes
  * long. The return value specifies the number of bytes read into the buffer.
  *
- * If src_buffer is not NULL (and nor is *src_buffer), it should point to a
- * buffer containing the packet data to parse, of at least *src_len bytes.
- * After the function returns, src_buf will be incremented and src_len
- * decremented by the number of bytes consumed.
+ * If src_buffer and *src_buffer are not NULL, it should point to a buffer
+ * containing the packet data to parse, of at least *src_len bytes.  After the
+ * function returns, src_buf will be incremented and src_len decremented by the
+ * number of bytes consumed.
  *
  * If src_buffer (or *src_buffer) is NULL, then data is read from the
  * descriptor "fd".
index e10263f2b2ce90f08ed082022ef16d13f1c7770a..0b9d59e8fa43dca6b580d9436712a7d09f27472b 100644 (file)
--- a/po/fr.po
+++ b/po/fr.po
@@ -1075,7 +1075,7 @@ msgstr "Votre branche est basée sur '%s', mais la branche amont a disparu.\n"
 
 #: remote.c:1875
 msgid "  (use \"git branch --unset-upstream\" to fixup)\n"
-msgstr "  (utilisez \"git branch -unset-upstream\" pour corriger)\n"
+msgstr "  (utilisez \"git branch --unset-upstream\" pour corriger)\n"
 
 #: remote.c:1878
 #, c-format
@@ -3266,7 +3266,7 @@ msgstr "    git branch -d %s\n"
 #: builtin/branch.c:1027
 #, c-format
 msgid "    git branch --set-upstream-to %s\n"
-msgstr "    git branch -set-upstream-to %s\n"
+msgstr "    git branch --set-upstream-to %s\n"
 
 #: builtin/bundle.c:47
 #, c-format
index 8c44ceb2c715936b314fc10a7aae3dfb44172327..968ee25eae13f82fe4f93254d77660456732a5c6 100644 (file)
@@ -3,6 +3,7 @@
  */
 #include "cache.h"
 #include "pathspec.h"
+#include "dir.h"
 
 #ifdef NO_PTHREADS
 static void preload_index(struct index_state *index,
@@ -53,7 +54,7 @@ static void *preload_thread(void *_data)
                        continue;
                if (ce_uptodate(ce))
                        continue;
-               if (!ce_path_match(ce, &p->pathspec))
+               if (!ce_path_match(ce, &p->pathspec, NULL))
                        continue;
                if (threaded_has_symlink_leading_path(&cache, ce->name, ce_namelen(ce)))
                        continue;
index 87db08bd749e74fef0b2372ab71ea98baf57b322..6e266ddf2749ab1b2388f72e3a1101e98fa656cc 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -397,12 +397,18 @@ static const char *show_ident_date(const struct ident_split *ident,
                                   enum date_mode mode)
 {
        unsigned long date = 0;
-       int tz = 0;
+       long tz = 0;
 
        if (ident->date_begin && ident->date_end)
                date = strtoul(ident->date_begin, NULL, 10);
-       if (ident->tz_begin && ident->tz_end)
-               tz = strtol(ident->tz_begin, NULL, 10);
+       if (date_overflows(date))
+               date = 0;
+       else {
+               if (ident->tz_begin && ident->tz_end)
+                       tz = strtol(ident->tz_begin, NULL, 10);
+               if (tz >= INT_MAX || tz <= INT_MIN)
+                       tz = 0;
+       }
        return show_date(date, tz, mode);
 }
 
index 33dd676ccbbd24e0bace49347f1f5d81b5099bcc..4b4effd64b842173d6a06656935436515c755242 100644 (file)
@@ -15,7 +15,8 @@
 #include "strbuf.h"
 #include "varint.h"
 
-static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
+static struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
+                                              unsigned int options);
 
 /* Mask for the name length in ce_flags in the on-disk index */
 
@@ -696,7 +697,7 @@ int add_file_to_index(struct index_state *istate, const char *path, int flags)
 
 struct cache_entry *make_cache_entry(unsigned int mode,
                const unsigned char *sha1, const char *path, int stage,
-               int refresh)
+               unsigned int refresh_options)
 {
        int size, len;
        struct cache_entry *ce;
@@ -716,10 +717,7 @@ struct cache_entry *make_cache_entry(unsigned int mode,
        ce->ce_namelen = len;
        ce->ce_mode = create_ce_mode(mode);
 
-       if (refresh)
-               return refresh_cache_entry(ce, 0);
-
-       return ce;
+       return refresh_cache_entry(ce, refresh_options);
 }
 
 int ce_same_name(const struct cache_entry *a, const struct cache_entry *b)
@@ -728,11 +726,6 @@ int ce_same_name(const struct cache_entry *a, const struct cache_entry *b)
        return ce_namelen(b) == len && !memcmp(a->name, b->name, len);
 }
 
-int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec)
-{
-       return match_pathspec_depth(pathspec, ce->name, ce_namelen(ce), 0, NULL);
-}
-
 /*
  * We fundamentally don't like some paths: we don't want
  * dot or dot-dot anywhere, and for obvious reasons don't
@@ -1029,10 +1022,12 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
        struct stat st;
        struct cache_entry *updated;
        int changed, size;
+       int refresh = options & CE_MATCH_REFRESH;
        int ignore_valid = options & CE_MATCH_IGNORE_VALID;
        int ignore_skip_worktree = options & CE_MATCH_IGNORE_SKIP_WORKTREE;
+       int ignore_missing = options & CE_MATCH_IGNORE_MISSING;
 
-       if (ce_uptodate(ce))
+       if (!refresh || ce_uptodate(ce))
                return ce;
 
        /*
@@ -1050,6 +1045,8 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
        }
 
        if (lstat(ce->name, &st) < 0) {
+               if (ignore_missing && errno == ENOENT)
+                       return ce;
                if (err)
                        *err = errno;
                return NULL;
@@ -1127,7 +1124,9 @@ int refresh_index(struct index_state *istate, unsigned int flags,
        int ignore_submodules = (flags & REFRESH_IGNORE_SUBMODULES) != 0;
        int first = 1;
        int in_porcelain = (flags & REFRESH_IN_PORCELAIN);
-       unsigned int options = really ? CE_MATCH_IGNORE_VALID : 0;
+       unsigned int options = (CE_MATCH_REFRESH |
+                               (really ? CE_MATCH_IGNORE_VALID : 0) |
+                               (not_new ? CE_MATCH_IGNORE_MISSING : 0));
        const char *modified_fmt;
        const char *deleted_fmt;
        const char *typechange_fmt;
@@ -1149,8 +1148,7 @@ int refresh_index(struct index_state *istate, unsigned int flags,
                if (ignore_submodules && S_ISGITLINK(ce->ce_mode))
                        continue;
 
-               if (pathspec &&
-                   !match_pathspec_depth(pathspec, ce->name, ce_namelen(ce), 0, seen))
+               if (pathspec && !ce_path_match(ce, pathspec, seen))
                        filtered = 1;
 
                if (ce_stage(ce)) {
@@ -1176,8 +1174,6 @@ int refresh_index(struct index_state *istate, unsigned int flags,
                if (!new) {
                        const char *fmt;
 
-                       if (not_new && cache_errno == ENOENT)
-                               continue;
                        if (really && cache_errno == EINVAL) {
                                /* If we are doing --really-refresh that
                                 * means the index is not valid anymore.
@@ -1207,9 +1203,10 @@ int refresh_index(struct index_state *istate, unsigned int flags,
        return has_errors;
 }
 
-static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really)
+static struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
+                                              unsigned int options)
 {
-       return refresh_cache_ent(&the_index, ce, really, NULL, NULL);
+       return refresh_cache_ent(&the_index, ce, options, NULL, NULL);
 }
 
 
index e41251ee77af1426dd26d4b13ee61a39cffccdeb..ebed40dcb65df55ac81facbf5df59ddc28451872 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -49,6 +49,7 @@ static int branches_nr;
 
 static struct branch *current_branch;
 static const char *default_remote_name;
+static const char *branch_pushremote_name;
 static const char *pushremote_name;
 static int explicit_default_remote_name;
 
@@ -352,7 +353,7 @@ static int handle_config(const char *key, const char *value, void *cb)
                        }
                } else if (!strcmp(subkey, ".pushremote")) {
                        if (branch == current_branch)
-                               if (git_config_string(&pushremote_name, key, value))
+                               if (git_config_string(&branch_pushremote_name, key, value))
                                        return -1;
                } else if (!strcmp(subkey, ".merge")) {
                        if (!value)
@@ -492,6 +493,10 @@ static void read_config(void)
                        make_branch(head_ref + strlen("refs/heads/"), 0);
        }
        git_config(handle_config, NULL);
+       if (branch_pushremote_name) {
+               free((char *)pushremote_name);
+               pushremote_name = branch_pushremote_name;
+       }
        alias_all_urls();
 }
 
@@ -852,6 +857,32 @@ static int match_name_with_pattern(const char *key, const char *name,
        return ret;
 }
 
+static void query_refspecs_multiple(struct refspec *refs, int ref_count, struct refspec *query, struct string_list *results)
+{
+       int i;
+       int find_src = !query->src;
+
+       if (find_src && !query->dst)
+               error("query_refspecs_multiple: need either src or dst");
+
+       for (i = 0; i < ref_count; i++) {
+               struct refspec *refspec = &refs[i];
+               const char *key = find_src ? refspec->dst : refspec->src;
+               const char *value = find_src ? refspec->src : refspec->dst;
+               const char *needle = find_src ? query->dst : query->src;
+               char **result = find_src ? &query->src : &query->dst;
+
+               if (!refspec->dst)
+                       continue;
+               if (refspec->pattern) {
+                       if (match_name_with_pattern(key, needle, value, result))
+                               string_list_append_nodup(results, *result);
+               } else if (!strcmp(needle, key)) {
+                       string_list_append(results, value);
+               }
+       }
+}
+
 int query_refspecs(struct refspec *refs, int ref_count, struct refspec *query)
 {
        int i;
@@ -1404,7 +1435,7 @@ int match_push_refs(struct ref *src, struct ref **dst,
                                /*
                                 * Remote doesn't have it, and we have no
                                 * explicit pattern, and we don't have
-                                * --all nor --mirror.
+                                * --all or --mirror.
                                 */
                                goto free_name;
 
@@ -1992,25 +2023,37 @@ static int get_stale_heads_cb(const char *refname,
        const unsigned char *sha1, int flags, void *cb_data)
 {
        struct stale_heads_info *info = cb_data;
+       struct string_list matches = STRING_LIST_INIT_DUP;
        struct refspec query;
+       int i, stale = 1;
        memset(&query, 0, sizeof(struct refspec));
        query.dst = (char *)refname;
 
-       if (query_refspecs(info->refs, info->ref_count, &query))
-               return 0; /* No matches */
+       query_refspecs_multiple(info->refs, info->ref_count, &query, &matches);
+       if (matches.nr == 0)
+               goto clean_exit; /* No matches */
 
        /*
         * If we did find a suitable refspec and it's not a symref and
         * it's not in the list of refs that currently exist in that
-        * remote we consider it to be stale.
+        * remote, we consider it to be stale. In order to deal with
+        * overlapping refspecs, we need to go over all of the
+        * matching refs.
         */
-       if (!((flags & REF_ISSYMREF) ||
-             string_list_has_string(info->ref_names, query.src))) {
+       if (flags & REF_ISSYMREF)
+               goto clean_exit;
+
+       for (i = 0; stale && i < matches.nr; i++)
+               if (string_list_has_string(info->ref_names, matches.items[i].string))
+                       stale = 0;
+
+       if (stale) {
                struct ref *ref = make_linked_ref(refname, &info->stale_refs_tail);
                hashcpy(ref->new_sha1, sha1);
        }
 
-       free(query.src);
+clean_exit:
+       string_list_clear(&matches, 0);
        return 0;
 }
 
index 1f2d21a72f56a68a7f9307bfd9092087687cffae..d55aa8a01b4a4f200f24972795f2887644a06d43 100644 (file)
--- a/rerere.c
+++ b/rerere.c
@@ -672,8 +672,8 @@ int rerere_forget(struct pathspec *pathspec)
        find_conflict(&conflict);
        for (i = 0; i < conflict.nr; i++) {
                struct string_list_item *it = &conflict.items[i];
-               if (!match_pathspec_depth(pathspec, it->string, strlen(it->string),
-                                         0, NULL))
+               if (!match_pathspec(pathspec, it->string,
+                                   strlen(it->string), 0, NULL, 0))
                        continue;
                rerere_forget_one_path(it->string, &merge_rr);
        }
index c09b00664e6892c84424bb4984152883460d3df6..67d1543141bf33b7a44e7f948e9750d35ebf420b 100644 (file)
@@ -182,7 +182,7 @@ void unmerge_index(struct index_state *istate, const struct pathspec *pathspec)
 
        for (i = 0; i < istate->cache_nr; i++) {
                const struct cache_entry *ce = istate->cache[i];
-               if (!match_pathspec_depth(pathspec, ce->name, ce_namelen(ce), 0, NULL))
+               if (!ce_path_match(ce, pathspec, NULL))
                        continue;
                i = unmerge_index_entry_at(istate, i);
        }
index a0df72f32c100a68e5d99b5b00e597d43f3802a5..f40ccf14269a3325f4f3069ce931bb73e1d1f27e 100644 (file)
@@ -16,6 +16,7 @@
 #include "line-log.h"
 #include "mailmap.h"
 #include "commit-slab.h"
+#include "dir.h"
 
 volatile show_early_output_fn_t show_early_output;
 
@@ -1400,7 +1401,7 @@ static void prepare_show_merge(struct rev_info *revs)
                const struct cache_entry *ce = active_cache[i];
                if (!ce_stage(ce))
                        continue;
-               if (ce_path_match(ce, &revs->prune_data)) {
+               if (ce_path_match(ce, &revs->prune_data, NULL)) {
                        prune_num++;
                        prune = xrealloc(prune, sizeof(*prune) * prune_num);
                        prune[prune_num-2] = ce->name;
index 3914d9c5117f29651b56772da143f0a226494a62..75abc478c6da75471e5fdbb55c74efdfcf3ad160 100644 (file)
@@ -760,13 +760,11 @@ char *find_hook(const char *name)
        return path;
 }
 
-int run_hook(const char *index_file, const char *name, ...)
+int run_hook_ve(const char *const *env, const char *name, va_list args)
 {
        struct child_process hook;
        struct argv_array argv = ARGV_ARRAY_INIT;
-       const char *p, *env[2];
-       char index[PATH_MAX];
-       va_list args;
+       const char *p;
        int ret;
 
        p = find_hook(name);
@@ -775,23 +773,45 @@ int run_hook(const char *index_file, const char *name, ...)
 
        argv_array_push(&argv, p);
 
-       va_start(args, name);
        while ((p = va_arg(args, const char *)))
                argv_array_push(&argv, p);
-       va_end(args);
 
        memset(&hook, 0, sizeof(hook));
        hook.argv = argv.argv;
+       hook.env = env;
        hook.no_stdin = 1;
        hook.stdout_to_stderr = 1;
-       if (index_file) {
-               snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
-               env[0] = index;
-               env[1] = NULL;
-               hook.env = env;
-       }
 
        ret = run_command(&hook);
        argv_array_clear(&argv);
        return ret;
 }
+
+int run_hook_le(const char *const *env, const char *name, ...)
+{
+       va_list args;
+       int ret;
+
+       va_start(args, name);
+       ret = run_hook_ve(env, name, args);
+       va_end(args);
+
+       return ret;
+}
+
+int run_hook_with_custom_index(const char *index_file, const char *name, ...)
+{
+       const char *hook_env[3] =  { NULL };
+       char index[PATH_MAX];
+       va_list args;
+       int ret;
+
+       snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
+       hook_env[0] = index;
+
+       va_start(args, name);
+       ret = run_hook_ve(hook_env, name, args);
+       va_end(args);
+
+       return ret;
+}
index 6b985afd07a5b58ecadad8859ae90b3430ccb4c2..3653bfa6e123ca8497571a2ca1c47200c1b544a2 100644 (file)
@@ -47,7 +47,12 @@ int run_command(struct child_process *);
 
 extern char *find_hook(const char *name);
 LAST_ARG_MUST_BE_NULL
-extern int run_hook(const char *index_file, const char *name, ...);
+extern int run_hook_le(const char *const *env, const char *name, ...);
+extern int run_hook_ve(const char *const *env, const char *name, va_list args);
+
+LAST_ARG_MUST_BE_NULL
+__attribute__((deprecated))
+extern int run_hook_with_custom_index(const char *index_file, const char *name, ...);
 
 #define RUN_COMMAND_NO_STDIN 1
 #define RUN_GIT_CMD         2  /*If this is to be git sub-command */
index 6e8c05d10825ee93d8248f749d4bef513d772be4..77dbb56946771d631ec544dc1958fcff9215c117 100644 (file)
@@ -787,7 +787,7 @@ void close_pack_index(struct packed_git *p)
  * contain the same set of objects as an existing one.  In that case
  * the resulting file might be different even if its name would be the
  * same.  It is best to close any reference to the old pack before it is
- * replaced on disk.  Of course no index pointers nor windows for given pack
+ * replaced on disk.  Of course no index pointers or windows for given pack
  * must subsist at this point.  If ever objects from this pack are requested
  * again, the new version of the pack will be reinitialized through
  * reprepare_packed_git().
@@ -1123,7 +1123,7 @@ static void report_helper(const struct string_list *list,
        const char *msg;
        switch (seen_bits) {
        case 0:
-               msg = "no corresponding .idx nor .pack";
+               msg = "no corresponding .idx or .pack";
                break;
        case 1:
                msg = "no corresponding .idx";
index bbc98b55c07969474b0afb01d9c4da70455f1903..0b267b64117c5f1d2df662e3d413418d575a94bd 100644 (file)
--- a/shallow.c
+++ b/shallow.c
@@ -8,9 +8,10 @@
 #include "diff.h"
 #include "revision.h"
 #include "commit-slab.h"
+#include "sigchain.h"
 
 static int is_shallow = -1;
-static struct stat shallow_stat;
+static struct stat_validity shallow_stat;
 static char *alternate_shallow_file;
 
 void set_alternate_shallow_file(const char *path, int override)
@@ -52,12 +53,12 @@ int is_repository_shallow(void)
         * shallow file should be used. We could just open it and it
         * will likely fail. But let's do an explicit check instead.
         */
-       if (!*path ||
-           stat(path, &shallow_stat) ||
-           (fp = fopen(path, "r")) == NULL) {
+       if (!*path || (fp = fopen(path, "r")) == NULL) {
+               stat_validity_clear(&shallow_stat);
                is_shallow = 0;
                return is_shallow;
        }
+       stat_validity_update(&shallow_stat, fileno(fp));
        is_shallow = 1;
 
        while (fgets(buf, sizeof(buf), fp)) {
@@ -137,21 +138,11 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
 
 void check_shallow_file_for_update(void)
 {
-       struct stat st;
-
-       if (!is_shallow)
-               return;
-       else if (is_shallow == -1)
+       if (is_shallow == -1)
                die("BUG: shallow must be initialized by now");
 
-       if (stat(git_path("shallow"), &st))
-               die("shallow file was removed during fetch");
-       else if (st.st_mtime != shallow_stat.st_mtime
-#ifdef USE_NSEC
-                || ST_MTIME_NSEC(st) != ST_MTIME_NSEC(shallow_stat)
-#endif
-                  )
-               die("shallow file was changed during fetch");
+       if (!stat_validity_check(&shallow_stat, git_path("shallow")))
+               die("shallow file has changed since we read it");
 }
 
 #define SEEN_ONLY 1
@@ -216,27 +207,53 @@ int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
        return write_shallow_commits_1(out, use_pack_protocol, extra, 0);
 }
 
-char *setup_temporary_shallow(const struct sha1_array *extra)
+static struct strbuf temporary_shallow = STRBUF_INIT;
+
+static void remove_temporary_shallow(void)
+{
+       if (temporary_shallow.len) {
+               unlink_or_warn(temporary_shallow.buf);
+               strbuf_reset(&temporary_shallow);
+       }
+}
+
+static void remove_temporary_shallow_on_signal(int signo)
+{
+       remove_temporary_shallow();
+       sigchain_pop(signo);
+       raise(signo);
+}
+
+const char *setup_temporary_shallow(const struct sha1_array *extra)
 {
+       static int installed_handler;
        struct strbuf sb = STRBUF_INIT;
        int fd;
 
+       if (temporary_shallow.len)
+               die("BUG: attempt to create two temporary shallow files");
+
        if (write_shallow_commits(&sb, 0, extra)) {
-               struct strbuf path = STRBUF_INIT;
-               strbuf_addstr(&path, git_path("shallow_XXXXXX"));
-               fd = xmkstemp(path.buf);
+               strbuf_addstr(&temporary_shallow, git_path("shallow_XXXXXX"));
+               fd = xmkstemp(temporary_shallow.buf);
+
+               if (!installed_handler) {
+                       atexit(remove_temporary_shallow);
+                       sigchain_push_common(remove_temporary_shallow_on_signal);
+               }
+
                if (write_in_full(fd, sb.buf, sb.len) != sb.len)
                        die_errno("failed to write to %s",
-                                 path.buf);
+                                 temporary_shallow.buf);
                close(fd);
                strbuf_release(&sb);
-               return strbuf_detach(&path, NULL);
+               return temporary_shallow.buf;
        }
        /*
         * is_repository_shallow() sees empty string as "no shallow
         * file".
         */
-       return xstrdup("");
+       return temporary_shallow.buf;
 }
 
 void setup_alternate_shallow(struct lock_file *shallow_lock,
@@ -246,9 +263,9 @@ void setup_alternate_shallow(struct lock_file *shallow_lock,
        struct strbuf sb = STRBUF_INIT;
        int fd;
 
-       check_shallow_file_for_update();
        fd = hold_lock_file_for_update(shallow_lock, git_path("shallow"),
                                       LOCK_DIE_ON_ERROR);
+       check_shallow_file_for_update();
        if (write_shallow_commits(&sb, 0, extra)) {
                if (write_in_full(fd, sb.buf, sb.len) != sb.len)
                        die_errno("failed to write to %s",
@@ -293,9 +310,9 @@ void prune_shallow(int show_only)
                strbuf_release(&sb);
                return;
        }
-       check_shallow_file_for_update();
        fd = hold_lock_file_for_update(&shallow_lock, git_path("shallow"),
                                       LOCK_DIE_ON_ERROR);
+       check_shallow_file_for_update();
        if (write_shallow_commits_1(&sb, 0, NULL, SEEN_ONLY)) {
                if (write_in_full(fd, sb.buf, sb.len) != sb.len)
                        die_errno("failed to write to %s",
index bfdff2a8c93091c8e2db8e03a74eae5c5a53991c..b43162ea2a932deb521381863900279c8d87f2b1 100644 (file)
@@ -64,7 +64,7 @@ case $(uname) in
 esac
 
 LIB_HTTPD_PATH=${LIB_HTTPD_PATH-"$DEFAULT_HTTPD_PATH"}
-LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'8111'}
+LIB_HTTPD_PORT=${LIB_HTTPD_PORT-${this_test#t}}
 
 TEST_PATH="$TEST_DIRECTORY"/lib-httpd
 HTTPD_ROOT_PATH="$PWD"/httpd
index 9a2dca506a8d6c15f52e6ded3aa22a0f08f507a1..51845491bb42ee72a1f7ec33c504e65c5bf8b248 100644 (file)
@@ -1,6 +1,20 @@
 # Helpers for terminal output tests.
 
-test_expect_success PERL 'set up terminal for tests' '
+# Catch tests which should depend on TTY but forgot to. There's no need
+# to aditionally check that the TTY prereq is set here.  If the test declared
+# it and we are running the test, then it must have been set.
+test_terminal () {
+       if ! test_declared_prereq TTY
+       then
+               echo >&4 "test_terminal: need to declare TTY prerequisite"
+               return 127
+       fi
+       perl "$TEST_DIRECTORY"/test-terminal.perl "$@"
+}
+
+test_lazy_prereq TTY '
+       test_have_prereq PERL &&
+
        # Reading from the pty master seems to get stuck _sometimes_
        # on Mac OS X 10.5.0, using Perl 5.10.0 or 5.8.9.
        #
@@ -15,21 +29,8 @@ test_expect_success PERL 'set up terminal for tests' '
        # After 2000 iterations or so it hangs.
        # https://rt.cpan.org/Ticket/Display.html?id=65692
        #
-       if test "$(uname -s)" = Darwin
-       then
-               :
-       elif
-               perl "$TEST_DIRECTORY"/test-terminal.perl \
-                       sh -c "test -t 1 && test -t 2"
-       then
-               test_set_prereq TTY &&
-               test_terminal () {
-                       if ! test_declared_prereq TTY
-                       then
-                               echo >&4 "test_terminal: need to declare TTY prerequisite"
-                               return 127
-                       fi
-                       perl "$TEST_DIRECTORY"/test-terminal.perl "$@"
-               }
-       fi
+       test "$(uname -s)" != Darwin &&
+
+       perl "$TEST_DIRECTORY"/test-terminal.perl \
+               sh -c "test -t 1 && test -t 2"
 '
index b9d79476e20b4ddf0f9e85c672df2061fb910f9d..f0fbb425545019a6275a347a5826f6ba2977d394 100755 (executable)
@@ -243,40 +243,58 @@ EOF
        test_line_count = 0 err
 '
 
+test_expect_success 'using --git-dir and --work-tree' '
+       mkdir unreal real &&
+       git init real &&
+       echo "file test=in-real" >real/.gitattributes &&
+       (
+               cd unreal &&
+               attr_check file in-real "--git-dir ../real/.git --work-tree ../real"
+       )
+'
+
 test_expect_success 'setup bare' '
-       git clone --bare . bare.git &&
-       cd bare.git
+       git clone --bare . bare.git
 '
 
 test_expect_success 'bare repository: check that .gitattribute is ignored' '
        (
-               echo "f test=f"
-               echo "a/i test=a/i"
-       ) >.gitattributes &&
-       attr_check f unspecified &&
-       attr_check a/f unspecified &&
-       attr_check a/c/f unspecified &&
-       attr_check a/i unspecified &&
-       attr_check subdir/a/i unspecified
+               cd bare.git &&
+               (
+                       echo "f test=f"
+                       echo "a/i test=a/i"
+               ) >.gitattributes &&
+               attr_check f unspecified &&
+               attr_check a/f unspecified &&
+               attr_check a/c/f unspecified &&
+               attr_check a/i unspecified &&
+               attr_check subdir/a/i unspecified
+       )
 '
 
 test_expect_success 'bare repository: check that --cached honors index' '
-       GIT_INDEX_FILE=../.git/index \
-       git check-attr --cached --stdin --all <../stdin-all |
-       sort >actual &&
-       test_cmp ../specified-all actual
+       (
+               cd bare.git &&
+               GIT_INDEX_FILE=../.git/index \
+               git check-attr --cached --stdin --all <../stdin-all |
+               sort >actual &&
+               test_cmp ../specified-all actual
+       )
 '
 
 test_expect_success 'bare repository: test info/attributes' '
        (
-               echo "f test=f"
-               echo "a/i test=a/i"
-       ) >info/attributes &&
-       attr_check f f &&
-       attr_check a/f f &&
-       attr_check a/c/f f &&
-       attr_check a/i a/i &&
-       attr_check subdir/a/i unspecified
+               cd bare.git &&
+               (
+                       echo "f test=f"
+                       echo "a/i test=a/i"
+               ) >info/attributes &&
+               attr_check f f &&
+               attr_check a/f f &&
+               attr_check a/c/f f &&
+               attr_check a/i a/i &&
+               attr_check subdir/a/i unspecified
+       )
 '
 
 test_done
index acaab07fac672e4b1b74161b58baf1f5e153840e..3a24abf5496c76862e772907442dc24bdcb4d78a 100755 (executable)
@@ -18,7 +18,7 @@ In the test, these paths are used:
         frotz   - not in H added in M
         nitfol  - in H, stays in M unmodified
         rezrov  - in H, deleted in M
-        yomin   - not in H nor M
+       yomin   - not in H or M
 '
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-read-tree.sh
index 6ffd82fe321cd3154d6f193c21198218e762f1b2..e130c528fe5a0115c99b1203cfe9dced046cece3 100755 (executable)
@@ -820,7 +820,18 @@ test_expect_success 'stdin -z update ref fails with bad old value' '
        test_must_fail git rev-parse --verify -q $c
 '
 
+test_expect_success 'stdin -z create ref fails when ref exists' '
+       git update-ref $c $m &&
+       git rev-parse "$c" >expect &&
+       printf $F "create $c" "$m~1" >stdin &&
+       test_must_fail git update-ref -z --stdin <stdin 2>err &&
+       grep "fatal: Cannot lock the ref '"'"'$c'"'"'" err &&
+       git rev-parse "$c" >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'stdin -z create ref fails with bad new value' '
+       git update-ref -d "$c" &&
        printf $F "create $c" "does-not-exist" >stdin &&
        test_must_fail git update-ref -z --stdin <stdin 2>err &&
        grep "fatal: invalid new value for ref $c: does-not-exist" err &&
index d730734fde8e4de69fdf2662915bc67342198fc8..8c739c96135fe942d7e76236eb34429be93937a8 100755 (executable)
@@ -142,6 +142,20 @@ test_expect_success '> in name is reported' '
        grep "error in commit $new" out
 '
 
+# date is 2^64 + 1
+test_expect_success 'integer overflow in timestamps is reported' '
+       git cat-file commit HEAD >basis &&
+       sed "s/^\\(author .*>\\) [0-9]*/\\1 18446744073709551617/" \
+               <basis >bad-timestamp &&
+       new=$(git hash-object -t commit -w --stdin <bad-timestamp) &&
+       test_when_finished "remove_object $new" &&
+       git update-ref refs/heads/bogus "$new" &&
+       test_when_finished "git update-ref -d refs/heads/bogus" &&
+       git fsck 2>out &&
+       cat out &&
+       grep "error in commit $new.*integer overflow" out
+'
+
 test_expect_success 'tag pointing to nonexistent' '
        cat >invalid-tag <<-\EOF &&
        object ffffffffffffffffffffffffffffffffffffffff
index 2f96100a5f655bbea859bf596ff9835c9abb11a2..82e18548c39817dec496766d2c8d500668fc4f76 100755 (executable)
@@ -257,6 +257,7 @@ test_expect_success 'setup 8' '
        git add e &&
        test_tick &&
        git commit -m "rename a->e" &&
+       c7=$(git rev-parse --verify HEAD) &&
        git checkout rename-ln &&
        git mv a e &&
        test_ln_s_add e a &&
@@ -517,6 +518,52 @@ test_expect_success 'reset and bind merge' '
 
 '
 
+test_expect_success 'merge-recursive w/ empty work tree - ours has rename' '
+       (
+               GIT_WORK_TREE="$PWD/ours-has-rename-work" &&
+               export GIT_WORK_TREE &&
+               GIT_INDEX_FILE="$PWD/ours-has-rename-index" &&
+               export GIT_INDEX_FILE &&
+               mkdir "$GIT_WORK_TREE" &&
+               git read-tree -i -m $c7 &&
+               git update-index --ignore-missing --refresh &&
+               git merge-recursive $c0 -- $c7 $c3 &&
+               git ls-files -s >actual-files
+       ) 2>actual-err &&
+       >expected-err &&
+       cat >expected-files <<-EOF &&
+       100644 $o3 0    b/c
+       100644 $o0 0    c
+       100644 $o0 0    d/e
+       100644 $o0 0    e
+       EOF
+       test_cmp expected-files actual-files &&
+       test_cmp expected-err actual-err
+'
+
+test_expect_success 'merge-recursive w/ empty work tree - theirs has rename' '
+       (
+               GIT_WORK_TREE="$PWD/theirs-has-rename-work" &&
+               export GIT_WORK_TREE &&
+               GIT_INDEX_FILE="$PWD/theirs-has-rename-index" &&
+               export GIT_INDEX_FILE &&
+               mkdir "$GIT_WORK_TREE" &&
+               git read-tree -i -m $c3 &&
+               git update-index --ignore-missing --refresh &&
+               git merge-recursive $c0 -- $c3 $c7 &&
+               git ls-files -s >actual-files
+       ) 2>actual-err &&
+       >expected-err &&
+       cat >expected-files <<-EOF &&
+       100644 $o3 0    b/c
+       100644 $o0 0    c
+       100644 $o0 0    d/e
+       100644 $o0 0    e
+       EOF
+       test_cmp expected-files actual-files &&
+       test_cmp expected-err actual-err
+'
+
 test_expect_success 'merge removes empty directories' '
 
        git reset --hard master &&
index 77d7f4946fb51a766399549e3c7364033d7668f0..7d2c6e13a2a7f5d8e9e863d83e6b7b716810c970 100755 (executable)
@@ -66,7 +66,7 @@ test_expect_success \
 
 # tree has COPYING and rezrov.  work tree has the same COPYING and
 # copy-edited COPYING.1, and unchanged rezrov.  We should not say
-# anything about rezrov nor COPYING, since the revised again diff-raw
+# anything about rezrov or COPYING, since the revised again diff-raw
 # nows how to say Copy.
 
 test_expect_success \
index f22c8e3dbaee8882160b6132160fcc3ccd7db057..57c094fdcea160a7816680d66efac9c05dd57cc8 100755 (executable)
@@ -73,7 +73,7 @@ test_expect_success \
 
 # tree has COPYING and rezrov.  work tree has the same COPYING and
 # copy-edited COPYING.1, and unchanged rezrov.  We should not say
-# anything about rezrov nor COPYING, since the revised again diff-raw
+# anything about rezrov or COPYING, since the revised again diff-raw
 # nows how to say Copy.
 
 test_expect_success \
index 9f5659f7fe4df23d805e6c38264a1ebf38fc2538..2bb973655bf043cc43292764ffd68becda25aa2e 100755 (executable)
@@ -140,4 +140,10 @@ test_expect_success 'diff multiple wildcard pathspecs' '
        test_cmp expect actual
 '
 
+test_expect_success 'diff-cache ignores trailing slash on submodule path' '
+       git diff --name-only HEAD^ submod >expect &&
+       git diff --name-only HEAD^ submod/ >actual &&
+       test_cmp expect actual
+'
+
 test_done
index bcae35ac1c93aaf79032db5ee09fd2d3400101f5..044620186d135fe5caeb9376665305af1c8acbe5 100755 (executable)
@@ -226,12 +226,13 @@ keep_only_cr () {
 }
 
 test_expect_success 'external diff with autocrlf = true' '
-       git config core.autocrlf true &&
+       test_config core.autocrlf true &&
        GIT_EXTERNAL_DIFF=./fake-diff.sh git diff &&
        test $(wc -l < crlfed.txt) = $(cat crlfed.txt | keep_only_cr | wc -c)
 '
 
 test_expect_success 'diff --cached' '
+       test_config core.autocrlf true &&
        git add file &&
        git update-index --assume-unchanged file &&
        echo second >file &&
@@ -239,4 +240,31 @@ test_expect_success 'diff --cached' '
        test_cmp "$TEST_DIRECTORY"/t4020/diff.NUL actual
 '
 
+test_expect_success 'clean up crlf leftovers' '
+       git update-index --no-assume-unchanged file &&
+       rm -f file* &&
+       git reset --hard
+'
+
+test_expect_success 'submodule diff' '
+       git init sub &&
+       ( cd sub && test_commit sub1 ) &&
+       git add sub &&
+       test_tick &&
+       git commit -m "add submodule" &&
+       ( cd sub && test_commit sub2 ) &&
+       write_script gather_pre_post.sh <<-\EOF &&
+       echo "$1 $4" # path, mode
+       cat "$2" # old file
+       cat "$5" # new file
+       EOF
+       GIT_EXTERNAL_DIFF=./gather_pre_post.sh git diff >actual &&
+       cat >expected <<-EOF &&
+       sub 160000
+       Subproject commit $(git rev-parse HEAD:sub)
+       Subproject commit $(cd sub && git rev-parse HEAD)
+       EOF
+       test_cmp expected actual
+'
+
 test_done
index 231412d1008e45e1d788660930cab708d3912ed4..e8ae2a03fdcf5ac57dc0e5bcacd40501960bce1c 100755 (executable)
@@ -148,4 +148,10 @@ test_expect_success 'git diff --ignore-all-space, both files outside repo' '
        )
 '
 
+test_expect_success 'git diff --quiet ignores stat-change only entries' '
+       test-chmtime +10 a &&
+       echo modified >>b &&
+       test_expect_code 1 git diff --quiet
+'
+
 test_done
index 93c7c366cfeffa46cc72665f6ce676bd37c3c2fe..58b792bf20a1cd64435fca0b3d24b2417303f819 100755 (executable)
@@ -44,4 +44,47 @@ test_expect_success 'git log --format with broken author email' '
        test_cmp expect.err actual.err
 '
 
+munge_author_date () {
+       git cat-file commit "$1" >commit.orig &&
+       sed "s/^\(author .*>\) [0-9]*/\1 $2/" <commit.orig >commit.munge &&
+       git hash-object -w -t commit commit.munge
+}
+
+test_expect_success 'unparsable dates produce sentinel value' '
+       commit=$(munge_author_date HEAD totally_bogus) &&
+       echo "Date:   Thu Jan 1 00:00:00 1970 +0000" >expect &&
+       git log -1 $commit >actual.full &&
+       grep Date <actual.full >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'unparsable dates produce sentinel value (%ad)' '
+       commit=$(munge_author_date HEAD totally_bogus) &&
+       echo >expect &&
+       git log -1 --format=%ad $commit >actual
+       test_cmp expect actual
+'
+
+# date is 2^64 + 1
+test_expect_success 'date parser recognizes integer overflow' '
+       commit=$(munge_author_date HEAD 18446744073709551617) &&
+       echo "Thu Jan 1 00:00:00 1970 +0000" >expect &&
+       git log -1 --format=%ad $commit >actual &&
+       test_cmp expect actual
+'
+
+# date is 2^64 - 2
+test_expect_success 'date parser recognizes time_t overflow' '
+       commit=$(munge_author_date HEAD 18446744073709551614) &&
+       echo "Thu Jan 1 00:00:00 1970 +0000" >expect &&
+       git log -1 --format=%ad $commit >actual &&
+       test_cmp expect actual
+'
+
+# date is within 2^63-1, but enough to choke glibc's gmtime
+test_expect_success 'absurdly far-in-future date' '
+       commit=$(munge_author_date HEAD 999999999999999999) &&
+       git log -1 --format=%ad $commit
+'
+
 test_done
index 66c9a41739e5d75633a239c55fd516341f8a98e3..377d3d3899737fec47f34f0db28ac876eb146af8 100755 (executable)
@@ -213,7 +213,7 @@ test_expect_success 'garbage report in count-objects -v' '
 warning: garbage found: .git/objects/pack/fake.bar
 warning: garbage found: .git/objects/pack/foo
 warning: garbage found: .git/objects/pack/foo.bar
-warning: no corresponding .idx nor .pack: .git/objects/pack/fake2.keep
+warning: no corresponding .idx or .pack: .git/objects/pack/fake2.keep
 warning: no corresponding .idx: .git/objects/pack/foo.keep
 warning: no corresponding .idx: .git/objects/pack/foo.pack
 warning: no corresponding .pack: .git/objects/pack/fake3.idx
index ab28594c62dd7cddc69d3afdb075b48c34091c45..b212f83db7514a0d687cf9884e123a9b8dad7ae0 100755 (executable)
@@ -113,6 +113,26 @@ test_expect_success 'fetch --prune with a namespace keeps other namespaces' '
        git rev-parse origin/master
 '
 
+test_expect_success 'fetch --prune handles overlapping refspecs' '
+       cd "$D" &&
+       git update-ref refs/pull/42/head master &&
+       git clone . prune-overlapping &&
+       cd prune-overlapping &&
+       git config --add remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
+
+       git fetch --prune origin &&
+       git rev-parse origin/master &&
+       git rev-parse origin/pr/42 &&
+
+       git config --unset-all remote.origin.fetch
+       git config remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
+       git config --add remote.origin.fetch refs/heads/*:refs/remotes/origin/* &&
+
+       git fetch --prune origin &&
+       git rev-parse origin/master &&
+       git rev-parse origin/pr/42
+'
+
 test_expect_success 'fetch --prune --tags prunes branches but not tags' '
        cd "$D" &&
        git clone . prune-tags &&
index 926e7f6b979d4d1c69ecc9d280cd6de365627012..67e0ab346204b437c8e3585d948c2c61858e1928 100755 (executable)
@@ -536,6 +536,19 @@ test_expect_success 'push with config branch.*.pushremote' '
        check_push_result down_repo $the_commit heads/master
 '
 
+test_expect_success 'branch.*.pushremote config order is irrelevant' '
+       mk_test one_repo heads/master &&
+       mk_test two_repo heads/master &&
+       test_config remote.one.url one_repo &&
+       test_config remote.two.url two_repo &&
+       test_config branch.master.pushremote two_repo &&
+       test_config remote.pushdefault one_repo &&
+       test_config push.default matching &&
+       git push &&
+       check_push_result one_repo $the_first_commit heads/master &&
+       check_push_result two_repo $the_commit heads/master
+'
+
 test_expect_success 'push with dry-run' '
 
        mk_test testrepo heads/master &&
index b0fa7387cbe082a72e26590be8e621c922e91eba..3ae9092f5c2511e075c1bf6c215ea773f738f1f9 100755 (executable)
@@ -173,32 +173,4 @@ EOF
        )
 '
 
-if test -n "$NO_CURL" -o -z "$GIT_TEST_HTTPD"; then
-       say 'skipping remaining tests, git built without http support'
-       test_done
-fi
-
-LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5537'}
-. "$TEST_DIRECTORY"/lib-httpd.sh
-start_httpd
-
-test_expect_success 'clone http repository' '
-       git clone --bare --no-local shallow "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
-       git clone $HTTPD_URL/smart/repo.git clone &&
-       (
-       cd clone &&
-       git fsck &&
-       git log --format=%s origin/master >actual &&
-       cat <<EOF >expect &&
-7
-6
-5
-4
-3
-EOF
-       test_cmp expect actual
-       )
-'
-
-stop_httpd
 test_done
index 0a6e40f144a767cba03818cffca8b8b2aa6a16e2..8e54ac57462987567b11623d502ffc68fca3d9a0 100755 (executable)
@@ -126,7 +126,6 @@ if test -n "$NO_CURL" -o -z "$GIT_TEST_HTTPD"; then
        test_done
 fi
 
-LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5537'}
 . "$TEST_DIRECTORY"/lib-httpd.sh
 start_httpd
 
diff --git a/t/t5539-fetch-http-shallow.sh b/t/t5539-fetch-http-shallow.sh
new file mode 100755 (executable)
index 0000000..94553e1
--- /dev/null
@@ -0,0 +1,82 @@
+#!/bin/sh
+
+test_description='fetch/clone from a shallow clone over http'
+
+. ./test-lib.sh
+
+if test -n "$NO_CURL"; then
+       skip_all='skipping test, git built without http support'
+       test_done
+fi
+
+. "$TEST_DIRECTORY"/lib-httpd.sh
+start_httpd
+
+commit() {
+       echo "$1" >tracked &&
+       git add tracked &&
+       git commit -m "$1"
+}
+
+test_expect_success 'setup shallow clone' '
+       commit 1 &&
+       commit 2 &&
+       commit 3 &&
+       commit 4 &&
+       commit 5 &&
+       commit 6 &&
+       commit 7 &&
+       git clone --no-local --depth=5 .git shallow &&
+       git config --global transfer.fsckObjects true
+'
+
+test_expect_success 'clone http repository' '
+       git clone --bare --no-local shallow "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+       git clone $HTTPD_URL/smart/repo.git clone &&
+       (
+       cd clone &&
+       git fsck &&
+       git log --format=%s origin/master >actual &&
+       cat <<EOF >expect &&
+7
+6
+5
+4
+3
+EOF
+       test_cmp expect actual
+       )
+'
+
+# This test is tricky. We need large enough "have"s that fetch-pack
+# will put pkt-flush in between. Then we need a "have" the server
+# does not have, it'll send "ACK %s ready"
+test_expect_success 'no shallow lines after receiving ACK ready' '
+       (
+               cd shallow &&
+               for i in $(test_seq 15)
+               do
+                       git checkout --orphan unrelated$i &&
+                       test_commit unrelated$i &&
+                       git push -q "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
+                               refs/heads/unrelated$i:refs/heads/unrelated$i &&
+                       git push -q ../clone/.git \
+                               refs/heads/unrelated$i:refs/heads/unrelated$i ||
+                       exit 1
+               done &&
+               git checkout master &&
+               test_commit new &&
+               git push  "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" master
+       ) &&
+       (
+               cd clone &&
+               git checkout --orphan newnew &&
+               test_commit new-too &&
+               GIT_TRACE_PACKET="$TRASH_DIRECTORY/trace" git fetch --depth=2 &&
+               grep "fetch-pack< ACK .* ready" ../trace &&
+               ! grep "fetch-pack> done" ../trace
+       )
+'
+
+stop_httpd
+test_done
diff --git a/t/t5540-http-push-webdav.sh b/t/t5540-http-push-webdav.sh
new file mode 100755 (executable)
index 0000000..8d7b3c5
--- /dev/null
@@ -0,0 +1,181 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at>
+#
+
+test_description='test WebDAV http-push
+
+This test runs various sanity checks on http-push.'
+
+. ./test-lib.sh
+
+if git http-push > /dev/null 2>&1 || [ $? -eq 128 ]
+then
+       skip_all="skipping test, USE_CURL_MULTI is not defined"
+       test_done
+fi
+
+LIB_HTTPD_DAV=t
+. "$TEST_DIRECTORY"/lib-httpd.sh
+ROOT_PATH="$PWD"
+start_httpd
+
+test_expect_success 'setup remote repository' '
+       cd "$ROOT_PATH" &&
+       mkdir test_repo &&
+       cd test_repo &&
+       git init &&
+       : >path1 &&
+       git add path1 &&
+       test_tick &&
+       git commit -m initial &&
+       cd - &&
+       git clone --bare test_repo test_repo.git &&
+       cd test_repo.git &&
+       git --bare update-server-info &&
+       mv hooks/post-update.sample hooks/post-update &&
+       ORIG_HEAD=$(git rev-parse --verify HEAD) &&
+       cd - &&
+       mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH"
+'
+
+test_expect_success 'create password-protected repository' '
+       mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb" &&
+       cp -Rf "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
+              "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/test_repo.git"
+'
+
+setup_askpass_helper
+
+test_expect_success 'clone remote repository' '
+       cd "$ROOT_PATH" &&
+       git clone $HTTPD_URL/dumb/test_repo.git test_repo_clone
+'
+
+test_expect_success 'push to remote repository with packed refs' '
+       cd "$ROOT_PATH"/test_repo_clone &&
+       : >path2 &&
+       git add path2 &&
+       test_tick &&
+       git commit -m path2 &&
+       HEAD=$(git rev-parse --verify HEAD) &&
+       git push &&
+       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
+        test $HEAD = $(git rev-parse --verify HEAD))
+'
+
+test_expect_success 'push already up-to-date' '
+       git push
+'
+
+test_expect_success 'push to remote repository with unpacked refs' '
+       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
+        rm packed-refs &&
+        git update-ref refs/heads/master $ORIG_HEAD &&
+        git --bare update-server-info) &&
+       git push &&
+       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
+        test $HEAD = $(git rev-parse --verify HEAD))
+'
+
+test_expect_success 'http-push fetches unpacked objects' '
+       cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
+               "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo_unpacked.git &&
+
+       git clone $HTTPD_URL/dumb/test_repo_unpacked.git \
+               "$ROOT_PATH"/fetch_unpacked &&
+
+       # By reset, we force git to retrieve the object
+       (cd "$ROOT_PATH"/fetch_unpacked &&
+        git reset --hard HEAD^ &&
+        git remote rm origin &&
+        git reflog expire --expire=0 --all &&
+        git prune &&
+        git push -f -v $HTTPD_URL/dumb/test_repo_unpacked.git master)
+'
+
+test_expect_success 'http-push fetches packed objects' '
+       cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
+               "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo_packed.git &&
+
+       git clone $HTTPD_URL/dumb/test_repo_packed.git \
+               "$ROOT_PATH"/test_repo_clone_packed &&
+
+       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo_packed.git &&
+        git --bare repack &&
+        git --bare prune-packed) &&
+
+       # By reset, we force git to retrieve the packed object
+       (cd "$ROOT_PATH"/test_repo_clone_packed &&
+        git reset --hard HEAD^ &&
+        git remote remove origin &&
+        git reflog expire --expire=0 --all &&
+        git prune &&
+        git push -f -v $HTTPD_URL/dumb/test_repo_packed.git master)
+'
+
+test_expect_success 'create and delete remote branch' '
+       cd "$ROOT_PATH"/test_repo_clone &&
+       git checkout -b dev &&
+       : >path3 &&
+       git add path3 &&
+       test_tick &&
+       git commit -m dev &&
+       git push origin dev &&
+       git push origin :dev &&
+       test_must_fail git show-ref --verify refs/remotes/origin/dev
+'
+
+test_expect_success 'MKCOL sends directory names with trailing slashes' '
+
+       ! grep "\"MKCOL.*[^/] HTTP/[^ ]*\"" < "$HTTPD_ROOT_PATH"/access.log
+
+'
+
+x1="[0-9a-f]"
+x2="$x1$x1"
+x5="$x1$x1$x1$x1$x1"
+x38="$x5$x5$x5$x5$x5$x5$x5$x1$x1$x1"
+x40="$x38$x2"
+
+test_expect_success 'PUT and MOVE sends object to URLs with SHA-1 hash suffix' '
+       sed \
+               -e "s/PUT /OP /" \
+               -e "s/MOVE /OP /" \
+           -e "s|/objects/$x2/${x38}_$x40|WANTED_PATH_REQUEST|" \
+               "$HTTPD_ROOT_PATH"/access.log |
+       grep -e "\"OP .*WANTED_PATH_REQUEST HTTP/[.0-9]*\" 20[0-9] "
+
+'
+
+test_http_push_nonff "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
+       "$ROOT_PATH"/test_repo_clone master
+
+test_expect_success 'push to password-protected repository (user in URL)' '
+       test_commit pw-user &&
+       set_askpass user@host pass@host &&
+       git push "$HTTPD_URL_USER/auth/dumb/test_repo.git" HEAD &&
+       git rev-parse --verify HEAD >expect &&
+       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/test_repo.git" \
+               rev-parse --verify HEAD >actual &&
+       test_cmp expect actual
+'
+
+test_expect_failure 'user was prompted only once for password' '
+       expect_askpass pass user@host
+'
+
+test_expect_failure 'push to password-protected repository (no user in URL)' '
+       test_commit pw-nouser &&
+       set_askpass user@host pass@host &&
+       git push "$HTTPD_URL/auth/dumb/test_repo.git" HEAD &&
+       expect_askpass both user@host
+       git rev-parse --verify HEAD >expect &&
+       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/test_repo.git" \
+               rev-parse --verify HEAD >actual &&
+       test_cmp expect actual
+'
+
+stop_httpd
+
+test_done
diff --git a/t/t5540-http-push.sh b/t/t5540-http-push.sh
deleted file mode 100755 (executable)
index 5b0198c..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at>
-#
-
-test_description='test WebDAV http-push
-
-This test runs various sanity checks on http-push.'
-
-. ./test-lib.sh
-
-if git http-push > /dev/null 2>&1 || [ $? -eq 128 ]
-then
-       skip_all="skipping test, USE_CURL_MULTI is not defined"
-       test_done
-fi
-
-LIB_HTTPD_DAV=t
-LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5540'}
-. "$TEST_DIRECTORY"/lib-httpd.sh
-ROOT_PATH="$PWD"
-start_httpd
-
-test_expect_success 'setup remote repository' '
-       cd "$ROOT_PATH" &&
-       mkdir test_repo &&
-       cd test_repo &&
-       git init &&
-       : >path1 &&
-       git add path1 &&
-       test_tick &&
-       git commit -m initial &&
-       cd - &&
-       git clone --bare test_repo test_repo.git &&
-       cd test_repo.git &&
-       git --bare update-server-info &&
-       mv hooks/post-update.sample hooks/post-update &&
-       ORIG_HEAD=$(git rev-parse --verify HEAD) &&
-       cd - &&
-       mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH"
-'
-
-test_expect_success 'create password-protected repository' '
-       mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb" &&
-       cp -Rf "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
-              "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/test_repo.git"
-'
-
-setup_askpass_helper
-
-test_expect_success 'clone remote repository' '
-       cd "$ROOT_PATH" &&
-       git clone $HTTPD_URL/dumb/test_repo.git test_repo_clone
-'
-
-test_expect_success 'push to remote repository with packed refs' '
-       cd "$ROOT_PATH"/test_repo_clone &&
-       : >path2 &&
-       git add path2 &&
-       test_tick &&
-       git commit -m path2 &&
-       HEAD=$(git rev-parse --verify HEAD) &&
-       git push &&
-       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
-        test $HEAD = $(git rev-parse --verify HEAD))
-'
-
-test_expect_success 'push already up-to-date' '
-       git push
-'
-
-test_expect_success 'push to remote repository with unpacked refs' '
-       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
-        rm packed-refs &&
-        git update-ref refs/heads/master $ORIG_HEAD &&
-        git --bare update-server-info) &&
-       git push &&
-       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
-        test $HEAD = $(git rev-parse --verify HEAD))
-'
-
-test_expect_success 'http-push fetches unpacked objects' '
-       cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
-               "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo_unpacked.git &&
-
-       git clone $HTTPD_URL/dumb/test_repo_unpacked.git \
-               "$ROOT_PATH"/fetch_unpacked &&
-
-       # By reset, we force git to retrieve the object
-       (cd "$ROOT_PATH"/fetch_unpacked &&
-        git reset --hard HEAD^ &&
-        git remote rm origin &&
-        git reflog expire --expire=0 --all &&
-        git prune &&
-        git push -f -v $HTTPD_URL/dumb/test_repo_unpacked.git master)
-'
-
-test_expect_success 'http-push fetches packed objects' '
-       cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
-               "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo_packed.git &&
-
-       git clone $HTTPD_URL/dumb/test_repo_packed.git \
-               "$ROOT_PATH"/test_repo_clone_packed &&
-
-       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo_packed.git &&
-        git --bare repack &&
-        git --bare prune-packed) &&
-
-       # By reset, we force git to retrieve the packed object
-       (cd "$ROOT_PATH"/test_repo_clone_packed &&
-        git reset --hard HEAD^ &&
-        git remote remove origin &&
-        git reflog expire --expire=0 --all &&
-        git prune &&
-        git push -f -v $HTTPD_URL/dumb/test_repo_packed.git master)
-'
-
-test_expect_success 'create and delete remote branch' '
-       cd "$ROOT_PATH"/test_repo_clone &&
-       git checkout -b dev &&
-       : >path3 &&
-       git add path3 &&
-       test_tick &&
-       git commit -m dev &&
-       git push origin dev &&
-       git push origin :dev &&
-       test_must_fail git show-ref --verify refs/remotes/origin/dev
-'
-
-test_expect_success 'MKCOL sends directory names with trailing slashes' '
-
-       ! grep "\"MKCOL.*[^/] HTTP/[^ ]*\"" < "$HTTPD_ROOT_PATH"/access.log
-
-'
-
-x1="[0-9a-f]"
-x2="$x1$x1"
-x5="$x1$x1$x1$x1$x1"
-x38="$x5$x5$x5$x5$x5$x5$x5$x1$x1$x1"
-x40="$x38$x2"
-
-test_expect_success 'PUT and MOVE sends object to URLs with SHA-1 hash suffix' '
-       sed \
-               -e "s/PUT /OP /" \
-               -e "s/MOVE /OP /" \
-           -e "s|/objects/$x2/${x38}_$x40|WANTED_PATH_REQUEST|" \
-               "$HTTPD_ROOT_PATH"/access.log |
-       grep -e "\"OP .*WANTED_PATH_REQUEST HTTP/[.0-9]*\" 20[0-9] "
-
-'
-
-test_http_push_nonff "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
-       "$ROOT_PATH"/test_repo_clone master
-
-test_expect_success 'push to password-protected repository (user in URL)' '
-       test_commit pw-user &&
-       set_askpass user@host pass@host &&
-       git push "$HTTPD_URL_USER/auth/dumb/test_repo.git" HEAD &&
-       git rev-parse --verify HEAD >expect &&
-       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/test_repo.git" \
-               rev-parse --verify HEAD >actual &&
-       test_cmp expect actual
-'
-
-test_expect_failure 'user was prompted only once for password' '
-       expect_askpass pass user@host
-'
-
-test_expect_failure 'push to password-protected repository (no user in URL)' '
-       test_commit pw-nouser &&
-       set_askpass user@host pass@host &&
-       git push "$HTTPD_URL/auth/dumb/test_repo.git" HEAD &&
-       expect_askpass both user@host
-       git rev-parse --verify HEAD >expect &&
-       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/test_repo.git" \
-               rev-parse --verify HEAD >actual &&
-       test_cmp expect actual
-'
-
-stop_httpd
-
-test_done
diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh
new file mode 100755 (executable)
index 0000000..73af16f
--- /dev/null
@@ -0,0 +1,327 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at>
+#
+
+test_description='test smart pushing over http via http-backend'
+. ./test-lib.sh
+
+if test -n "$NO_CURL"; then
+       skip_all='skipping test, git built without http support'
+       test_done
+fi
+
+ROOT_PATH="$PWD"
+. "$TEST_DIRECTORY"/lib-httpd.sh
+. "$TEST_DIRECTORY"/lib-terminal.sh
+start_httpd
+
+test_expect_success 'setup remote repository' '
+       cd "$ROOT_PATH" &&
+       mkdir test_repo &&
+       cd test_repo &&
+       git init &&
+       : >path1 &&
+       git add path1 &&
+       test_tick &&
+       git commit -m initial &&
+       cd - &&
+       git clone --bare test_repo test_repo.git &&
+       cd test_repo.git &&
+       git config http.receivepack true &&
+       git config core.logallrefupdates true &&
+       ORIG_HEAD=$(git rev-parse --verify HEAD) &&
+       cd - &&
+       mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH"
+'
+
+setup_askpass_helper
+
+cat >exp <<EOF
+GET  /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
+POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200
+EOF
+test_expect_success 'no empty path components' '
+       # In the URL, add a trailing slash, and see if git appends yet another
+       # slash.
+       cd "$ROOT_PATH" &&
+       git clone $HTTPD_URL/smart/test_repo.git/ test_repo_clone &&
+
+       sed -e "
+               s/^.* \"//
+               s/\"//
+               s/ [1-9][0-9]*\$//
+               s/^GET /GET  /
+       " >act <"$HTTPD_ROOT_PATH"/access.log &&
+
+       # Clear the log, so that it does not affect the "used receive-pack
+       # service" test which reads the log too.
+       #
+       # We do this before the actual comparison to ensure the log is cleared.
+       echo > "$HTTPD_ROOT_PATH"/access.log &&
+
+       test_cmp exp act
+'
+
+test_expect_success 'clone remote repository' '
+       rm -rf test_repo_clone &&
+       git clone $HTTPD_URL/smart/test_repo.git test_repo_clone &&
+       (
+               cd test_repo_clone && git config push.default matching
+       )
+'
+
+test_expect_success 'push to remote repository (standard)' '
+       cd "$ROOT_PATH"/test_repo_clone &&
+       : >path2 &&
+       git add path2 &&
+       test_tick &&
+       git commit -m path2 &&
+       HEAD=$(git rev-parse --verify HEAD) &&
+       GIT_CURL_VERBOSE=1 git push -v -v 2>err &&
+       ! grep "Expect: 100-continue" err &&
+       grep "POST git-receive-pack ([0-9]* bytes)" err &&
+       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
+        test $HEAD = $(git rev-parse --verify HEAD))
+'
+
+test_expect_success 'push already up-to-date' '
+       git push
+'
+
+test_expect_success 'create and delete remote branch' '
+       cd "$ROOT_PATH"/test_repo_clone &&
+       git checkout -b dev &&
+       : >path3 &&
+       git add path3 &&
+       test_tick &&
+       git commit -m dev &&
+       git push origin dev &&
+       git push origin :dev &&
+       test_must_fail git show-ref --verify refs/remotes/origin/dev
+'
+
+cat >"$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update" <<EOF
+#!/bin/sh
+exit 1
+EOF
+chmod a+x "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update"
+
+cat >exp <<EOF
+remote: error: hook declined to update refs/heads/dev2
+To http://127.0.0.1:$LIB_HTTPD_PORT/smart/test_repo.git
+ ! [remote rejected] dev2 -> dev2 (hook declined)
+error: failed to push some refs to 'http://127.0.0.1:$LIB_HTTPD_PORT/smart/test_repo.git'
+EOF
+
+test_expect_success 'rejected update prints status' '
+       cd "$ROOT_PATH"/test_repo_clone &&
+       git checkout -b dev2 &&
+       : >path4 &&
+       git add path4 &&
+       test_tick &&
+       git commit -m dev2 &&
+       test_must_fail git push origin dev2 2>act &&
+       sed -e "/^remote: /s/ *$//" <act >cmp &&
+       test_cmp exp cmp
+'
+rm -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update"
+
+cat >exp <<EOF
+
+GET  /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
+POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200
+GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
+POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
+GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
+GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
+POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
+GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
+POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
+GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
+POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
+EOF
+test_expect_success 'used receive-pack service' '
+       sed -e "
+               s/^.* \"//
+               s/\"//
+               s/ [1-9][0-9]*\$//
+               s/^GET /GET  /
+       " >act <"$HTTPD_ROOT_PATH"/access.log &&
+       test_cmp exp act
+'
+
+test_http_push_nonff "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
+       "$ROOT_PATH"/test_repo_clone master             success
+
+test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper' '
+       # create a dissimilarly-named remote ref so that git is unable to match the
+       # two refs (viz. local, remote) unless an explicit refspec is provided.
+       git push origin master:retsam
+
+       echo "change changed" > path2 &&
+       git commit -a -m path2 --amend &&
+
+       # push master too; this ensures there is at least one '"'push'"' command to
+       # the remote helper and triggers interaction with the helper.
+       test_must_fail git push -v origin +master master:retsam >output 2>&1'
+
+test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper: remote output' '
+       grep "^ + [a-f0-9]*\.\.\.[a-f0-9]* *master -> master (forced update)$" output &&
+       grep "^ ! \[rejected\] *master -> retsam (non-fast-forward)$" output
+'
+
+test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper: our output' '
+       test_i18ngrep "Updates were rejected because" \
+               output
+'
+
+test_expect_success 'push (chunked)' '
+       git checkout master &&
+       test_commit commit path3 &&
+       HEAD=$(git rev-parse --verify HEAD) &&
+       test_config http.postbuffer 4 &&
+       git push -v -v origin $BRANCH 2>err &&
+       grep "POST git-receive-pack (chunked)" err &&
+       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
+        test $HEAD = $(git rev-parse --verify HEAD))
+'
+
+test_expect_success 'push --all can push to empty repo' '
+       d=$HTTPD_DOCUMENT_ROOT_PATH/empty-all.git &&
+       git init --bare "$d" &&
+       git --git-dir="$d" config http.receivepack true &&
+       git push --all "$HTTPD_URL"/smart/empty-all.git
+'
+
+test_expect_success 'push --mirror can push to empty repo' '
+       d=$HTTPD_DOCUMENT_ROOT_PATH/empty-mirror.git &&
+       git init --bare "$d" &&
+       git --git-dir="$d" config http.receivepack true &&
+       git push --mirror "$HTTPD_URL"/smart/empty-mirror.git
+'
+
+test_expect_success 'push --all to repo with alternates' '
+       s=$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git &&
+       d=$HTTPD_DOCUMENT_ROOT_PATH/alternates-all.git &&
+       git clone --bare --shared "$s" "$d" &&
+       git --git-dir="$d" config http.receivepack true &&
+       git --git-dir="$d" repack -adl &&
+       git push --all "$HTTPD_URL"/smart/alternates-all.git
+'
+
+test_expect_success 'push --mirror to repo with alternates' '
+       s=$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git &&
+       d=$HTTPD_DOCUMENT_ROOT_PATH/alternates-mirror.git &&
+       git clone --bare --shared "$s" "$d" &&
+       git --git-dir="$d" config http.receivepack true &&
+       git --git-dir="$d" repack -adl &&
+       git push --mirror "$HTTPD_URL"/smart/alternates-mirror.git
+'
+
+test_expect_success TTY 'push shows progress when stderr is a tty' '
+       cd "$ROOT_PATH"/test_repo_clone &&
+       test_commit noisy &&
+       test_terminal git push >output 2>&1 &&
+       grep "^Writing objects" output
+'
+
+test_expect_success TTY 'push --quiet silences status and progress' '
+       cd "$ROOT_PATH"/test_repo_clone &&
+       test_commit quiet &&
+       test_terminal git push --quiet >output 2>&1 &&
+       test_cmp /dev/null output
+'
+
+test_expect_success TTY 'push --no-progress silences progress but not status' '
+       cd "$ROOT_PATH"/test_repo_clone &&
+       test_commit no-progress &&
+       test_terminal git push --no-progress >output 2>&1 &&
+       grep "^To http" output &&
+       ! grep "^Writing objects"
+'
+
+test_expect_success 'push --progress shows progress to non-tty' '
+       cd "$ROOT_PATH"/test_repo_clone &&
+       test_commit progress &&
+       git push --progress >output 2>&1 &&
+       grep "^To http" output &&
+       grep "^Writing objects" output
+'
+
+test_expect_success 'http push gives sane defaults to reflog' '
+       cd "$ROOT_PATH"/test_repo_clone &&
+       test_commit reflog-test &&
+       git push "$HTTPD_URL"/smart/test_repo.git &&
+       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
+               log -g -1 --format="%gn <%ge>" >actual &&
+       echo "anonymous <anonymous@http.127.0.0.1>" >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'http push respects GIT_COMMITTER_* in reflog' '
+       cd "$ROOT_PATH"/test_repo_clone &&
+       test_commit custom-reflog-test &&
+       git push "$HTTPD_URL"/smart_custom_env/test_repo.git &&
+       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
+               log -g -1 --format="%gn <%ge>" >actual &&
+       echo "Custom User <custom@example.com>" >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'push over smart http with auth' '
+       cd "$ROOT_PATH/test_repo_clone" &&
+       echo push-auth-test >expect &&
+       test_commit push-auth-test &&
+       set_askpass user@host pass@host &&
+       git push "$HTTPD_URL"/auth/smart/test_repo.git &&
+       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
+               log -1 --format=%s >actual &&
+       expect_askpass both user@host &&
+       test_cmp expect actual
+'
+
+test_expect_success 'push to auth-only-for-push repo' '
+       cd "$ROOT_PATH/test_repo_clone" &&
+       echo push-half-auth >expect &&
+       test_commit push-half-auth &&
+       set_askpass user@host pass@host &&
+       git push "$HTTPD_URL"/auth-push/smart/test_repo.git &&
+       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
+               log -1 --format=%s >actual &&
+       expect_askpass both user@host &&
+       test_cmp expect actual
+'
+
+test_expect_success 'create repo without http.receivepack set' '
+       cd "$ROOT_PATH" &&
+       git init half-auth &&
+       (
+               cd half-auth &&
+               test_commit one
+       ) &&
+       git clone --bare half-auth "$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git"
+'
+
+test_expect_success 'clone via half-auth-complete does not need password' '
+       cd "$ROOT_PATH" &&
+       set_askpass wrong &&
+       git clone "$HTTPD_URL"/half-auth-complete/smart/half-auth.git \
+               half-auth-clone &&
+       expect_askpass none
+'
+
+test_expect_success 'push into half-auth-complete requires password' '
+       cd "$ROOT_PATH/half-auth-clone" &&
+       echo two >expect &&
+       test_commit two &&
+       set_askpass user@host pass@host &&
+       git push "$HTTPD_URL/half-auth-complete/smart/half-auth.git" &&
+       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git" \
+               log -1 --format=%s >actual &&
+       expect_askpass both user@host &&
+       test_cmp expect actual
+'
+
+stop_httpd
+test_done
diff --git a/t/t5541-http-push.sh b/t/t5541-http-push.sh
deleted file mode 100755 (executable)
index bfd241e..0000000
+++ /dev/null
@@ -1,328 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at>
-#
-
-test_description='test smart pushing over http via http-backend'
-. ./test-lib.sh
-
-if test -n "$NO_CURL"; then
-       skip_all='skipping test, git built without http support'
-       test_done
-fi
-
-ROOT_PATH="$PWD"
-LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5541'}
-. "$TEST_DIRECTORY"/lib-httpd.sh
-. "$TEST_DIRECTORY"/lib-terminal.sh
-start_httpd
-
-test_expect_success 'setup remote repository' '
-       cd "$ROOT_PATH" &&
-       mkdir test_repo &&
-       cd test_repo &&
-       git init &&
-       : >path1 &&
-       git add path1 &&
-       test_tick &&
-       git commit -m initial &&
-       cd - &&
-       git clone --bare test_repo test_repo.git &&
-       cd test_repo.git &&
-       git config http.receivepack true &&
-       git config core.logallrefupdates true &&
-       ORIG_HEAD=$(git rev-parse --verify HEAD) &&
-       cd - &&
-       mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH"
-'
-
-setup_askpass_helper
-
-cat >exp <<EOF
-GET  /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
-POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200
-EOF
-test_expect_success 'no empty path components' '
-       # In the URL, add a trailing slash, and see if git appends yet another
-       # slash.
-       cd "$ROOT_PATH" &&
-       git clone $HTTPD_URL/smart/test_repo.git/ test_repo_clone &&
-
-       sed -e "
-               s/^.* \"//
-               s/\"//
-               s/ [1-9][0-9]*\$//
-               s/^GET /GET  /
-       " >act <"$HTTPD_ROOT_PATH"/access.log &&
-
-       # Clear the log, so that it does not affect the "used receive-pack
-       # service" test which reads the log too.
-       #
-       # We do this before the actual comparison to ensure the log is cleared.
-       echo > "$HTTPD_ROOT_PATH"/access.log &&
-
-       test_cmp exp act
-'
-
-test_expect_success 'clone remote repository' '
-       rm -rf test_repo_clone &&
-       git clone $HTTPD_URL/smart/test_repo.git test_repo_clone &&
-       (
-               cd test_repo_clone && git config push.default matching
-       )
-'
-
-test_expect_success 'push to remote repository (standard)' '
-       cd "$ROOT_PATH"/test_repo_clone &&
-       : >path2 &&
-       git add path2 &&
-       test_tick &&
-       git commit -m path2 &&
-       HEAD=$(git rev-parse --verify HEAD) &&
-       GIT_CURL_VERBOSE=1 git push -v -v 2>err &&
-       ! grep "Expect: 100-continue" err &&
-       grep "POST git-receive-pack ([0-9]* bytes)" err &&
-       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
-        test $HEAD = $(git rev-parse --verify HEAD))
-'
-
-test_expect_success 'push already up-to-date' '
-       git push
-'
-
-test_expect_success 'create and delete remote branch' '
-       cd "$ROOT_PATH"/test_repo_clone &&
-       git checkout -b dev &&
-       : >path3 &&
-       git add path3 &&
-       test_tick &&
-       git commit -m dev &&
-       git push origin dev &&
-       git push origin :dev &&
-       test_must_fail git show-ref --verify refs/remotes/origin/dev
-'
-
-cat >"$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update" <<EOF
-#!/bin/sh
-exit 1
-EOF
-chmod a+x "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update"
-
-cat >exp <<EOF
-remote: error: hook declined to update refs/heads/dev2
-To http://127.0.0.1:$LIB_HTTPD_PORT/smart/test_repo.git
- ! [remote rejected] dev2 -> dev2 (hook declined)
-error: failed to push some refs to 'http://127.0.0.1:$LIB_HTTPD_PORT/smart/test_repo.git'
-EOF
-
-test_expect_success 'rejected update prints status' '
-       cd "$ROOT_PATH"/test_repo_clone &&
-       git checkout -b dev2 &&
-       : >path4 &&
-       git add path4 &&
-       test_tick &&
-       git commit -m dev2 &&
-       test_must_fail git push origin dev2 2>act &&
-       sed -e "/^remote: /s/ *$//" <act >cmp &&
-       test_cmp exp cmp
-'
-rm -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update"
-
-cat >exp <<EOF
-
-GET  /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
-POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200
-GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
-POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
-GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
-GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
-POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
-GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
-POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
-GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
-POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
-EOF
-test_expect_success 'used receive-pack service' '
-       sed -e "
-               s/^.* \"//
-               s/\"//
-               s/ [1-9][0-9]*\$//
-               s/^GET /GET  /
-       " >act <"$HTTPD_ROOT_PATH"/access.log &&
-       test_cmp exp act
-'
-
-test_http_push_nonff "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
-       "$ROOT_PATH"/test_repo_clone master             success
-
-test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper' '
-       # create a dissimilarly-named remote ref so that git is unable to match the
-       # two refs (viz. local, remote) unless an explicit refspec is provided.
-       git push origin master:retsam
-
-       echo "change changed" > path2 &&
-       git commit -a -m path2 --amend &&
-
-       # push master too; this ensures there is at least one '"'push'"' command to
-       # the remote helper and triggers interaction with the helper.
-       test_must_fail git push -v origin +master master:retsam >output 2>&1'
-
-test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper: remote output' '
-       grep "^ + [a-f0-9]*\.\.\.[a-f0-9]* *master -> master (forced update)$" output &&
-       grep "^ ! \[rejected\] *master -> retsam (non-fast-forward)$" output
-'
-
-test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper: our output' '
-       test_i18ngrep "Updates were rejected because" \
-               output
-'
-
-test_expect_success 'push (chunked)' '
-       git checkout master &&
-       test_commit commit path3 &&
-       HEAD=$(git rev-parse --verify HEAD) &&
-       test_config http.postbuffer 4 &&
-       git push -v -v origin $BRANCH 2>err &&
-       grep "POST git-receive-pack (chunked)" err &&
-       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
-        test $HEAD = $(git rev-parse --verify HEAD))
-'
-
-test_expect_success 'push --all can push to empty repo' '
-       d=$HTTPD_DOCUMENT_ROOT_PATH/empty-all.git &&
-       git init --bare "$d" &&
-       git --git-dir="$d" config http.receivepack true &&
-       git push --all "$HTTPD_URL"/smart/empty-all.git
-'
-
-test_expect_success 'push --mirror can push to empty repo' '
-       d=$HTTPD_DOCUMENT_ROOT_PATH/empty-mirror.git &&
-       git init --bare "$d" &&
-       git --git-dir="$d" config http.receivepack true &&
-       git push --mirror "$HTTPD_URL"/smart/empty-mirror.git
-'
-
-test_expect_success 'push --all to repo with alternates' '
-       s=$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git &&
-       d=$HTTPD_DOCUMENT_ROOT_PATH/alternates-all.git &&
-       git clone --bare --shared "$s" "$d" &&
-       git --git-dir="$d" config http.receivepack true &&
-       git --git-dir="$d" repack -adl &&
-       git push --all "$HTTPD_URL"/smart/alternates-all.git
-'
-
-test_expect_success 'push --mirror to repo with alternates' '
-       s=$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git &&
-       d=$HTTPD_DOCUMENT_ROOT_PATH/alternates-mirror.git &&
-       git clone --bare --shared "$s" "$d" &&
-       git --git-dir="$d" config http.receivepack true &&
-       git --git-dir="$d" repack -adl &&
-       git push --mirror "$HTTPD_URL"/smart/alternates-mirror.git
-'
-
-test_expect_success TTY 'push shows progress when stderr is a tty' '
-       cd "$ROOT_PATH"/test_repo_clone &&
-       test_commit noisy &&
-       test_terminal git push >output 2>&1 &&
-       grep "^Writing objects" output
-'
-
-test_expect_success TTY 'push --quiet silences status and progress' '
-       cd "$ROOT_PATH"/test_repo_clone &&
-       test_commit quiet &&
-       test_terminal git push --quiet >output 2>&1 &&
-       test_cmp /dev/null output
-'
-
-test_expect_success TTY 'push --no-progress silences progress but not status' '
-       cd "$ROOT_PATH"/test_repo_clone &&
-       test_commit no-progress &&
-       test_terminal git push --no-progress >output 2>&1 &&
-       grep "^To http" output &&
-       ! grep "^Writing objects"
-'
-
-test_expect_success 'push --progress shows progress to non-tty' '
-       cd "$ROOT_PATH"/test_repo_clone &&
-       test_commit progress &&
-       git push --progress >output 2>&1 &&
-       grep "^To http" output &&
-       grep "^Writing objects" output
-'
-
-test_expect_success 'http push gives sane defaults to reflog' '
-       cd "$ROOT_PATH"/test_repo_clone &&
-       test_commit reflog-test &&
-       git push "$HTTPD_URL"/smart/test_repo.git &&
-       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
-               log -g -1 --format="%gn <%ge>" >actual &&
-       echo "anonymous <anonymous@http.127.0.0.1>" >expect &&
-       test_cmp expect actual
-'
-
-test_expect_success 'http push respects GIT_COMMITTER_* in reflog' '
-       cd "$ROOT_PATH"/test_repo_clone &&
-       test_commit custom-reflog-test &&
-       git push "$HTTPD_URL"/smart_custom_env/test_repo.git &&
-       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
-               log -g -1 --format="%gn <%ge>" >actual &&
-       echo "Custom User <custom@example.com>" >expect &&
-       test_cmp expect actual
-'
-
-test_expect_success 'push over smart http with auth' '
-       cd "$ROOT_PATH/test_repo_clone" &&
-       echo push-auth-test >expect &&
-       test_commit push-auth-test &&
-       set_askpass user@host pass@host &&
-       git push "$HTTPD_URL"/auth/smart/test_repo.git &&
-       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
-               log -1 --format=%s >actual &&
-       expect_askpass both user@host &&
-       test_cmp expect actual
-'
-
-test_expect_success 'push to auth-only-for-push repo' '
-       cd "$ROOT_PATH/test_repo_clone" &&
-       echo push-half-auth >expect &&
-       test_commit push-half-auth &&
-       set_askpass user@host pass@host &&
-       git push "$HTTPD_URL"/auth-push/smart/test_repo.git &&
-       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
-               log -1 --format=%s >actual &&
-       expect_askpass both user@host &&
-       test_cmp expect actual
-'
-
-test_expect_success 'create repo without http.receivepack set' '
-       cd "$ROOT_PATH" &&
-       git init half-auth &&
-       (
-               cd half-auth &&
-               test_commit one
-       ) &&
-       git clone --bare half-auth "$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git"
-'
-
-test_expect_success 'clone via half-auth-complete does not need password' '
-       cd "$ROOT_PATH" &&
-       set_askpass wrong &&
-       git clone "$HTTPD_URL"/half-auth-complete/smart/half-auth.git \
-               half-auth-clone &&
-       expect_askpass none
-'
-
-test_expect_success 'push into half-auth-complete requires password' '
-       cd "$ROOT_PATH/half-auth-clone" &&
-       echo two >expect &&
-       test_commit two &&
-       set_askpass user@host pass@host &&
-       git push "$HTTPD_URL/half-auth-complete/smart/half-auth.git" &&
-       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git" \
-               log -1 --format=%s >actual &&
-       expect_askpass both user@host &&
-       test_cmp expect actual
-'
-
-stop_httpd
-test_done
diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh
new file mode 100755 (executable)
index 0000000..1a3a2b6
--- /dev/null
@@ -0,0 +1,175 @@
+#!/bin/sh
+
+test_description='test dumb fetching over http via static file'
+. ./test-lib.sh
+
+if test -n "$NO_CURL"; then
+       skip_all='skipping test, git built without http support'
+       test_done
+fi
+
+. "$TEST_DIRECTORY"/lib-httpd.sh
+start_httpd
+
+test_expect_success 'setup repository' '
+       git config push.default matching &&
+       echo content1 >file &&
+       git add file &&
+       git commit -m one
+       echo content2 >file &&
+       git add file &&
+       git commit -m two
+'
+
+test_expect_success 'create http-accessible bare repository with loose objects' '
+       cp -R .git "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+       (cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+        git config core.bare true &&
+        mkdir -p hooks &&
+        echo "exec git update-server-info" >hooks/post-update &&
+        chmod +x hooks/post-update &&
+        hooks/post-update
+       ) &&
+       git remote add public "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+       git push public master:master
+'
+
+test_expect_success 'clone http repository' '
+       git clone $HTTPD_URL/dumb/repo.git clone-tmpl &&
+       cp -R clone-tmpl clone &&
+       test_cmp file clone/file
+'
+
+test_expect_success 'create password-protected repository' '
+       mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/" &&
+       cp -Rf "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
+              "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/repo.git"
+'
+
+setup_askpass_helper
+
+test_expect_success 'cloning password-protected repository can fail' '
+       set_askpass wrong &&
+       test_must_fail git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-fail &&
+       expect_askpass both wrong
+'
+
+test_expect_success 'http auth can use user/pass in URL' '
+       set_askpass wrong &&
+       git clone "$HTTPD_URL_USER_PASS/auth/dumb/repo.git" clone-auth-none &&
+       expect_askpass none
+'
+
+test_expect_success 'http auth can use just user in URL' '
+       set_askpass wrong pass@host &&
+       git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-pass &&
+       expect_askpass pass user@host
+'
+
+test_expect_success 'http auth can request both user and pass' '
+       set_askpass user@host pass@host &&
+       git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-both &&
+       expect_askpass both user@host
+'
+
+test_expect_success 'http auth respects credential helper config' '
+       test_config_global credential.helper "!f() {
+               cat >/dev/null
+               echo username=user@host
+               echo password=pass@host
+       }; f" &&
+       set_askpass wrong &&
+       git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-helper &&
+       expect_askpass none
+'
+
+test_expect_success 'http auth can get username from config' '
+       test_config_global "credential.$HTTPD_URL.username" user@host &&
+       set_askpass wrong pass@host &&
+       git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-user &&
+       expect_askpass pass user@host
+'
+
+test_expect_success 'configured username does not override URL' '
+       test_config_global "credential.$HTTPD_URL.username" wrong &&
+       set_askpass wrong pass@host &&
+       git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-user2 &&
+       expect_askpass pass user@host
+'
+
+test_expect_success 'fetch changes via http' '
+       echo content >>file &&
+       git commit -a -m two &&
+       git push public &&
+       (cd clone && git pull) &&
+       test_cmp file clone/file
+'
+
+test_expect_success 'fetch changes via manual http-fetch' '
+       cp -R clone-tmpl clone2 &&
+
+       HEAD=$(git rev-parse --verify HEAD) &&
+       (cd clone2 &&
+        git http-fetch -a -w heads/master-new $HEAD $(git config remote.origin.url) &&
+        git checkout master-new &&
+        test $HEAD = $(git rev-parse --verify HEAD)) &&
+       test_cmp file clone2/file
+'
+
+test_expect_success 'http remote detects correct HEAD' '
+       git push public master:other &&
+       (cd clone &&
+        git remote set-head origin -d &&
+        git remote set-head origin -a &&
+        git symbolic-ref refs/remotes/origin/HEAD > output &&
+        echo refs/remotes/origin/master > expect &&
+        test_cmp expect output
+       )
+'
+
+test_expect_success 'fetch packed objects' '
+       cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git &&
+       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git &&
+        git --bare repack -a -d
+       ) &&
+       git clone $HTTPD_URL/dumb/repo_pack.git
+'
+
+test_expect_success 'fetch notices corrupt pack' '
+       cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad1.git &&
+       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad1.git &&
+        p=`ls objects/pack/pack-*.pack` &&
+        chmod u+w $p &&
+        printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc
+       ) &&
+       mkdir repo_bad1.git &&
+       (cd repo_bad1.git &&
+        git --bare init &&
+        test_must_fail git --bare fetch $HTTPD_URL/dumb/repo_bad1.git &&
+        test 0 = `ls objects/pack/pack-*.pack | wc -l`
+       )
+'
+
+test_expect_success 'fetch notices corrupt idx' '
+       cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad2.git &&
+       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad2.git &&
+        p=`ls objects/pack/pack-*.idx` &&
+        chmod u+w $p &&
+        printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc
+       ) &&
+       mkdir repo_bad2.git &&
+       (cd repo_bad2.git &&
+        git --bare init &&
+        test_must_fail git --bare fetch $HTTPD_URL/dumb/repo_bad2.git &&
+        test 0 = `ls objects/pack | wc -l`
+       )
+'
+
+test_expect_success 'did not use upload-pack service' '
+       grep '/git-upload-pack' <"$HTTPD_ROOT_PATH"/access.log >act
+       : >exp
+       test_cmp exp act
+'
+
+stop_httpd
+test_done
diff --git a/t/t5550-http-fetch.sh b/t/t5550-http-fetch.sh
deleted file mode 100755 (executable)
index 8392624..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-#!/bin/sh
-
-test_description='test dumb fetching over http via static file'
-. ./test-lib.sh
-
-if test -n "$NO_CURL"; then
-       skip_all='skipping test, git built without http support'
-       test_done
-fi
-
-LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5550'}
-. "$TEST_DIRECTORY"/lib-httpd.sh
-start_httpd
-
-test_expect_success 'setup repository' '
-       git config push.default matching &&
-       echo content1 >file &&
-       git add file &&
-       git commit -m one
-       echo content2 >file &&
-       git add file &&
-       git commit -m two
-'
-
-test_expect_success 'create http-accessible bare repository with loose objects' '
-       cp -R .git "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
-       (cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
-        git config core.bare true &&
-        mkdir -p hooks &&
-        echo "exec git update-server-info" >hooks/post-update &&
-        chmod +x hooks/post-update &&
-        hooks/post-update
-       ) &&
-       git remote add public "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
-       git push public master:master
-'
-
-test_expect_success 'clone http repository' '
-       git clone $HTTPD_URL/dumb/repo.git clone-tmpl &&
-       cp -R clone-tmpl clone &&
-       test_cmp file clone/file
-'
-
-test_expect_success 'create password-protected repository' '
-       mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/" &&
-       cp -Rf "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
-              "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/repo.git"
-'
-
-setup_askpass_helper
-
-test_expect_success 'cloning password-protected repository can fail' '
-       set_askpass wrong &&
-       test_must_fail git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-fail &&
-       expect_askpass both wrong
-'
-
-test_expect_success 'http auth can use user/pass in URL' '
-       set_askpass wrong &&
-       git clone "$HTTPD_URL_USER_PASS/auth/dumb/repo.git" clone-auth-none &&
-       expect_askpass none
-'
-
-test_expect_success 'http auth can use just user in URL' '
-       set_askpass wrong pass@host &&
-       git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-pass &&
-       expect_askpass pass user@host
-'
-
-test_expect_success 'http auth can request both user and pass' '
-       set_askpass user@host pass@host &&
-       git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-both &&
-       expect_askpass both user@host
-'
-
-test_expect_success 'http auth respects credential helper config' '
-       test_config_global credential.helper "!f() {
-               cat >/dev/null
-               echo username=user@host
-               echo password=pass@host
-       }; f" &&
-       set_askpass wrong &&
-       git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-helper &&
-       expect_askpass none
-'
-
-test_expect_success 'http auth can get username from config' '
-       test_config_global "credential.$HTTPD_URL.username" user@host &&
-       set_askpass wrong pass@host &&
-       git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-user &&
-       expect_askpass pass user@host
-'
-
-test_expect_success 'configured username does not override URL' '
-       test_config_global "credential.$HTTPD_URL.username" wrong &&
-       set_askpass wrong pass@host &&
-       git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-user2 &&
-       expect_askpass pass user@host
-'
-
-test_expect_success 'fetch changes via http' '
-       echo content >>file &&
-       git commit -a -m two &&
-       git push public &&
-       (cd clone && git pull) &&
-       test_cmp file clone/file
-'
-
-test_expect_success 'fetch changes via manual http-fetch' '
-       cp -R clone-tmpl clone2 &&
-
-       HEAD=$(git rev-parse --verify HEAD) &&
-       (cd clone2 &&
-        git http-fetch -a -w heads/master-new $HEAD $(git config remote.origin.url) &&
-        git checkout master-new &&
-        test $HEAD = $(git rev-parse --verify HEAD)) &&
-       test_cmp file clone2/file
-'
-
-test_expect_success 'http remote detects correct HEAD' '
-       git push public master:other &&
-       (cd clone &&
-        git remote set-head origin -d &&
-        git remote set-head origin -a &&
-        git symbolic-ref refs/remotes/origin/HEAD > output &&
-        echo refs/remotes/origin/master > expect &&
-        test_cmp expect output
-       )
-'
-
-test_expect_success 'fetch packed objects' '
-       cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git &&
-       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git &&
-        git --bare repack -a -d
-       ) &&
-       git clone $HTTPD_URL/dumb/repo_pack.git
-'
-
-test_expect_success 'fetch notices corrupt pack' '
-       cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad1.git &&
-       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad1.git &&
-        p=`ls objects/pack/pack-*.pack` &&
-        chmod u+w $p &&
-        printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc
-       ) &&
-       mkdir repo_bad1.git &&
-       (cd repo_bad1.git &&
-        git --bare init &&
-        test_must_fail git --bare fetch $HTTPD_URL/dumb/repo_bad1.git &&
-        test 0 = `ls objects/pack/pack-*.pack | wc -l`
-       )
-'
-
-test_expect_success 'fetch notices corrupt idx' '
-       cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad2.git &&
-       (cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad2.git &&
-        p=`ls objects/pack/pack-*.idx` &&
-        chmod u+w $p &&
-        printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc
-       ) &&
-       mkdir repo_bad2.git &&
-       (cd repo_bad2.git &&
-        git --bare init &&
-        test_must_fail git --bare fetch $HTTPD_URL/dumb/repo_bad2.git &&
-        test 0 = `ls objects/pack | wc -l`
-       )
-'
-
-test_expect_success 'did not use upload-pack service' '
-       grep '/git-upload-pack' <"$HTTPD_ROOT_PATH"/access.log >act
-       : >exp
-       test_cmp exp act
-'
-
-stop_httpd
-test_done
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
new file mode 100755 (executable)
index 0000000..e07eaf3
--- /dev/null
@@ -0,0 +1,252 @@
+#!/bin/sh
+
+test_description='test smart fetching over http via http-backend'
+. ./test-lib.sh
+
+if test -n "$NO_CURL"; then
+       skip_all='skipping test, git built without http support'
+       test_done
+fi
+
+. "$TEST_DIRECTORY"/lib-httpd.sh
+start_httpd
+
+test_expect_success 'setup repository' '
+       git config push.default matching &&
+       echo content >file &&
+       git add file &&
+       git commit -m one
+'
+
+test_expect_success 'create http-accessible bare repository' '
+       mkdir "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+       (cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+        git --bare init
+       ) &&
+       git remote add public "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+       git push public master:master
+'
+
+setup_askpass_helper
+
+cat >exp <<EOF
+> GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1
+> Accept: */*
+> Accept-Encoding: gzip
+> Pragma: no-cache
+< HTTP/1.1 200 OK
+< Pragma: no-cache
+< Cache-Control: no-cache, max-age=0, must-revalidate
+< Content-Type: application/x-git-upload-pack-advertisement
+> POST /smart/repo.git/git-upload-pack HTTP/1.1
+> Accept-Encoding: gzip
+> Content-Type: application/x-git-upload-pack-request
+> Accept: application/x-git-upload-pack-result
+> Content-Length: xxx
+< HTTP/1.1 200 OK
+< Pragma: no-cache
+< Cache-Control: no-cache, max-age=0, must-revalidate
+< Content-Type: application/x-git-upload-pack-result
+EOF
+test_expect_success 'clone http repository' '
+       GIT_CURL_VERBOSE=1 git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err &&
+       test_cmp file clone/file &&
+       tr '\''\015'\'' Q <err |
+       sed -e "
+               s/Q\$//
+               /^[*] /d
+               /^$/d
+               /^< $/d
+
+               /^[^><]/{
+                       s/^/> /
+               }
+
+               /^> User-Agent: /d
+               /^> Host: /d
+               /^> POST /,$ {
+                       /^> Accept: [*]\\/[*]/d
+               }
+               s/^> Content-Length: .*/> Content-Length: xxx/
+               /^> 00..want /d
+               /^> 00.*done/d
+
+               /^< Server: /d
+               /^< Expires: /d
+               /^< Date: /d
+               /^< Content-Length: /d
+               /^< Transfer-Encoding: /d
+       " >act &&
+       test_cmp exp act
+'
+
+test_expect_success 'fetch changes via http' '
+       echo content >>file &&
+       git commit -a -m two &&
+       git push public
+       (cd clone && git pull) &&
+       test_cmp file clone/file
+'
+
+cat >exp <<EOF
+GET  /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
+POST /smart/repo.git/git-upload-pack HTTP/1.1 200
+GET  /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
+POST /smart/repo.git/git-upload-pack HTTP/1.1 200
+EOF
+test_expect_success 'used upload-pack service' '
+       sed -e "
+               s/^.* \"//
+               s/\"//
+               s/ [1-9][0-9]*\$//
+               s/^GET /GET  /
+       " >act <"$HTTPD_ROOT_PATH"/access.log &&
+       test_cmp exp act
+'
+
+test_expect_success 'follow redirects (301)' '
+       git clone $HTTPD_URL/smart-redir-perm/repo.git --quiet repo-p
+'
+
+test_expect_success 'follow redirects (302)' '
+       git clone $HTTPD_URL/smart-redir-temp/repo.git --quiet repo-t
+'
+
+test_expect_success 'redirects re-root further requests' '
+       git clone $HTTPD_URL/smart-redir-limited/repo.git repo-redir-limited
+'
+
+test_expect_success 'clone from password-protected repository' '
+       echo two >expect &&
+       set_askpass user@host pass@host &&
+       git clone --bare "$HTTPD_URL/auth/smart/repo.git" smart-auth &&
+       expect_askpass both user@host &&
+       git --git-dir=smart-auth log -1 --format=%s >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'clone from auth-only-for-push repository' '
+       echo two >expect &&
+       set_askpass wrong &&
+       git clone --bare "$HTTPD_URL/auth-push/smart/repo.git" smart-noauth &&
+       expect_askpass none &&
+       git --git-dir=smart-noauth log -1 --format=%s >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'clone from auth-only-for-objects repository' '
+       echo two >expect &&
+       set_askpass user@host pass@host &&
+       git clone --bare "$HTTPD_URL/auth-fetch/smart/repo.git" half-auth &&
+       expect_askpass both user@host &&
+       git --git-dir=half-auth log -1 --format=%s >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'no-op half-auth fetch does not require a password' '
+       set_askpass wrong &&
+       git --git-dir=half-auth fetch &&
+       expect_askpass none
+'
+
+test_expect_success 'redirects send auth to new location' '
+       set_askpass user@host pass@host &&
+       git -c credential.useHttpPath=true \
+         clone $HTTPD_URL/smart-redir-auth/repo.git repo-redir-auth &&
+       expect_askpass both user@host auth/smart/repo.git
+'
+
+test_expect_success 'disable dumb http on server' '
+       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
+               config http.getanyfile false
+'
+
+test_expect_success 'GIT_SMART_HTTP can disable smart http' '
+       (GIT_SMART_HTTP=0 &&
+        export GIT_SMART_HTTP &&
+        cd clone &&
+        test_must_fail git fetch)
+'
+
+test_expect_success 'invalid Content-Type rejected' '
+       test_must_fail git clone $HTTPD_URL/broken_smart/repo.git 2>actual
+       grep "not valid:" actual
+'
+
+test_expect_success 'create namespaced refs' '
+       test_commit namespaced &&
+       git push public HEAD:refs/namespaces/ns/refs/heads/master &&
+       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
+               symbolic-ref refs/namespaces/ns/HEAD refs/namespaces/ns/refs/heads/master
+'
+
+test_expect_success 'smart clone respects namespace' '
+       git clone "$HTTPD_URL/smart_namespace/repo.git" ns-smart &&
+       echo namespaced >expect &&
+       git --git-dir=ns-smart/.git log -1 --format=%s >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'dumb clone via http-backend respects namespace' '
+       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
+               config http.getanyfile true &&
+       GIT_SMART_HTTP=0 git clone \
+               "$HTTPD_URL/smart_namespace/repo.git" ns-dumb &&
+       echo namespaced >expect &&
+       git --git-dir=ns-dumb/.git log -1 --format=%s >actual &&
+       test_cmp expect actual
+'
+
+cat >cookies.txt <<EOF
+127.0.0.1      FALSE   /smart_cookies/ FALSE   0       othername       othervalue
+EOF
+cat >expect_cookies.txt <<EOF
+
+127.0.0.1      FALSE   /smart_cookies/ FALSE   0       othername       othervalue
+127.0.0.1      FALSE   /smart_cookies/repo.git/info/   FALSE   0       name    value
+EOF
+test_expect_success 'cookies stored in http.cookiefile when http.savecookies set' '
+       git config http.cookiefile cookies.txt &&
+       git config http.savecookies true &&
+       git ls-remote $HTTPD_URL/smart_cookies/repo.git master &&
+       tail -3 cookies.txt > cookies_tail.txt
+       test_cmp expect_cookies.txt cookies_tail.txt
+'
+
+test -n "$GIT_TEST_LONG" && test_set_prereq EXPENSIVE
+
+test_expect_success EXPENSIVE 'create 50,000 tags in the repo' '
+       (
+       cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+       for i in `test_seq 50000`
+       do
+               echo "commit refs/heads/too-many-refs"
+               echo "mark :$i"
+               echo "committer git <git@example.com> $i +0000"
+               echo "data 0"
+               echo "M 644 inline bla.txt"
+               echo "data 4"
+               echo "bla"
+               # make every commit dangling by always
+               # rewinding the branch after each commit
+               echo "reset refs/heads/too-many-refs"
+               echo "from :1"
+       done | git fast-import --export-marks=marks &&
+
+       # now assign tags to all the dangling commits we created above
+       tag=$(perl -e "print \"bla\" x 30") &&
+       sed -e "s|^:\([^ ]*\) \(.*\)$|\2 refs/tags/$tag-\1|" <marks >>packed-refs
+       )
+'
+
+test_expect_success EXPENSIVE 'clone the 50,000 tag repo to check OS command line overflow' '
+       git clone $HTTPD_URL/smart/repo.git too-many-refs 2>err &&
+       test_line_count = 0 err &&
+       (
+               cd too-many-refs &&
+               test $(git for-each-ref refs/tags | wc -l) = 50000
+       )
+'
+
+stop_httpd
+test_done
diff --git a/t/t5551-http-fetch.sh b/t/t5551-http-fetch.sh
deleted file mode 100755 (executable)
index a124efe..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-#!/bin/sh
-
-test_description='test smart fetching over http via http-backend'
-. ./test-lib.sh
-
-if test -n "$NO_CURL"; then
-       skip_all='skipping test, git built without http support'
-       test_done
-fi
-
-LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5551'}
-. "$TEST_DIRECTORY"/lib-httpd.sh
-start_httpd
-
-test_expect_success 'setup repository' '
-       git config push.default matching &&
-       echo content >file &&
-       git add file &&
-       git commit -m one
-'
-
-test_expect_success 'create http-accessible bare repository' '
-       mkdir "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
-       (cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
-        git --bare init
-       ) &&
-       git remote add public "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
-       git push public master:master
-'
-
-setup_askpass_helper
-
-cat >exp <<EOF
-> GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1
-> Accept: */*
-> Accept-Encoding: gzip
-> Pragma: no-cache
-< HTTP/1.1 200 OK
-< Pragma: no-cache
-< Cache-Control: no-cache, max-age=0, must-revalidate
-< Content-Type: application/x-git-upload-pack-advertisement
-> POST /smart/repo.git/git-upload-pack HTTP/1.1
-> Accept-Encoding: gzip
-> Content-Type: application/x-git-upload-pack-request
-> Accept: application/x-git-upload-pack-result
-> Content-Length: xxx
-< HTTP/1.1 200 OK
-< Pragma: no-cache
-< Cache-Control: no-cache, max-age=0, must-revalidate
-< Content-Type: application/x-git-upload-pack-result
-EOF
-test_expect_success 'clone http repository' '
-       GIT_CURL_VERBOSE=1 git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err &&
-       test_cmp file clone/file &&
-       tr '\''\015'\'' Q <err |
-       sed -e "
-               s/Q\$//
-               /^[*] /d
-               /^$/d
-               /^< $/d
-
-               /^[^><]/{
-                       s/^/> /
-               }
-
-               /^> User-Agent: /d
-               /^> Host: /d
-               /^> POST /,$ {
-                       /^> Accept: [*]\\/[*]/d
-               }
-               s/^> Content-Length: .*/> Content-Length: xxx/
-               /^> 00..want /d
-               /^> 00.*done/d
-
-               /^< Server: /d
-               /^< Expires: /d
-               /^< Date: /d
-               /^< Content-Length: /d
-               /^< Transfer-Encoding: /d
-       " >act &&
-       test_cmp exp act
-'
-
-test_expect_success 'fetch changes via http' '
-       echo content >>file &&
-       git commit -a -m two &&
-       git push public
-       (cd clone && git pull) &&
-       test_cmp file clone/file
-'
-
-cat >exp <<EOF
-GET  /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
-POST /smart/repo.git/git-upload-pack HTTP/1.1 200
-GET  /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
-POST /smart/repo.git/git-upload-pack HTTP/1.1 200
-EOF
-test_expect_success 'used upload-pack service' '
-       sed -e "
-               s/^.* \"//
-               s/\"//
-               s/ [1-9][0-9]*\$//
-               s/^GET /GET  /
-       " >act <"$HTTPD_ROOT_PATH"/access.log &&
-       test_cmp exp act
-'
-
-test_expect_success 'follow redirects (301)' '
-       git clone $HTTPD_URL/smart-redir-perm/repo.git --quiet repo-p
-'
-
-test_expect_success 'follow redirects (302)' '
-       git clone $HTTPD_URL/smart-redir-temp/repo.git --quiet repo-t
-'
-
-test_expect_success 'redirects re-root further requests' '
-       git clone $HTTPD_URL/smart-redir-limited/repo.git repo-redir-limited
-'
-
-test_expect_success 'clone from password-protected repository' '
-       echo two >expect &&
-       set_askpass user@host pass@host &&
-       git clone --bare "$HTTPD_URL/auth/smart/repo.git" smart-auth &&
-       expect_askpass both user@host &&
-       git --git-dir=smart-auth log -1 --format=%s >actual &&
-       test_cmp expect actual
-'
-
-test_expect_success 'clone from auth-only-for-push repository' '
-       echo two >expect &&
-       set_askpass wrong &&
-       git clone --bare "$HTTPD_URL/auth-push/smart/repo.git" smart-noauth &&
-       expect_askpass none &&
-       git --git-dir=smart-noauth log -1 --format=%s >actual &&
-       test_cmp expect actual
-'
-
-test_expect_success 'clone from auth-only-for-objects repository' '
-       echo two >expect &&
-       set_askpass user@host pass@host &&
-       git clone --bare "$HTTPD_URL/auth-fetch/smart/repo.git" half-auth &&
-       expect_askpass both user@host &&
-       git --git-dir=half-auth log -1 --format=%s >actual &&
-       test_cmp expect actual
-'
-
-test_expect_success 'no-op half-auth fetch does not require a password' '
-       set_askpass wrong &&
-       git --git-dir=half-auth fetch &&
-       expect_askpass none
-'
-
-test_expect_success 'redirects send auth to new location' '
-       set_askpass user@host pass@host &&
-       git -c credential.useHttpPath=true \
-         clone $HTTPD_URL/smart-redir-auth/repo.git repo-redir-auth &&
-       expect_askpass both user@host auth/smart/repo.git
-'
-
-test_expect_success 'disable dumb http on server' '
-       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
-               config http.getanyfile false
-'
-
-test_expect_success 'GIT_SMART_HTTP can disable smart http' '
-       (GIT_SMART_HTTP=0 &&
-        export GIT_SMART_HTTP &&
-        cd clone &&
-        test_must_fail git fetch)
-'
-
-test_expect_success 'invalid Content-Type rejected' '
-       test_must_fail git clone $HTTPD_URL/broken_smart/repo.git 2>actual
-       grep "not valid:" actual
-'
-
-test_expect_success 'create namespaced refs' '
-       test_commit namespaced &&
-       git push public HEAD:refs/namespaces/ns/refs/heads/master &&
-       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
-               symbolic-ref refs/namespaces/ns/HEAD refs/namespaces/ns/refs/heads/master
-'
-
-test_expect_success 'smart clone respects namespace' '
-       git clone "$HTTPD_URL/smart_namespace/repo.git" ns-smart &&
-       echo namespaced >expect &&
-       git --git-dir=ns-smart/.git log -1 --format=%s >actual &&
-       test_cmp expect actual
-'
-
-test_expect_success 'dumb clone via http-backend respects namespace' '
-       git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
-               config http.getanyfile true &&
-       GIT_SMART_HTTP=0 git clone \
-               "$HTTPD_URL/smart_namespace/repo.git" ns-dumb &&
-       echo namespaced >expect &&
-       git --git-dir=ns-dumb/.git log -1 --format=%s >actual &&
-       test_cmp expect actual
-'
-
-cat >cookies.txt <<EOF
-127.0.0.1      FALSE   /smart_cookies/ FALSE   0       othername       othervalue
-EOF
-cat >expect_cookies.txt <<EOF
-
-127.0.0.1      FALSE   /smart_cookies/ FALSE   0       othername       othervalue
-127.0.0.1      FALSE   /smart_cookies/repo.git/info/   FALSE   0       name    value
-EOF
-test_expect_success 'cookies stored in http.cookiefile when http.savecookies set' '
-       git config http.cookiefile cookies.txt &&
-       git config http.savecookies true &&
-       git ls-remote $HTTPD_URL/smart_cookies/repo.git master &&
-       tail -3 cookies.txt > cookies_tail.txt
-       test_cmp expect_cookies.txt cookies_tail.txt
-'
-
-test -n "$GIT_TEST_LONG" && test_set_prereq EXPENSIVE
-
-test_expect_success EXPENSIVE 'create 50,000 tags in the repo' '
-       (
-       cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
-       for i in `test_seq 50000`
-       do
-               echo "commit refs/heads/too-many-refs"
-               echo "mark :$i"
-               echo "committer git <git@example.com> $i +0000"
-               echo "data 0"
-               echo "M 644 inline bla.txt"
-               echo "data 4"
-               echo "bla"
-               # make every commit dangling by always
-               # rewinding the branch after each commit
-               echo "reset refs/heads/too-many-refs"
-               echo "from :1"
-       done | git fast-import --export-marks=marks &&
-
-       # now assign tags to all the dangling commits we created above
-       tag=$(perl -e "print \"bla\" x 30") &&
-       sed -e "s|^:\([^ ]*\) \(.*\)$|\2 refs/tags/$tag-\1|" <marks >>packed-refs
-       )
-'
-
-test_expect_success EXPENSIVE 'clone the 50,000 tag repo to check OS command line overflow' '
-       git clone $HTTPD_URL/smart/repo.git too-many-refs 2>err &&
-       test_line_count = 0 err &&
-       (
-               cd too-many-refs &&
-               test $(git for-each-ref refs/tags | wc -l) = 50000
-       )
-'
-
-stop_httpd
-test_done
index 9be9ae3436c929921bc0a2cd2a458e4e4500c154..5abd11a5638299f2d3fe41d38f9a3d10050a4e4b 100755 (executable)
@@ -9,8 +9,8 @@ test_have_prereq GREP_STRIPS_CR && export GREP_OPTIONS=-U
 
 run_backend() {
        echo "$2" |
-       QUERY_STRING="${1#*\?}" \
-       PATH_TRANSLATED="$HTTPD_DOCUMENT_ROOT_PATH/${1%%\?*}" \
+       QUERY_STRING="${1#*[?]}" \
+       PATH_TRANSLATED="$HTTPD_DOCUMENT_ROOT_PATH/${1%%[?]*}" \
        git http-backend >act.out 2>act.err
 }
 
index b5d7fbc3815aed53ec50bdf7f5dbf2c796fed1fe..d23fb0238483520e77004a208f15db808941b4af 100755 (executable)
@@ -8,7 +8,6 @@ if test -n "$NO_CURL"; then
        test_done
 fi
 
-LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5561'}
 . "$TEST_DIRECTORY"/lib-httpd.sh
 start_httpd
 
index dfee7d159b3b5198b4773f2d3869e809095b11f7..a86087be955a65d62a596f10cdbac1b6669cf2db 100755 (executable)
@@ -388,7 +388,7 @@ test_expect_failure 'git detects conflict w/ criss-cross+contrived resolution' '
 
 #
 # criss-cross + d/f conflict via add/add:
-#   Commit A: Neither file 'a' nor directory 'a/' exist.
+#   Commit A: Neither file 'a' nor directory 'a/' exists.
 #   Commit B: Introduce 'a'
 #   Commit C: Introduce 'a/file'
 #   Commit D: Merge B & C, keeping 'a' and deleting 'a/'
index a7c7ff5f4938c1fa7439e7c5a45321572bfc55fe..39fc3f6769be1c41d76c6acbfcb780b823afe7e7 100755 (executable)
@@ -69,7 +69,7 @@ test_expect_success 'tree_entry_interesting matches :(icase)bar with empty prefi
        test_cmp expect actual
 '
 
-test_expect_success 'match_pathspec_depth matches :(icase)bar' '
+test_expect_success 'match_pathspec matches :(icase)bar' '
        cat <<-EOF >expect &&
        BAR
        bAr
@@ -79,7 +79,7 @@ test_expect_success 'match_pathspec_depth matches :(icase)bar' '
        test_cmp expect actual
 '
 
-test_expect_success 'match_pathspec_depth matches :(icase)bar with prefix' '
+test_expect_success 'match_pathspec matches :(icase)bar with prefix' '
        cat <<-EOF >expect &&
        fOo/BAR
        fOo/bAr
@@ -89,7 +89,7 @@ test_expect_success 'match_pathspec_depth matches :(icase)bar with prefix' '
        test_cmp expect actual
 '
 
-test_expect_success 'match_pathspec_depth matches :(icase)bar with empty prefix' '
+test_expect_success 'match_pathspec matches :(icase)bar with empty prefix' '
        cat <<-EOF >expect &&
        bar
        fOo/BAR
index e3c8c2c1b8817acd85866470c6f76c4a4f8d17d7..c8ff9115ec51ded977bcdcef0346b9a7dbaca2e6 100755 (executable)
@@ -294,7 +294,8 @@ test_expect_success 'setup submodule' '
        git submodule add ./. sub &&
        echo content >file &&
        git add file &&
-       git commit -m "added sub and file"
+       git commit -m "added sub and file" &&
+       git branch submodule
 '
 
 test_expect_success 'git mv cannot move a submodule in a file' '
@@ -307,7 +308,7 @@ test_expect_success 'git mv moves a submodule with a .git directory and no .gitm
        (
                cd sub &&
                rm -f .git &&
-               cp -a ../.git/modules/sub .git &&
+               cp -R -P -p ../.git/modules/sub .git &&
                GIT_WORK_TREE=. git config --unset core.worktree
        ) &&
        mkdir mod &&
@@ -330,7 +331,7 @@ test_expect_success 'git mv moves a submodule with a .git directory and .gitmodu
        (
                cd sub &&
                rm -f .git &&
-               cp -a ../.git/modules/sub .git &&
+               cp -R -P -p ../.git/modules/sub .git &&
                GIT_WORK_TREE=. git config --unset core.worktree
        ) &&
        mkdir mod &&
@@ -463,4 +464,14 @@ test_expect_success 'checking out a commit before submodule moved needs manual u
        ! test -s actual
 '
 
+test_expect_success 'mv -k does not accidentally destroy submodules' '
+       git checkout submodule &&
+       mkdir dummy dest &&
+       git mv -k dummy sub dest &&
+       git status --porcelain >actual &&
+       grep "^R  sub -> dest/sub" actual &&
+       git reset --hard &&
+       git checkout .
+'
+
 test_done
index 7d467c034a27f50e8b60b4b0f390f08fdf126e55..741ec085767c9469f8ba15408af37cd558df1559 100755 (executable)
@@ -38,7 +38,7 @@ You have unmerged paths.
 Unmerged paths:
   (use "git add/rm <file>..." as appropriate to mark resolution)
 
-       deleted by us:      foo
+       deleted by us:   foo
 
 no changes added to commit (use "git add" and/or "git commit -a")
 EOF
@@ -142,8 +142,8 @@ You have unmerged paths.
 Unmerged paths:
   (use "git add/rm <file>..." as appropriate to mark resolution)
 
-       both added:         conflict.txt
-       deleted by them:    main.txt
+       both added:      conflict.txt
+       deleted by them: main.txt
 
 no changes added to commit (use "git add" and/or "git commit -a")
 EOF
@@ -175,9 +175,9 @@ You have unmerged paths.
 Unmerged paths:
   (use "git add/rm <file>..." as appropriate to mark resolution)
 
-       both deleted:       main.txt
-       added by them:      sub_master.txt
-       added by us:        sub_second.txt
+       both deleted:    main.txt
+       added by them:   sub_master.txt
+       added by us:     sub_second.txt
 
 no changes added to commit (use "git add" and/or "git commit -a")
 EOF
@@ -203,7 +203,7 @@ Changes to be committed:
 Unmerged paths:
   (use "git rm <file>..." to mark resolution)
 
-       both deleted:       main.txt
+       both deleted:    main.txt
 
 Untracked files not listed (use -u option to show untracked files)
 EOF
index 8d4b50d1b5816d69ab165119773a7ffc0c360c0a..ee117e2e727d2bcdc87053684f0c32486452a65e 100755 (executable)
@@ -535,4 +535,15 @@ test_expect_success 'reset with paths accepts tree' '
        git diff HEAD --exit-code
 '
 
+test_expect_success 'reset --mixed sets up work tree' '
+       git init mixed_worktree &&
+       (
+               cd mixed_worktree &&
+               test_commit dummy
+       ) &&
+       : >expect &&
+       git --git-dir=mixed_worktree/.git --work-tree=mixed_worktree reset >actual &&
+       test_cmp expect actual
+'
+
 test_done
index f136ee7bb5300966c0c3c9d2250dc81763db9feb..16faa0781373bb3769ce9f0fa0a09be8c2b2ed81 100755 (executable)
@@ -33,7 +33,7 @@ test_expect_success 'reset --hard should restore unmerged ones' '
 
 '
 
-test_expect_success 'reset --hard did not corrupt index nor cached-tree' '
+test_expect_success 'reset --hard did not corrupt index or cached-tree' '
 
        T=$(git write-tree) &&
        rm -f .git/index &&
index 710be90489b2fd5d6ca1a98201c1ec635efcae9f..74de814aec1465848ba316e867106a18635139f6 100755 (executable)
@@ -511,4 +511,20 @@ test_expect_success SANITY 'git clean -d with an unreadable empty directory' '
        ! test -d foo
 '
 
+test_expect_success 'git clean -d respects pathspecs (dir is prefix of pathspec)' '
+       mkdir -p foo &&
+       mkdir -p foobar &&
+       git clean -df foobar &&
+       test_path_is_dir foo &&
+       test_path_is_missing foobar
+'
+
+test_expect_success 'git clean -d respects pathspecs (pathspec is prefix of dir)' '
+       mkdir -p foo &&
+       mkdir -p foobar &&
+       git clean -df foo &&
+       test_path_is_missing foo &&
+       test_path_is_dir foobar
+'
+
 test_done
index 357375151d79d03d11275875dd10ceea42a3ba47..03dce09cfea5f1b5c19e7e8c4537a657cdf55dfc 100755 (executable)
@@ -134,14 +134,26 @@ test_expect_success 'with hook (-c)' '
 
 test_expect_success 'with hook (merge)' '
 
-       head=`git rev-parse HEAD` &&
-       git checkout -b other HEAD@{1} &&
-       echo "more" >> file &&
+       test_when_finished "git checkout -f master" &&
+       git checkout -B other HEAD@{1} &&
+       echo "more" >>file &&
+       git add file &&
+       git commit -m other &&
+       git checkout - &&
+       git merge --no-ff other &&
+       test "`git log -1 --pretty=format:%s`" = "merge (no editor)"
+'
+
+test_expect_success 'with hook and editor (merge)' '
+
+       test_when_finished "git checkout -f master" &&
+       git checkout -B other HEAD@{1} &&
+       echo "more" >>file &&
        git add file &&
        git commit -m other &&
        git checkout - &&
-       git merge other &&
-       test "`git log -1 --pretty=format:%s`" = merge
+       env GIT_EDITOR="\"\$FAKE_EDITOR\"" git merge --no-ff -e other &&
+       test "`git log -1 --pretty=format:%s`" = "merge"
 '
 
 cat > "$HOOK" <<'EOF'
@@ -151,34 +163,37 @@ EOF
 
 test_expect_success 'with failing hook' '
 
+       test_when_finished "git checkout -f master" &&
        head=`git rev-parse HEAD` &&
        echo "more" >> file &&
        git add file &&
-       ! GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -c $head
+       test_must_fail env GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -c $head
 
 '
 
 test_expect_success 'with failing hook (--no-verify)' '
 
+       test_when_finished "git checkout -f master" &&
        head=`git rev-parse HEAD` &&
        echo "more" >> file &&
        git add file &&
-       ! GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify -c $head
+       test_must_fail env GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify -c $head
 
 '
 
 test_expect_success 'with failing hook (merge)' '
 
+       test_when_finished "git checkout -f master" &&
        git checkout -B other HEAD@{1} &&
        echo "more" >> file &&
        git add file &&
        rm -f "$HOOK" &&
        git commit -m other &&
-       write_script "$HOOK" <<-EOF
+       write_script "$HOOK" <<-EOF &&
        exit 1
        EOF
        git checkout - &&
-       test_must_fail git merge other
+       test_must_fail git merge --no-ff other
 
 '
 
index 3cec57af1ee0ca8ccbbbdc47871cd4ff07e0d034..68ad2d7454d6cbc93b5f7109fe836138c95ba684 100755 (executable)
@@ -33,7 +33,7 @@ You have unmerged paths.
 Unmerged paths:
   (use "git add <file>..." to mark resolution)
 
-       both modified:      main.txt
+       both modified:   main.txt
 
 no changes added to commit (use "git add" and/or "git commit -a")
 EOF
@@ -87,7 +87,7 @@ Unmerged paths:
   (use "git reset HEAD <file>..." to unstage)
   (use "git add <file>..." to mark resolution)
 
-       both modified:      main.txt
+       both modified:   main.txt
 
 no changes added to commit (use "git add" and/or "git commit -a")
 EOF
@@ -146,7 +146,7 @@ Unmerged paths:
   (use "git reset HEAD <file>..." to unstage)
   (use "git add <file>..." to mark resolution)
 
-       both modified:      main.txt
+       both modified:   main.txt
 
 no changes added to commit (use "git add" and/or "git commit -a")
 EOF
@@ -602,7 +602,7 @@ rebase in progress; onto $ONTO
 You are currently rebasing branch '\''statushints_disabled'\'' on '\''$ONTO'\''.
 
 Unmerged paths:
-       both modified:      main.txt
+       both modified:   main.txt
 
 no changes added to commit
 EOF
@@ -636,7 +636,7 @@ You are currently cherry-picking commit $TO_CHERRY_PICK.
 Unmerged paths:
   (use "git add <file>..." to mark resolution)
 
-       both modified:      main.txt
+       both modified:   main.txt
 
 no changes added to commit (use "git add" and/or "git commit -a")
 EOF
@@ -707,7 +707,7 @@ Unmerged paths:
   (use "git reset HEAD <file>..." to unstage)
   (use "git add <file>..." to mark resolution)
 
-       both modified:      to-revert.txt
+       both modified:   to-revert.txt
 
 no changes added to commit (use "git add" and/or "git commit -a")
 EOF
diff --git a/t/t7514-commit-patch.sh b/t/t7514-commit-patch.sh
new file mode 100755 (executable)
index 0000000..998a210
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+test_description='hunk edit with "commit -p -m"'
+. ./test-lib.sh
+
+if ! test_have_prereq PERL
+then
+       skip_all="skipping '$test_description' tests, perl not available"
+       test_done
+fi
+
+test_expect_success 'setup (initial)' '
+       echo line1 >file &&
+       git add file &&
+       git commit -m commit1
+'
+
+test_expect_success 'edit hunk "commit -p -m message"' '
+       test_when_finished "rm -f editor_was_started" &&
+       rm -f editor_was_started &&
+       echo more >>file &&
+       echo e | env GIT_EDITOR=": >editor_was_started" git commit -p -m commit2 file &&
+       test -r editor_was_started
+'
+
+test_expect_success 'edit hunk "commit --dry-run -p -m message"' '
+       test_when_finished "rm -f editor_was_started" &&
+       rm -f editor_was_started &&
+       echo more >>file &&
+       echo e | env GIT_EDITOR=": >editor_was_started" git commit -p -m commit3 file &&
+       test -r editor_was_started
+'
+
+test_done
index 2418528487624bf5497af71c9958a84e0a50328f..5a193c500d282cc2b13e8de6e128229585897a16 100755 (executable)
@@ -434,4 +434,18 @@ test_expect_success PERL 'difftool --no-symlinks detects conflict ' '
        )
 '
 
+test_expect_success PERL 'difftool properly honors gitlink and core.worktree' '
+       git submodule add ./. submod/ule &&
+       (
+               cd submod/ule &&
+               test_config diff.tool checktrees &&
+               test_config difftool.checktrees.cmd '\''
+                       test -d "$LOCAL" && test -d "$REMOTE" && echo good
+               '\'' &&
+               echo good >expect &&
+               git difftool --tool=checktrees --dir-diff HEAD~ >actual &&
+               test_cmp expect actual
+       )
+'
+
 test_done
index 3edc4086d860e38e4dddab97a223071ab8e3cfc0..1f06e25db6451150ff0a066e0d342414301433a3 100755 (executable)
@@ -512,7 +512,7 @@ test_expect_success 'cvs co -c (shows module database)' '
 # Known issues with git-cvsserver current log output:
 #  - Hard coded "lines: +2 -3" placeholder, instead of real numbers.
 #  - CVS normally does not internally add a blank first line
-#    nor a last line with nothing but a space to log messages.
+#    or a last line with nothing but a space to log messages.
 #  - The latest cvs 1.12.x server sends +0000 timezone (with some hidden "MT"
 #    tagging in the protocol), and if cvs 1.12.x client sees the MT tags,
 #    it converts to local time zone.  git-cvsserver doesn't do the +0000
index 1531c241c08f0fad1a8e0789dbed2675b0fe5e56..3c7cb1d774cadaa4d625e2d53ba122db4108cb0e 100644 (file)
@@ -277,7 +277,7 @@ error "Test script did not set test_description."
 
 if test "$help" = "t"
 then
-       echo "$test_description"
+       printf '%s\n' "$test_description"
        exit 0
 fi
 
@@ -328,7 +328,7 @@ test_failure_ () {
        test_failure=$(($test_failure + 1))
        say_color error "not ok $test_count - $1"
        shift
-       echo "$@" | sed -e 's/^/#       /'
+       printf '%s\n' "$*" | sed -e 's/^/#      /'
        test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; }
 }
 
index 0df748784bb7f6b6f286dd37ada293df17cffeee..dfe8a83261b3623e64f99ddf8dc775616771ec4d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This program can either change modification time of the given
- * file(s) or just print it. The program does not change atime nor
+ * file(s) or just print it. The program does not change atime or
  * ctime (their values are explicitly preserved).
  *
  * The mtime can be changed to an absolute value:
index 0c44f6b292563e7c87bce0b7b5d9b8a4ccd32ec3..a3c52f691da5e5ce95d70a9ed43cffd00f620ccd 100644 (file)
@@ -81,7 +81,7 @@ static void create_pack_file(void)
        const char *argv[12];
        int i, arg = 0;
        FILE *pipe_fd;
-       char *shallow_file = NULL;
+       const char *shallow_file = NULL;
 
        if (shallow_nr) {
                shallow_file = setup_temporary_shallow(NULL);
@@ -242,11 +242,6 @@ static void create_pack_file(void)
                error("git upload-pack: git-pack-objects died with error.");
                goto fail;
        }
-       if (shallow_file) {
-               if (*shallow_file)
-                       unlink(shallow_file);
-               free(shallow_file);
-       }
 
        /* flush the data */
        if (0 <= buffered) {
index 4e5581005936a1e7832e3ab224cfe142ac777a63..9bf96c3af064bcc71ea62c97018312bd084e9273 100644 (file)
@@ -245,53 +245,92 @@ static void wt_status_print_trailer(struct wt_status *s)
 
 #define quote_path quote_path_relative
 
-static void wt_status_print_unmerged_data(struct wt_status *s,
-                                         struct string_list_item *it)
+static const char *wt_status_unmerged_status_string(int stagemask)
 {
-       const char *c = color(WT_STATUS_UNMERGED, s);
-       struct wt_status_change_data *d = it->util;
-       struct strbuf onebuf = STRBUF_INIT;
-       const char *one, *how = _("bug");
-
-       one = quote_path(it->string, s->prefix, &onebuf);
-       status_printf(s, color(WT_STATUS_HEADER, s), "\t");
-       switch (d->stagemask) {
-       case 1: how = _("both deleted:"); break;
-       case 2: how = _("added by us:"); break;
-       case 3: how = _("deleted by them:"); break;
-       case 4: how = _("added by them:"); break;
-       case 5: how = _("deleted by us:"); break;
-       case 6: how = _("both added:"); break;
-       case 7: how = _("both modified:"); break;
+       switch (stagemask) {
+       case 1:
+               return _("both deleted:");
+       case 2:
+               return _("added by us:");
+       case 3:
+               return _("deleted by them:");
+       case 4:
+               return _("added by them:");
+       case 5:
+               return _("deleted by us:");
+       case 6:
+               return _("both added:");
+       case 7:
+               return _("both modified:");
+       default:
+               die(_("bug: unhandled unmerged status %x"), stagemask);
        }
-       status_printf_more(s, c, "%-20s%s\n", how, one);
-       strbuf_release(&onebuf);
 }
 
 static const char *wt_status_diff_status_string(int status)
 {
        switch (status) {
        case DIFF_STATUS_ADDED:
-               return _("new file");
+               return _("new file:");
        case DIFF_STATUS_COPIED:
-               return _("copied");
+               return _("copied:");
        case DIFF_STATUS_DELETED:
-               return _("deleted");
+               return _("deleted:");
        case DIFF_STATUS_MODIFIED:
-               return _("modified");
+               return _("modified:");
        case DIFF_STATUS_RENAMED:
-               return _("renamed");
+               return _("renamed:");
        case DIFF_STATUS_TYPE_CHANGED:
-               return _("typechange");
+               return _("typechange:");
        case DIFF_STATUS_UNKNOWN:
-               return _("unknown");
+               return _("unknown:");
        case DIFF_STATUS_UNMERGED:
-               return _("unmerged");
+               return _("unmerged:");
        default:
                return NULL;
        }
 }
 
+static int maxwidth(const char *(*label)(int), int minval, int maxval)
+{
+       int result = 0, i;
+
+       for (i = minval; i <= maxval; i++) {
+               const char *s = label(i);
+               int len = s ? utf8_strwidth(s) : 0;
+               if (len > result)
+                       result = len;
+       }
+       return result;
+}
+
+static void wt_status_print_unmerged_data(struct wt_status *s,
+                                         struct string_list_item *it)
+{
+       const char *c = color(WT_STATUS_UNMERGED, s);
+       struct wt_status_change_data *d = it->util;
+       struct strbuf onebuf = STRBUF_INIT;
+       static char *padding;
+       static int label_width;
+       const char *one, *how;
+       int len;
+
+       if (!padding) {
+               label_width = maxwidth(wt_status_unmerged_status_string, 1, 7);
+               label_width += strlen(" ");
+               padding = xmallocz(label_width);
+               memset(padding, ' ', label_width);
+       }
+
+       one = quote_path(it->string, s->prefix, &onebuf);
+       status_printf(s, color(WT_STATUS_HEADER, s), "\t");
+
+       how = wt_status_unmerged_status_string(d->stagemask);
+       len = label_width - utf8_strwidth(how);
+       status_printf_more(s, c, "%s%.*s%s\n", how, len, padding, one);
+       strbuf_release(&onebuf);
+}
+
 static void wt_status_print_change_data(struct wt_status *s,
                                        int change_type,
                                        struct string_list_item *it)
@@ -305,21 +344,16 @@ static void wt_status_print_change_data(struct wt_status *s,
        struct strbuf onebuf = STRBUF_INIT, twobuf = STRBUF_INIT;
        struct strbuf extra = STRBUF_INIT;
        static char *padding;
+       static int label_width;
        const char *what;
        int len;
 
        if (!padding) {
-               int width = 0;
-               /* If DIFF_STATUS_* uses outside this range, we're in trouble */
-               for (status = 'A'; status <= 'Z'; status++) {
-                       what = wt_status_diff_status_string(status);
-                       len = what ? strlen(what) : 0;
-                       if (len > width)
-                               width = len;
-               }
-               width += 2;     /* colon and a space */
-               padding = xmallocz(width);
-               memset(padding, ' ', width);
+               /* If DIFF_STATUS_* uses outside the range [A..Z], we're in trouble */
+               label_width = maxwidth(wt_status_diff_status_string, 'A', 'Z');
+               label_width += strlen(" ");
+               padding = xmallocz(label_width);
+               memset(padding, ' ', label_width);
        }
 
        one_name = two_name = it->string;
@@ -355,14 +389,13 @@ static void wt_status_print_change_data(struct wt_status *s,
        what = wt_status_diff_status_string(status);
        if (!what)
                die(_("bug: unhandled diff status %c"), status);
-       /* 1 for colon, which is not part of "what" */
-       len = strlen(padding) - (utf8_strwidth(what) + 1);
+       len = label_width - utf8_strwidth(what);
        assert(len >= 0);
        if (status == DIFF_STATUS_COPIED || status == DIFF_STATUS_RENAMED)
-               status_printf_more(s, c, "%s:%.*s%s -> %s",
+               status_printf_more(s, c, "%s%.*s%s -> %s",
                                   what, len, padding, one, two);
        else
-               status_printf_more(s, c, "%s:%.*s%s",
+               status_printf_more(s, c, "%s%.*s%s",
                                   what, len, padding, one);
        if (extra.len) {
                status_printf_more(s, color(WT_STATUS_HEADER, s), "%s", extra.buf);
@@ -510,7 +543,7 @@ static void wt_status_collect_changes_initial(struct wt_status *s)
                struct wt_status_change_data *d;
                const struct cache_entry *ce = active_cache[i];
 
-               if (!ce_path_match(ce, &s->pathspec))
+               if (!ce_path_match(ce, &s->pathspec, NULL))
                        continue;
                it = string_list_insert(&s->change, ce->name);
                d = it->util;
@@ -552,7 +585,7 @@ static void wt_status_collect_untracked(struct wt_status *s)
        for (i = 0; i < dir.nr; i++) {
                struct dir_entry *ent = dir.entries[i];
                if (cache_name_is_other(ent->name, ent->len) &&
-                   match_pathspec_depth(&s->pathspec, ent->name, ent->len, 0, NULL))
+                   dir_path_match(ent, &s->pathspec, 0, NULL))
                        string_list_insert(&s->untracked, ent->name);
                free(ent);
        }
@@ -560,7 +593,7 @@ static void wt_status_collect_untracked(struct wt_status *s)
        for (i = 0; i < dir.ignored_nr; i++) {
                struct dir_entry *ent = dir.ignored[i];
                if (cache_name_is_other(ent->name, ent->len) &&
-                   match_pathspec_depth(&s->pathspec, ent->name, ent->len, 0, NULL))
+                   dir_path_match(ent, &s->pathspec, 0, NULL))
                        string_list_insert(&s->ignored, ent->name);
                free(ent);
        }
@@ -1509,19 +1542,21 @@ static void wt_shortstatus_print_tracking(struct wt_status *s)
                return;
        }
 
+#define LABEL(string) (s->no_gettext ? (string) : _(string))
+
        color_fprintf(s->fp, header_color, " [");
        if (upstream_is_gone) {
-               color_fprintf(s->fp, header_color, _("gone"));
+               color_fprintf(s->fp, header_color, LABEL(N_("gone")));
        } else if (!num_ours) {
-               color_fprintf(s->fp, header_color, _("behind "));
+               color_fprintf(s->fp, header_color, LABEL(N_("behind ")));
                color_fprintf(s->fp, branch_color_remote, "%d", num_theirs);
        } else if (!num_theirs) {
-               color_fprintf(s->fp, header_color, _("ahead "));
+               color_fprintf(s->fp, header_color, LABEL(N_(("ahead "))));
                color_fprintf(s->fp, branch_color_local, "%d", num_ours);
        } else {
-               color_fprintf(s->fp, header_color, _("ahead "));
+               color_fprintf(s->fp, header_color, LABEL(N_(("ahead "))));
                color_fprintf(s->fp, branch_color_local, "%d", num_ours);
-               color_fprintf(s->fp, header_color, _(", behind "));
+               color_fprintf(s->fp, header_color, ", %s", LABEL(N_("behind ")));
                color_fprintf(s->fp, branch_color_remote, "%d", num_theirs);
        }
 
@@ -1566,5 +1601,6 @@ void wt_porcelain_print(struct wt_status *s)
        s->use_color = 0;
        s->relative_paths = 0;
        s->prefix = NULL;
+       s->no_gettext = 1;
        wt_shortstatus_print(s);
 }
index 30a481258366733ad5d6a65e3a9c3ae1ee74e833..82f6ce64f8312f9d02e6dc08d46ec8af96a311a3 100644 (file)
@@ -50,6 +50,7 @@ struct wt_status {
        enum commit_whence whence;
        int nowarn;
        int use_color;
+       int no_gettext;
        int display_comment_prefix;
        int relative_paths;
        int submodule_summary;