summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/CodingGuidelines2
-rw-r--r--Documentation/RelNotes/1.7.4.1.txt27
-rw-r--r--Documentation/RelNotes/1.7.4.2.txt58
-rw-r--r--Documentation/RelNotes/1.7.4.3.txt32
-rw-r--r--Documentation/SubmittingPatches26
-rw-r--r--Documentation/config.txt14
-rw-r--r--Documentation/diff-generate-patch.txt11
-rw-r--r--Documentation/fetch-options.txt2
-rw-r--r--Documentation/git-am.txt6
-rw-r--r--Documentation/git-apply.txt2
-rw-r--r--Documentation/git-bisect.txt68
-rw-r--r--Documentation/git-commit.txt12
-rw-r--r--Documentation/git-diff.txt2
-rw-r--r--Documentation/git-fast-import.txt7
-rw-r--r--Documentation/git-filter-branch.txt2
-rw-r--r--Documentation/git-for-each-ref.txt18
-rw-r--r--Documentation/git-grep.txt1
-rw-r--r--Documentation/git-ls-remote.txt2
-rw-r--r--Documentation/git-pack-objects.txt11
-rw-r--r--Documentation/git-pull.txt9
-rw-r--r--Documentation/git-remote-ext.txt14
-rw-r--r--Documentation/git-remote-helpers.txt6
-rw-r--r--Documentation/git-status.txt16
-rw-r--r--Documentation/git-svn.txt6
-rw-r--r--Documentation/git-tag.txt47
-rw-r--r--Documentation/git-verify-pack.txt2
-rw-r--r--Documentation/git.txt3
-rw-r--r--Documentation/gitattributes.txt10
-rw-r--r--Documentation/howto/using-merge-subtree.txt2
-rw-r--r--Documentation/rev-list-options.txt2
-rw-r--r--Documentation/technical/index-format.txt185
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--Makefile2
l---------RelNotes2
-rw-r--r--abspath.c4
-rw-r--r--aclocal.m44
-rw-r--r--branch.c11
-rw-r--r--builtin/add.c5
-rw-r--r--builtin/apply.c23
-rw-r--r--builtin/blame.c3
-rw-r--r--builtin/branch.c50
-rw-r--r--builtin/checkout.c25
-rw-r--r--builtin/clone.c8
-rw-r--r--builtin/commit.c24
-rw-r--r--builtin/config.c29
-rw-r--r--builtin/describe.c4
-rw-r--r--builtin/diff.c7
-rw-r--r--builtin/fast-export.c4
-rw-r--r--builtin/fetch.c6
-rw-r--r--builtin/fsck.c31
-rw-r--r--builtin/grep.c5
-rw-r--r--builtin/index-pack.c6
-rw-r--r--builtin/init-db.c14
-rw-r--r--builtin/log.c42
-rw-r--r--builtin/merge.c39
-rw-r--r--builtin/notes.c16
-rw-r--r--builtin/patch-id.c2
-rw-r--r--builtin/push.c10
-rw-r--r--builtin/read-tree.c4
-rw-r--r--builtin/tag.c6
-rw-r--r--bundle.c5
-rw-r--r--cache.h13
-rw-r--r--commit.c6
-rw-r--r--commit.h5
-rw-r--r--compat/bswap.h18
-rw-r--r--compat/mingw.h16
-rw-r--r--config.c127
-rw-r--r--configure.ac56
-rwxr-xr-xcontrib/hooks/post-receive-email2
-rw-r--r--contrib/svn-fe/svn-fe.txt3
-rwxr-xr-xcontrib/thunderbird-patch-inline/appp.sh4
-rw-r--r--convert.c2
-rw-r--r--diff-lib.c3
-rw-r--r--diff.c37
-rw-r--r--diffcore-rename.c69
-rw-r--r--environment.c1
-rw-r--r--fast-import.c45
-rw-r--r--fetch-pack.h3
-rwxr-xr-xgenerate-cmdlist.sh3
-rwxr-xr-xgit-bisect.sh10
-rw-r--r--git-compat-util.h12
-rwxr-xr-xgit-cvsimport.perl4
-rwxr-xr-xgit-instaweb.sh6
-rw-r--r--git-mergetool--lib.sh4
-rw-r--r--git-parse-remote.sh3
-rwxr-xr-xgit-pull.sh2
-rwxr-xr-xgit-stash.sh14
-rwxr-xr-xgit-submodule.sh9
-rw-r--r--gitweb/INSTALL6
-rwxr-xr-xgitweb/gitweb.perl19
-rw-r--r--hash.c4
-rw-r--r--hash.h2
-rw-r--r--http-push.c15
-rw-r--r--http-walker.c6
-rw-r--r--http.h15
-rw-r--r--list-objects.c7
-rw-r--r--merge-recursive.c12
-rw-r--r--notes-merge.c2
-rw-r--r--pack-check.c3
-rw-r--r--parse-options.h2
-rw-r--r--patch-delta.c2
-rw-r--r--perl/Git.pm25
-rw-r--r--pretty.c36
-rw-r--r--quote.h3
-rw-r--r--run-command.c2
-rw-r--r--sha1_file.c162
-rw-r--r--sha1_name.c4
-rw-r--r--strbuf.c5
-rw-r--r--strbuf.h37
-rw-r--r--string-list.c1
-rw-r--r--string-list.h3
-rw-r--r--submodule.c103
-rw-r--r--symlinks.c2
-rw-r--r--t/README18
-rw-r--r--t/gitweb-lib.sh7
-rw-r--r--t/lib-terminal.sh22
-rwxr-xr-xt/t0040-parse-options.sh2
-rwxr-xr-xt/t0070-fundamental.sh13
-rwxr-xr-xt/t1300-repo-config.sh22
-rwxr-xr-xt/t2019-checkout-ambiguous-ref.sh59
-rwxr-xr-xt/t2021-checkout-overwrite.sh50
-rwxr-xr-xt/t3200-branch.sh14
-rwxr-xr-xt/t3509-cherry-pick-merge-df.sh6
-rwxr-xr-xt/t3903-stash.sh19
-rwxr-xr-xt/t4003-diff-rename-1.sh2
-rwxr-xr-xt/t4004-diff-rename-symlink.sh2
-rwxr-xr-xt/t4005-diff-rename-2.sh2
-rwxr-xr-xt/t4008-diff-break-rewrite.sh4
-rwxr-xr-xt/t4009-diff-rename-4.sh2
-rwxr-xr-xt/t4013-diff-various.sh14
-rw-r--r--t/t4013/diff.diff_--cached38
-rw-r--r--t/t4013/diff.diff_--cached_--_file015
-rw-r--r--t/t4013/diff.log_-SF_master_--max-count=02
-rw-r--r--t/t4013/diff.log_-SF_master_--max-count=17
-rw-r--r--t/t4013/diff.log_-SF_master_--max-count=27
-rwxr-xr-xt/t4014-format-patch.sh84
-rwxr-xr-xt/t4031-diff-rewrite-binary.sh7
-rwxr-xr-xt/t4040-whitespace-status.sh7
-rwxr-xr-xt/t4120-apply-popt.sh9
-rwxr-xr-xt/t4204-patch-id.sh36
-rwxr-xr-xt/t5526-fetch-submodules.sh2
-rwxr-xr-xt/t5701-clone-local.sh13
-rwxr-xr-xt/t6035-merge-dir-to-symlink.sh14
-rwxr-xr-xt/t6040-tracking-info.sh16
-rwxr-xr-xt/t6110-rev-list-sparse.sh27
-rwxr-xr-xt/t7201-co.sh16
-rwxr-xr-xt/t7406-submodule-update.sh52
-rwxr-xr-xt/t7407-submodule-foreach.sh4
-rwxr-xr-xt/t7500-commit.sh21
-rwxr-xr-xt/t7505-prepare-commit-msg-hook.sh12
-rwxr-xr-xt/t8001-annotate.sh11
-rwxr-xr-xt/t8006-blame-textconv.sh3
-rwxr-xr-xt/t9301-fast-import-notes.sh1
-rwxr-xr-xt/t9500-gitweb-standalone-no-errors.sh86
-rwxr-xr-xt/t9501-gitweb-standalone-http-status.sh1
-rwxr-xr-xt/t9700/test.pl10
-rw-r--r--t/test-lib.sh6
-rw-r--r--t/valgrind/default.supp6
-rw-r--r--tag.c8
-rw-r--r--tag.h2
-rw-r--r--test-mktemp.c14
-rw-r--r--test-parse-options.c2
-rw-r--r--transport-helper.c3
-rw-r--r--utf8.c9
-rw-r--r--utf8.h2
-rw-r--r--wrapper.c34
166 files changed, 1952 insertions, 846 deletions
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines
index ba2006d892..fe1c1e5bc2 100644
--- a/Documentation/CodingGuidelines
+++ b/Documentation/CodingGuidelines
@@ -152,7 +152,7 @@ Writing Documentation:
when writing or modifying command usage strings and synopsis sections
in the manual pages:
- Placeholders are enclosed in angle brackets:
+ Placeholders are spelled in lowercase and enclosed in angle brackets:
<file>
--sort=<key>
--abbrev[=<n>]
diff --git a/Documentation/RelNotes/1.7.4.1.txt b/Documentation/RelNotes/1.7.4.1.txt
new file mode 100644
index 0000000000..79923a6d2f
--- /dev/null
+++ b/Documentation/RelNotes/1.7.4.1.txt
@@ -0,0 +1,27 @@
+Git v1.7.4.1 Release Notes
+==========================
+
+Fixes since v1.7.4
+------------------
+
+ * On Windows platform, the codepath to spawn a new child process forgot
+ to first flush the output buffer.
+
+ * "git bundle" did not use OFS_DELTA encoding, making its output a few
+ per-cent larger than necessarily.
+
+ * The option to tell "git clone" to recurse into the submodules was
+ misspelled with an underscore "--recurse_submodules".
+
+ * "git diff --cached HEAD" before the first commit does what an end user
+ would expect (namely, show what would be committed without further "git
+ add").
+
+ * "git fast-import" didn't accept the command to ask for "notes" feature
+ to be present in its input stream, even though it was capable of the
+ feature.
+
+ * "git fsck" gave up scanning loose object files in directories with
+ garbage files.
+
+And other minor fixes and documentation updates.
diff --git a/Documentation/RelNotes/1.7.4.2.txt b/Documentation/RelNotes/1.7.4.2.txt
new file mode 100644
index 0000000000..ef4ce1fcd3
--- /dev/null
+++ b/Documentation/RelNotes/1.7.4.2.txt
@@ -0,0 +1,58 @@
+Git v1.7.4.2 Release Notes
+==========================
+
+Fixes since v1.7.4.1
+--------------------
+
+ * Many documentation updates to match "git cmd -h" output and the
+ git-cmd manual page.
+
+ * We used to keep one file descriptor open for each and every packfile
+ that we have a mmap window on it (read: "in use"), even when for very
+ tiny packfiles. We now close the file descriptor early when the entire
+ packfile fits inside one mmap window.
+
+ * "git bisect visualize" tried to run "gitk" in windowing
+ environments even when "gitk" is not installed, resulting in a
+ strange error message.
+
+ * "git clone /no/such/path" did not fail correctly.
+
+ * "git commit" did not correctly error out when the user asked to use a
+ non existent file as the commit message template.
+
+ * "git diff --stat -B" ran on binary files counted the changes in lines,
+ which was nonsensical.
+
+ * "git diff -M" opportunistically detected copies, which was not
+ necessarily a good thing, especially when it is internally run by
+ recursive merge.
+
+ * "git difftool" didn't tell (g)vimdiff that the files it is reading are
+ to be opened read-only.
+
+ * "git merge" didn't pay attention to prepare-commit-msg hook, even
+ though if a merge is conflicted and manually resolved, the subsequent
+ "git commit" would have triggered the hook, which was inconsistent.
+
+ * "git patch-id" (and commands like "format-patch --ignore-in-upstream"
+ that use it as their internal logic) handled changes to files that end
+ with incomplete lines incorrectly.
+
+ * The official value to tell "git push" to push the current branch back
+ to update the upstream branch it forked from is now called "upstream".
+ The old name "tracking" is and will be supported.
+
+ * "git submodule update" used to honor the --merge/--rebase option (or
+ corresponding configuration variables) even for a newly cloned
+ subproject, which made no sense (so/submodule-no-update-first-time).
+
+ * gitweb's "highlight" interface mishandled tabs.
+
+ * gitweb didn't understand timezones with GMT offset that is not
+ multiple of a whole hour.
+
+ * gitweb had a few forward-incompatible syntactic constructs and
+ also used incorrect variable when showing the file mode in a diff.
+
+And other minor fixes and documentation updates.
diff --git a/Documentation/RelNotes/1.7.4.3.txt b/Documentation/RelNotes/1.7.4.3.txt
new file mode 100644
index 0000000000..02a3d5bdf6
--- /dev/null
+++ b/Documentation/RelNotes/1.7.4.3.txt
@@ -0,0 +1,32 @@
+Git v1.7.4.3 Release Notes
+==========================
+
+Fixes since v1.7.4.2
+--------------------
+
+ * "git apply" used to confuse lines updated by previous hunks as lines
+ that existed before when applying a hunk, contributing misapplication
+ of patches with offsets.
+
+ * "git branch --track" (and "git checkout --track --branch") used to
+ allow setting up a random non-branch that does not make sense to follow
+ as the "upstream". The command correctly diagnoses it as an error.
+
+ * "git checkout $other_branch" silently removed untracked symbolic links
+ in the working tree that are in the way in order to check out paths
+ under it from the named branch.
+
+ * "git cvsimport" did not bail out immediately when the cvs server cannot
+ be reached, spewing unnecessary error messages that complain about the
+ server response that it never got.
+
+ * "git diff --quiet" did not work very well with the "--diff-filter"
+ option.
+
+ * "git grep -n" lacked a long-hand synonym --line-number.
+
+ * "git stash apply" reported the result of its operation by running
+ "git status" from the top-level of the working tree; it should (and
+ now does) run it from the user's working directory.
+
+And other minor fixes and documentation updates.
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 72741ebda1..c3b0816ed7 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -10,10 +10,18 @@ Checklist (and a short version for the impatient):
description (50 characters is the soft limit, see DISCUSSION
in git-commit(1)), and should skip the full stop
- the body should provide a meaningful commit message, which:
- - uses the imperative, present tense: "change",
- not "changed" or "changes".
- - includes motivation for the change, and contrasts
- its implementation with previous behaviour
+ . explains the problem the change tries to solve, iow, what
+ is wrong with the current code without the change.
+ . justifies the way the change solves the problem, iow, why
+ the result with the change is better.
+ . alternate solutions considered but discarded, if any.
+ - describe changes in imperative mood, e.g. "make xyzzy do frotz"
+ instead of "[This patch] makes xyzzy do frotz" or "[I] changed
+ xyzzy to do frotz", as if you are giving orders to the codebase
+ to change its behaviour.
+ - try to make sure your explanation can be understood without
+ external resources. Instead of giving a URL to a mailing list
+ archive, summarize the relevant points of the discussion.
- add a "Signed-off-by: Your Name <you@example.com>" line to the
commit message (or just use the option "-s" when committing)
to confirm that you agree to the Developer's Certificate of Origin
@@ -90,7 +98,10 @@ your commit head. Instead, always make a commit with complete
commit message and generate a series of patches from your
repository. It is a good discipline.
-Describe the technical detail of the change(s).
+Give an explanation for the change(s) that is detailed enough so
+that people can judge if it is good thing to do, without reading
+the actual patch text to determine how well the code does what
+the explanation promises to do.
If your description starts to get too long, that's a sign that you
probably need to split up your commit to finer grained pieces.
@@ -99,9 +110,8 @@ help reviewers check the patch, and future maintainers understand
the code, are the most beautiful patches. Descriptions that summarise
the point in the subject well, and describe the motivation for the
change, the approach taken by the change, and if relevant how this
-differs substantially from the prior version, can be found on Usenet
-archives back into the late 80's. Consider it like good Netiquette,
-but for code.
+differs substantially from the prior version, are all good things
+to have.
Oh, another thing. I am picky about whitespaces. Make sure your
changes do not trigger errors with the sample pre-commit hook shipped
diff --git a/Documentation/config.txt b/Documentation/config.txt
index dacbcdeb79..52ffbf4efb 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -62,7 +62,7 @@ Internal whitespace within a variable value is retained verbatim.
The values following the equals sign in variable assign are all either
a string, an integer, or a boolean. Boolean values may be given as yes/no,
-0/1, true/false or on/off. Case is not significant in boolean values, when
+1/0, true/false or on/off. Case is not significant in boolean values, when
converting value to the canonical form using '--bool' type specifier;
'git config' will ensure that the output is "true" or "false".
@@ -376,15 +376,6 @@ core.warnAmbiguousRefs::
If true, git will warn you if the ref name you passed it is ambiguous
and might match multiple refs in the .git/refs/ tree. True by default.
-core.abbrevguard::
- Even though git makes sure that it uses enough hexdigits to show
- an abbreviated object name unambiguously, as more objects are
- added to the repository over time, a short name that used to be
- unique will stop being unique. Git uses this many extra hexdigits
- that are more than necessary to make the object name currently
- unique, in the hope that its output will stay unique a bit longer.
- Defaults to 0.
-
core.compression::
An integer -1..9, indicating a default compression level.
-1 is the zlib default. 0 means no compression,
@@ -1597,7 +1588,8 @@ push.default::
* `matching` - push all matching branches.
All branches having the same name in both ends are considered to be
matching. This is the default.
-* `tracking` - push the current branch to its upstream branch.
+* `upstream` - push the current branch to its upstream branch.
+* `tracking` - deprecated synonym for `upstream`.
* `current` - push the current branch to a branch of the same name.
rebase.stat::
diff --git a/Documentation/diff-generate-patch.txt b/Documentation/diff-generate-patch.txt
index 3ac2beac62..c57460c03d 100644
--- a/Documentation/diff-generate-patch.txt
+++ b/Documentation/diff-generate-patch.txt
@@ -74,10 +74,13 @@ separate lines indicate the old and the new mode.
combined diff format
--------------------
-"git-diff-tree", "git-diff-files" and "git-diff" can take '-c' or
-'--cc' option to produce 'combined diff'. For showing a merge commit
-with "git log -p", this is the default format; you can force showing
-full diff with the '-m' option.
+Any diff-generating command can take the `-c` or `--cc` option to
+produce a 'combined diff' when showing a merge. This is the default
+format when showing merges with linkgit:git-diff[1] or
+linkgit:git-show[1]. Note also that you can give the `-m' option to any
+of these commands to force generation of diffs with individual parents
+of a merge.
+
A 'combined diff' format looks like this:
------------
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index 695696da1b..f37276e5ad 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -64,13 +64,11 @@ ifndef::git-pull[]
downloaded. The default behavior for a remote may be
specified with the remote.<name>.tagopt setting. See
linkgit:git-config[1].
-endif::git-pull[]
--[no-]recurse-submodules::
This option controls if new commits of all populated submodules should
be fetched too (see linkgit:git-config[1] and linkgit:gitmodules[5]).
-ifndef::git-pull[]
--submodule-prefix=<path>::
Prepend <path> to paths printed in informative messages
such as "Fetching submodule foo". This option is used
diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 51297d09ec..4d37de639d 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -173,9 +173,9 @@ aborts in the middle. You can recover from this in one of two ways:
the index file to bring it into a state that the patch should
have produced. Then run the command with the '--resolved' option.
-The command refuses to process new mailboxes while the `.git/rebase-apply`
-directory exists, so if you decide to start over from scratch,
-run `rm -f -r .git/rebase-apply` before running the command with mailbox
+The command refuses to process new mailboxes until the current
+operation is finished, so if you decide to start over from scratch,
+run `git am --abort` before running the command with mailbox
names.
Before any patches are applied, ORIG_HEAD is set to the tip of the
diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt
index 881652f490..2dcfc097d3 100644
--- a/Documentation/git-apply.txt
+++ b/Documentation/git-apply.txt
@@ -22,7 +22,7 @@ DESCRIPTION
-----------
Reads the supplied diff output (i.e. "a patch") and applies it to files.
With the `--index` option the patch is also applied to the index, and
-with the `--cache` option the patch is only applied to the index.
+with the `--cached` option the patch is only applied to the index.
Without these options, the command applies the patch only to files,
and does not require them to be in a git repository.
diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt
index c39d957c3a..c443e0f307 100644
--- a/Documentation/git-bisect.txt
+++ b/Documentation/git-bisect.txt
@@ -241,7 +241,12 @@ exit(3) manual page), as the value is chopped with "& 0377".
The special exit code 125 should be used when the current source code
cannot be tested. If the script exits with this code, the current
-revision will be skipped (see `git bisect skip` above).
+revision will be skipped (see `git bisect skip` above). 125 was chosen
+as the highest sensible value to use for this purpose, because 126 and 127
+are used by POSIX shells to signal specific error status (127 is for
+command not found, 126 is for command found but not executable---these
+details do not matter, as they are normal errors in the script, as far as
+"bisect run" is concerned).
You may often find that during a bisect session you want to have
temporary modifications (e.g. s/#define DEBUG 0/#define DEBUG 1/ in a
@@ -274,53 +279,68 @@ $ git bisect start HEAD origin -- # HEAD is bad, origin is good
$ git bisect run make test # "make test" builds and tests
------------
-* Automatically bisect a broken test suite:
+* Automatically bisect a broken test case:
+
------------
$ cat ~/test.sh
#!/bin/sh
-make || exit 125 # this skips broken builds
-make test # "make test" runs the test suite
-$ git bisect start v1.3 v1.1 -- # v1.3 is bad, v1.1 is good
+make || exit 125 # this skips broken builds
+~/check_test_case.sh # does the test case pass?
+$ git bisect start HEAD HEAD~10 -- # culprit is among the last 10
$ git bisect run ~/test.sh
------------
+
Here we use a "test.sh" custom script. In this script, if "make"
fails, we skip the current commit.
+"check_test_case.sh" should "exit 0" if the test case passes,
+and "exit 1" otherwise.
+
-It is safer to use a custom script outside the repository to prevent
-interactions between the bisect, make and test processes and the
-script.
-+
-"make test" should "exit 0", if the test suite passes, and
-"exit 1" otherwise.
+It is safer if both "test.sh" and "check_test_case.sh" are
+outside the repository to prevent interactions between the bisect,
+make and test processes and the scripts.
-* Automatically bisect a broken test case:
+* Automatically bisect with temporary modifications (hot-fix):
+
------------
$ cat ~/test.sh
#!/bin/sh
-make || exit 125 # this skips broken builds
-~/check_test_case.sh # does the test case passes ?
-$ git bisect start HEAD HEAD~10 -- # culprit is among the last 10
-$ git bisect run ~/test.sh
+
+# tweak the working tree by merging the hot-fix branch
+# and then attempt a build
+if git merge --no-commit hot-fix &&
+ make
+then
+ # run project specific test and report its status
+ ~/check_test_case.sh
+ status=$?
+else
+ # tell the caller this is untestable
+ status=125
+fi
+
+# undo the tweak to allow clean flipping to the next commit
+git reset --hard
+
+# return control
+exit $status
------------
+
-Here "check_test_case.sh" should "exit 0" if the test case passes,
-and "exit 1" otherwise.
-+
-It is safer if both "test.sh" and "check_test_case.sh" scripts are
-outside the repository to prevent interactions between the bisect,
-make and test processes and the scripts.
+This applies modifications from a hot-fix branch before each test run,
+e.g. in case your build or test environment changed so that older
+revisions may need a fix which newer ones have already. (Make sure the
+hot-fix branch is based off a commit which is contained in all revisions
+which you are bisecting, so that the merge does not pull in too much, or
+use `git cherry-pick` instead of `git merge`.)
-* Automatically bisect a broken test suite:
+* Automatically bisect a broken test case:
+
------------
$ git bisect start HEAD HEAD~10 -- # culprit is among the last 10
$ git bisect run sh -c "make || exit 125; ~/check_test_case.sh"
------------
+
-Does the same as the previous example, but on a single line.
+This shows that you can do without a run script if you write the test
+on a single line.
Author
------
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index b586c0f442..8f89f6f08c 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -214,10 +214,11 @@ FROM UPSTREAM REBASE" section in linkgit:git-rebase[1].)
-u[<mode>]::
--untracked-files[=<mode>]::
- Show untracked files (Default: 'all').
+ Show untracked files.
+
-The mode parameter is optional, and is used to specify
-the handling of untracked files.
+The mode parameter is optional (defaults to 'all'), and is used to
+specify the handling of untracked files; when -u is not used, the
+default is 'normal', i.e. show untracked files and directories.
+
The possible options are:
+
@@ -225,9 +226,8 @@ The possible options are:
- 'normal' - Shows untracked files and directories
- 'all' - Also shows individual files in untracked directories.
+
-See linkgit:git-config[1] for configuration variable
-used to change the default for when the option is not
-specified.
+The default can be changed using the status.showUntrackedFiles
+configuration variable documented in linkgit:git-config[1].
-v::
--verbose::
diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt
index f6ac847507..49105102db 100644
--- a/Documentation/git-diff.txt
+++ b/Documentation/git-diff.txt
@@ -38,6 +38,8 @@ directories. This behavior can be forced by --no-index.
commit relative to the named <commit>. Typically you
would want comparison with the latest commit, so if you
do not give <commit>, it defaults to HEAD.
+ If HEAD does not exist (e.g. unborned branches) and
+ <commit> is not given, it shows all staged changes.
--staged is a synonym of --cached.
'git diff' [--options] <commit> [--] [<path>...]::
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 4415e63635..02bb49886c 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -948,6 +948,13 @@ cat-blob::
rather than wasting time on the early part of an import
before the unsupported command is detected.
+notes::
+ Require that the backend support the 'notemodify' (N)
+ subcommand to the 'commit' command.
+ Versions of fast-import not supporting notes will exit
+ with a message indicating so.
+
+
`option`
~~~~~~~~
Processes the specified option so that git fast-import behaves in a
diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt
index 796e7489ff..aa69b8ef13 100644
--- a/Documentation/git-filter-branch.txt
+++ b/Documentation/git-filter-branch.txt
@@ -361,7 +361,7 @@ git filter-branch --index-filter \
'git ls-files -s | sed "s-\t\"*-&newsubdir/-" |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
git update-index --index-info &&
- mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' HEAD
+ mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
---------------------------------------------------------------
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index fac1cf55e5..152e695c81 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -123,7 +123,7 @@ EXAMPLES
--------
An example directly producing formatted text. Show the most recent
-3 tagged commits::
+3 tagged commits:
------------
#!/bin/sh
@@ -140,7 +140,7 @@ Ref: %(*refname)
A simple example showing the use of shell eval on the output,
-demonstrating the use of --shell. List the prefixes of all heads::
+demonstrating the use of --shell. List the prefixes of all heads:
------------
#!/bin/sh
@@ -154,7 +154,7 @@ done
A bit more elaborate report on tags, demonstrating that the format
-may be an entire script::
+may be an entire script:
------------
#!/bin/sh
@@ -204,3 +204,15 @@ eval=`git for-each-ref --shell --format="$fmt" \
refs/tags`
eval "$eval"
------------
+
+Author
+------
+Written by Junio C Hamano <gitster@pobox.com>.
+
+Documentation
+-------------
+Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index dab0a78fa8..791d4d4871 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -93,6 +93,7 @@ OPTIONS
as a regex).
-n::
+--line-number::
Prefix the line number to matching lines.
-l::
diff --git a/Documentation/git-ls-remote.txt b/Documentation/git-ls-remote.txt
index abe7bf9ff9..3422765827 100644
--- a/Documentation/git-ls-remote.txt
+++ b/Documentation/git-ls-remote.txt
@@ -10,7 +10,7 @@ SYNOPSIS
--------
[verse]
'git ls-remote' [--heads] [--tags] [-u <exec> | --upload-pack <exec>]
- <repository> <refs>...
+ <repository> [<refs>...]
DESCRIPTION
-----------
diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt
index 65eff66afe..96684bc510 100644
--- a/Documentation/git-pack-objects.txt
+++ b/Documentation/git-pack-objects.txt
@@ -190,15 +190,20 @@ self-contained. Use `git index-pack --fix-thin`
(see linkgit:git-index-pack[1]) to restore the self-contained property.
--delta-base-offset::
- A packed archive can express base object of a delta as
- either 20-byte object name or as an offset in the
- stream, but older version of git does not understand the
+ A packed archive can express the base object of a delta as
+ either a 20-byte object name or as an offset in the
+ stream, but ancient versions of git don't understand the
latter. By default, 'git pack-objects' only uses the
former format for better compatibility. This option
allows the command to use the latter format for
compactness. Depending on the average delta chain
length, this option typically shrinks the resulting
packfile by 3-5 per-cent.
++
+Note: Porcelain commands such as `git gc` (see linkgit:git-gc[1]),
+`git repack` (see linkgit:git-repack[1]) pass this option by default
+in modern git when they put objects in your repository into pack files.
+So does `git bundle` (see linkgit:git-bundle[1]) when it creates a bundle.
--threads=<n>::
Specifies the number of threads to spawn when searching for best
diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt
index 30466917da..b33e6be872 100644
--- a/Documentation/git-pull.txt
+++ b/Documentation/git-pull.txt
@@ -84,6 +84,15 @@ must be given before the options meant for 'git fetch'.
--verbose::
Pass --verbose to git-fetch and git-merge.
+--[no-]recurse-submodules::
+ This option controls if new commits of all populated submodules should
+ be fetched too (see linkgit:git-config[1] and linkgit:gitmodules[5]).
+ That might be necessary to get the data needed for merging submodule
+ commits, a feature git learned in 1.7.3. Notice that the result of a
+ merge will not be checked out in the submodule, "git submodule update"
+ has to be called afterwards to bring the work tree up to date with the
+ merge result.
+
Options related to merging
~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/git-remote-ext.txt b/Documentation/git-remote-ext.txt
index 2d65cfefd5..68263a6a53 100644
--- a/Documentation/git-remote-ext.txt
+++ b/Documentation/git-remote-ext.txt
@@ -7,17 +7,17 @@ git-remote-ext - Bridge smart transport to external command.
SYNOPSIS
--------
-git remote add nick "ext::<command>[ <arguments>...]"
+git remote add <nick> "ext::<command>[ <arguments>...]"
DESCRIPTION
-----------
-This remote helper uses the specified 'program' to connect
+This remote helper uses the specified '<command>' to connect
to a remote git server.
-Data written to stdin of this specified 'program' is assumed
+Data written to stdin of the specified '<command>' is assumed
to be sent to a git:// server, git-upload-pack, git-receive-pack
or git-upload-archive (depending on situation), and data read
-from stdout of this program is assumed to be received from
+from stdout of <command> is assumed to be received from
the same service.
Command and arguments are separated by an unescaped space.
@@ -40,7 +40,7 @@ The following sequences have a special meaning:
git wants to invoke.
'%G' (must be the first characters in an argument)::
- This argument will not be passed to 'program'. Instead, it
+ This argument will not be passed to '<command>'. Instead, it
will cause the helper to start by sending git:// service requests to
the remote side with the service field set to an appropriate value and
the repository field set to rest of the argument. Default is not to send
@@ -50,7 +50,7 @@ This is useful if remote side is git:// server accessed over
some tunnel.
'%V' (must be first characters in argument)::
- This argument will not be passed to 'program'. Instead it sets
+ This argument will not be passed to '<command>'. Instead it sets
the vhost field in the git:// service request (to rest of the argument).
Default is not to send vhost in such request (if sent).
@@ -76,7 +76,7 @@ EXAMPLES:
---------
This remote helper is transparently used by git when
you use commands such as "git fetch <URL>", "git clone <URL>",
-, "git push <URL>" or "git remote add nick <URL>", where <URL>
+, "git push <URL>" or "git remote add <nick> <URL>", where <URL>
begins with `ext::`. Examples:
"ext::ssh -i /home/foo/.ssh/somekey user&#64;host.example %S 'foo/repo'"::
diff --git a/Documentation/git-remote-helpers.txt b/Documentation/git-remote-helpers.txt
index 3a23477ce7..51de895822 100644
--- a/Documentation/git-remote-helpers.txt
+++ b/Documentation/git-remote-helpers.txt
@@ -201,12 +201,12 @@ REF LIST ATTRIBUTES
OPTIONS
-------
-'option verbosity' <N>::
+'option verbosity' <n>::
Changes the verbosity of messages displayed by the helper.
- A value of 0 for N means that processes operate
+ A value of 0 for <n> means that processes operate
quietly, and the helper produces only error output.
1 is the default level of verbosity, and higher values
- of N correspond to the number of -v flags passed on the
+ of <n> correspond to the number of -v flags passed on the
command line.
'option progress' \{'true'|'false'\}::
diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt
index dae190a5f2..5102a23f8e 100644
--- a/Documentation/git-status.txt
+++ b/Documentation/git-status.txt
@@ -38,20 +38,20 @@ OPTIONS
-u[<mode>]::
--untracked-files[=<mode>]::
- Show untracked files (Default: 'all').
+ Show untracked files.
+
-The mode parameter is optional, and is used to specify
-the handling of untracked files. The possible options are:
+The mode parameter is optional (defaults to 'all'), and is used to
+specify the handling of untracked files; when -u is not used, the
+default is 'normal', i.e. show untracked files and directories.
++
+The possible options are:
+
---
- 'no' - Show no untracked files
- 'normal' - Shows untracked files and directories
- 'all' - Also shows individual files in untracked directories.
---
+
-See linkgit:git-config[1] for configuration variable
-used to change the default for when the option is not
-specified.
+The default can be changed using the status.showUntrackedFiles
+configuration variable documented in linkgit:git-config[1].
--ignore-submodules[=<when>]::
Ignore changes to submodules when looking for changes. <when> can be
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index 0ade2ce54e..e161a40a73 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -66,7 +66,7 @@ COMMANDS
Set the 'rewriteRoot' option in the [svn-remote] config.
--rewrite-uuid=<UUID>;;
Set the 'rewriteUUID' option in the [svn-remote] config.
---username=<USER>;;
+--username=<user>;;
For transports that SVN handles authentication for (http,
https, and plain svn), specify the username. For other
transports (eg svn+ssh://), you must include the username in
@@ -443,8 +443,8 @@ OPTIONS
Only used with the 'init' command.
These are passed directly to 'git init'.
--r <ARG>::
---revision <ARG>::
+-r <arg>::
+--revision <arg>::
Used with the 'fetch' command.
+
This allows revision ranges for partial/cauterized history
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 8b169e364a..fa7ac12a3d 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -18,21 +18,22 @@ SYNOPSIS
DESCRIPTION
-----------
-Adds a tag reference in `.git/refs/tags/`.
+Add a tag reference in `.git/refs/tags/`, unless `-d/-l/-v` is given
+to delete, list or verify tags.
-Unless `-f` is given, the tag must not yet exist in
+Unless `-f` is given, the tag to be created must not yet exist in the
`.git/refs/tags/` directory.
If one of `-a`, `-s`, or `-u <key-id>` is passed, the command
-creates a 'tag' object, and requires the tag message. Unless
+creates a 'tag' object, and requires a tag message. Unless
`-m <msg>` or `-F <file>` is given, an editor is started for the user to type
in the tag message.
If `-m <msg>` or `-F <file>` is given and `-a`, `-s`, and `-u <key-id>`
are absent, `-a` is implied.
-Otherwise just the SHA1 object name of the commit object is
-written (i.e. a lightweight tag).
+Otherwise just a tag reference for the SHA1 object name of the commit object is
+created (i.e. a lightweight tag).
A GnuPG signed tag object will be created when `-s` or `-u
<key-id>` is used. When `-u <key-id>` is not used, the
@@ -164,13 +165,12 @@ You can test which tag you have by doing
which should return 0123456789abcdef.. if you have the new version.
-Sorry for inconvenience.
+Sorry for the inconvenience.
------------
Does this seem a bit complicated? It *should* be. There is no
-way that it would be correct to just "fix" it behind peoples
-backs. People need to know that their tags might have been
-changed.
+way that it would be correct to just "fix" it automatically.
+People need to know that their tags might have been changed.
On Automatic following
@@ -188,9 +188,10 @@ the toplevel but not limited to them. Mere mortals when pulling
from each other do not necessarily want to automatically get
private anchor point tags from the other person.
-You would notice "please pull" messages on the mailing list says
-repo URL and branch name alone. This is designed to be easily
-cut&pasted to a 'git fetch' command line:
+Often, "please pull" messages on the mailing list just provide
+two pieces of information: a repo URL and a branch name; this
+is designed to be easily cut&pasted at the end of a 'git fetch'
+command line:
------------
Linus, please pull from
@@ -206,14 +207,14 @@ becomes:
$ git pull git://git..../proj.git master
------------
-In such a case, you do not want to automatically follow other's
-tags.
+In such a case, you do not want to automatically follow the other
+person's tags.
-One important aspect of git is it is distributed, and being
-distributed largely means there is no inherent "upstream" or
+One important aspect of git is its distributed nature, which
+largely means there is no inherent "upstream" or
"downstream" in the system. On the face of it, the above
example might seem to indicate that the tag namespace is owned
-by upper echelon of people and tags only flow downwards, but
+by the upper echelon of people and that tags only flow downwards, but
that is not the case. It only shows that the usage pattern
determines who are interested in whose tags.
@@ -231,7 +232,7 @@ this case.
It may well be that among networking people, they may want to
exchange the tags internal to their group, but in that workflow
-they are most likely tracking with each other's progress by
+they are most likely tracking each other's progress by
having remote-tracking branches. Again, the heuristic to automatically
follow such tags is a good thing.
@@ -241,21 +242,21 @@ On Backdating Tags
If you have imported some changes from another VCS and would like
to add tags for major releases of your work, it is useful to be able
-to specify the date to embed inside of the tag object. The data in
+to specify the date to embed inside of the tag object; such data in
the tag object affects, for example, the ordering of tags in the
gitweb interface.
To set the date used in future tag objects, set the environment
-variable GIT_COMMITTER_DATE to one or more of the date and time. The
-date and time can be specified in a number of ways; the most common
-is "YYYY-MM-DD HH:MM".
+variable GIT_COMMITTER_DATE (see the later discussion of possible
+values; the most common form is "YYYY-MM-DD HH:MM").
-An example follows.
+For example:
------------
$ GIT_COMMITTER_DATE="2006-10-02 10:31" git tag -s v1.0.1
------------
+include::date-formats.txt[]
SEE ALSO
--------
diff --git a/Documentation/git-verify-pack.txt b/Documentation/git-verify-pack.txt
index 916a38aa99..0f848de8b2 100644
--- a/Documentation/git-verify-pack.txt
+++ b/Documentation/git-verify-pack.txt
@@ -8,7 +8,7 @@ git-verify-pack - Validate packed git archive files
SYNOPSIS
--------
-'git verify-pack' [-v|--verbose] [--] <pack>.idx ...
+'git verify-pack' [-v|--verbose] [-s|--stat-only] [--] <pack>.idx ...
DESCRIPTION
diff --git a/Documentation/git.txt b/Documentation/git.txt
index e968ed4aa0..0c32d45248 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -44,9 +44,10 @@ unreleased) version of git, that is available from 'master'
branch of the `git.git` repository.
Documentation for older releases are available here:
-* link:v1.7.4/git.html[documentation for release 1.7.4]
+* link:v1.7.4.1/git.html[documentation for release 1.7.4.1]
* release notes for
+ link:RelNotes/1.7.4.1.txt[1.7.4.1],
link:RelNotes/1.7.4.txt[1.7.4].
* link:v1.7.3.5/git.html[documentation for release 1.7.3.5]
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index 7e7e12168e..15aebc6062 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -632,7 +632,7 @@ Performing a three-way merge
`merge`
^^^^^^^
-The attribute `merge` affects how three versions of a file is
+The attribute `merge` affects how three versions of a file are
merged when a file-level merge is necessary during `git merge`,
and other commands such as `git revert` and `git cherry-pick`.
@@ -646,15 +646,15 @@ Unset::
Take the version from the current branch as the
tentative merge result, and declare that the merge has
- conflicts. This is suitable for binary files that does
+ conflicts. This is suitable for binary files that do
not have a well-defined merge semantics.
Unspecified::
By default, this uses the same built-in 3-way merge
- driver as is the case the `merge` attribute is set.
- However, `merge.default` configuration variable can name
- different merge driver to be used for paths to which the
+ driver as is the case when the `merge` attribute is set.
+ However, the `merge.default` configuration variable can name
+ different merge driver to be used with paths for which the
`merge` attribute is unspecified.
String::
diff --git a/Documentation/howto/using-merge-subtree.txt b/Documentation/howto/using-merge-subtree.txt
index 0953a50b69..2933056120 100644
--- a/Documentation/howto/using-merge-subtree.txt
+++ b/Documentation/howto/using-merge-subtree.txt
@@ -71,5 +71,5 @@ Additional tips
relevant parts of your tree.
- Please note that if the other project merges from you, then it will
- connects its history to yours, which can be something they don't want
+ connect its history to yours, which can be something they don't want
to.
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index 44a2ef1de1..9c47ad885b 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -165,7 +165,7 @@ limiting may be applied.
-n 'number'::
--max-count=<number>::
- Limit the number of commits output.
+ Limit the number of commits to output.
--skip=<number>::
diff --git a/Documentation/technical/index-format.txt b/Documentation/technical/index-format.txt
new file mode 100644
index 0000000000..7b233ca196
--- /dev/null
+++ b/Documentation/technical/index-format.txt
@@ -0,0 +1,185 @@
+GIT index format
+================
+
+= The git index file has the following format
+
+ All binary numbers are in network byte order. Version 2 is described
+ here unless stated otherwise.
+
+ - A 12-byte header consisting of
+
+ 4-byte signature:
+ The signature is { 'D', 'I', 'R', 'C' } (stands for "dircache")
+
+ 4-byte version number:
+ The current supported versions are 2 and 3.
+
+ 32-bit number of index entries.
+
+ - A number of sorted index entries (see below).
+
+ - Extensions
+
+ Extensions are identified by signature. Optional extensions can
+ be ignored if GIT does not understand them.
+
+ GIT currently supports cached tree and resolve undo extensions.
+
+ 4-byte extension signature. If the first byte is 'A'..'Z' the
+ extension is optional and can be ignored.
+
+ 32-bit size of the extension
+
+ Extension data
+
+ - 160-bit SHA-1 over the content of the index file before this
+ checksum.
+
+== Index entry
+
+ Index entries are sorted in ascending order on the name field,
+ interpreted as a string of unsigned bytes (i.e. memcmp() order, no
+ localization, no special casing of directory separator '/'). Entries
+ with the same name are sorted by their stage field.
+
+ 32-bit ctime seconds, the last time a file's metadata changed
+ this is stat(2) data
+
+ 32-bit ctime nanosecond fractions
+ this is stat(2) data
+
+ 32-bit mtime seconds, the last time a file's data changed
+ this is stat(2) data
+
+ 32-bit mtime nanosecond fractions
+ this is stat(2) data
+
+ 32-bit dev
+ this is stat(2) data
+
+ 32-bit ino
+ this is stat(2) data
+
+ 32-bit mode, split into (high to low bits)
+
+ 4-bit object type
+ valid values in binary are 1000 (regular file), 1010 (symbolic link)
+ and 1110 (gitlink)
+
+ 3-bit unused
+
+ 9-bit unix permission. Only 0755 and 0644 are valid for regular files.
+ Symbolic links and gitlinks have value 0 in this field.
+
+ 32-bit uid
+ this is stat(2) data
+
+ 32-bit gid
+ this is stat(2) data
+
+ 32-bit file size
+ This is the on-disk size from stat(2), truncated to 32-bit.
+
+ 160-bit SHA-1 for the represented object
+
+ A 16-bit 'flags' field split into (high to low bits)
+
+ 1-bit assume-valid flag
+
+ 1-bit extended flag (must be zero in version 2)
+
+ 2-bit stage (during merge)
+
+ 12-bit name length if the length is less than 0xFFF; otherwise 0xFFF
+ is stored in this field.
+
+ (Version 3) A 16-bit field, only applicable if the "extended flag"
+ above is 1, split into (high to low bits).
+
+ 1-bit reserved for future
+
+ 1-bit skip-worktree flag (used by sparse checkout)
+
+ 1-bit intent-to-add flag (used by "git add -N")
+
+ 13-bit unused, must be zero
+
+ Entry path name (variable length) relative to top level directory
+ (without leading slash). '/' is used as path separator. The special
+ path components ".", ".." and ".git" (without quotes) are disallowed.
+ Trailing slash is also disallowed.
+
+ The exact encoding is undefined, but the '.' and '/' characters
+ are encoded in 7-bit ASCII and the encoding cannot contain a NUL
+ byte (iow, this is a UNIX pathname).
+
+ 1-8 nul bytes as necessary to pad the entry to a multiple of eight bytes
+ while keeping the name NUL-terminated.
+
+== Extensions
+
+=== Cached tree
+
+ Cached tree extension contains pre-computed hashes for trees that can
+ be derived from the index. It helps speed up tree object generation
+ from index for a new commit.
+
+ When a path is updated in index, the path must be invalidated and
+ removed from tree cache.
+
+ The signature for this extension is { 'T', 'R', 'E', 'E' }.
+
+ A series of entries fill the entire extension; each of which
+ consists of:
+
+ - NUL-terminated path component (relative to its parent directory);
+
+ - ASCII decimal number of entries in the index that is covered by the
+ tree this entry represents (entry_count);
+
+ - A space (ASCII 32);
+
+ - ASCII decimal number that represents the number of subtrees this
+ tree has;
+
+ - A newline (ASCII 10); and
+
+ - 160-bit object name for the object that would result from writing
+ this span of index as a tree.
+
+ An entry can be in an invalidated state and is represented by having -1
+ in the entry_count field.
+
+ The entries are written out in the top-down, depth-first order. The
+ first entry represents the root level of the repository, followed by the
+ first subtree---let's call this A---of the root level (with its name
+ relative to the root level), followed by the first subtree of A (with
+ its name relative to A), ...
+
+=== Resolve undo
+
+ A conflict is represented in the index as a set of higher stage entries.
+ When a conflict is resolved (e.g. with "git add path"), these higher
+ stage entries will be removed and a stage-0 entry with proper resoluton
+ is added.
+
+ When these higher stage entries are removed, they are saved in the
+ resolve undo extension, so that conflicts can be recreated (e.g. with
+ "git checkout -m"), in case users want to redo a conflict resolution
+ from scratch.
+
+ The signature for this extension is { 'R', 'E', 'U', 'C' }.
+
+ A series of entries fill the entire extension; each of which
+ consists of:
+
+ - NUL-terminated pathname the entry describes (relative to the root of
+ the repository, i.e. full pathname);
+
+ - Three NUL-terminated ASCII octal numbers, entry mode of entries in
+ stage 1 to 3 (a missing stage is represented by "0" in this field);
+ and
+
+ - At most three 160-bit object names of the entry in stages from 1 to 3
+ (nothing is written for a missing stage).
+
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 92fe7a59db..cbd6e34644 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v1.7.4
+DEF_VER=v1.7.4.3
LF='
'
diff --git a/Makefile b/Makefile
index 775ee838c3..5c2b797554 100644
--- a/Makefile
+++ b/Makefile
@@ -435,6 +435,7 @@ TEST_PROGRAMS_NEED_X += test-subprocess
TEST_PROGRAMS_NEED_X += test-svn-fe
TEST_PROGRAMS_NEED_X += test-treap
TEST_PROGRAMS_NEED_X += test-index-version
+TEST_PROGRAMS_NEED_X += test-mktemp
TEST_PROGRAMS = $(patsubst %,%$X,$(TEST_PROGRAMS_NEED_X))
@@ -1041,6 +1042,7 @@ ifeq ($(uname_S),HP-UX)
NO_UNSETENV = YesPlease
NO_HSTRERROR = YesPlease
NO_SYS_SELECT_H = YesPlease
+ NO_FNMATCH_CASEFOLD = YesPlease
SNPRINTF_RETURNS_BOGUS = YesPlease
NO_NSEC = YesPlease
ifeq ($(uname_R),B.11.00)
diff --git a/RelNotes b/RelNotes
index b942e49944..5d988d6ab7 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/1.7.4.txt \ No newline at end of file
+Documentation/RelNotes/1.7.4.3.txt \ No newline at end of file
diff --git a/abspath.c b/abspath.c
index 91ca00f05f..ff140689ed 100644
--- a/abspath.c
+++ b/abspath.c
@@ -24,6 +24,10 @@ const char *make_absolute_path(const char *path)
char *last_elem = NULL;
struct stat st;
+ /* We've already done it */
+ if (path == buf || path == next_buf)
+ return path;
+
if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
die ("Too long path: %.*s", 60, path);
diff --git a/aclocal.m4 b/aclocal.m4
index d399de2671..f11bc7ed7d 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -13,7 +13,7 @@ AC_DEFUN([TYPE_SOCKLEN_T],
git_cv_socklen_t_equiv=
for arg2 in "struct sockaddr" void; do
for t in int size_t unsigned long "unsigned long"; do
- AC_TRY_COMPILE([
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
#include <sys/types.h>
#include <sys/socket.h>
@@ -21,7 +21,7 @@ AC_DEFUN([TYPE_SOCKLEN_T],
],[
$t len;
getpeername(0,0,&len);
- ],[
+ ])],[
git_cv_socklen_t_equiv="$t"
break 2
])
diff --git a/branch.c b/branch.c
index 93dc866f8c..da5c03e565 100644
--- a/branch.c
+++ b/branch.c
@@ -175,9 +175,14 @@ void create_branch(const char *head,
die("Cannot setup tracking information; starting point is not a branch.");
break;
case 1:
- /* Unique completion -- good, only if it is a real ref */
- if (explicit_tracking && !strcmp(real_ref, "HEAD"))
- die("Cannot setup tracking information; starting point is not a branch.");
+ /* Unique completion -- good, only if it is a real branch */
+ if (prefixcmp(real_ref, "refs/heads/") &&
+ prefixcmp(real_ref, "refs/remotes/")) {
+ if (explicit_tracking)
+ die("Cannot setup tracking information; starting point is not a branch.");
+ else
+ real_ref = NULL;
+ }
break;
default:
die("Ambiguous object name: '%s'.", start_name);
diff --git a/builtin/add.c b/builtin/add.c
index 12b964e642..1d74763f58 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -21,8 +21,7 @@ static const char * const builtin_add_usage[] = {
static int patch_interactive, add_interactive, edit_interactive;
static int take_worktree_changes;
-struct update_callback_data
-{
+struct update_callback_data {
int flags;
int add_errors;
};
@@ -317,7 +316,7 @@ static struct option builtin_add_options[] = {
OPT__VERBOSE(&verbose, "be verbose"),
OPT_GROUP(""),
OPT_BOOLEAN('i', "interactive", &add_interactive, "interactive picking"),
- OPT_BOOLEAN('p', "patch", &patch_interactive, "interactive patching"),
+ OPT_BOOLEAN('p', "patch", &patch_interactive, "select hunks interactively"),
OPT_BOOLEAN('e', "edit", &edit_interactive, "edit current diff and apply"),
OPT__FORCE(&ignored_too, "allow adding otherwise ignored files"),
OPT_BOOLEAN('u', "update", &take_worktree_changes, "update tracked files"),
diff --git a/builtin/apply.c b/builtin/apply.c
index 14951daedf..36e150768b 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -204,6 +204,7 @@ struct line {
unsigned hash : 24;
unsigned flag : 8;
#define LINE_COMMON 1
+#define LINE_PATCHED 2
};
/*
@@ -2085,7 +2086,8 @@ static int match_fragment(struct image *img,
/* Quick hash check */
for (i = 0; i < preimage_limit; i++)
- if (preimage->line[i].hash != img->line[try_lno + i].hash)
+ if ((img->line[try_lno + i].flag & LINE_PATCHED) ||
+ (preimage->line[i].hash != img->line[try_lno + i].hash))
return 0;
if (preimage_limit == preimage->nr) {
@@ -2428,11 +2430,15 @@ static void update_image(struct image *img,
memcpy(img->line + applied_pos,
postimage->line,
postimage->nr * sizeof(*img->line));
+ for (i = 0; i < postimage->nr; i++)
+ img->line[applied_pos + i].flag |= LINE_PATCHED;
+
img->nr = nr;
}
static int apply_one_fragment(struct image *img, struct fragment *frag,
- int inaccurate_eof, unsigned ws_rule)
+ int inaccurate_eof, unsigned ws_rule,
+ int nth_fragment)
{
int match_beginning, match_end;
const char *patch = frag->patch;
@@ -2638,6 +2644,15 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
apply = 0;
}
+ if (apply_verbosely && applied_pos != pos) {
+ int offset = applied_pos - pos;
+ if (apply_in_reverse)
+ offset = 0 - offset;
+ fprintf(stderr,
+ "Hunk #%d succeeded at %d (offset %d lines).\n",
+ nth_fragment, applied_pos + 1, offset);
+ }
+
/*
* Warn if it was necessary to reduce the number
* of context lines.
@@ -2785,12 +2800,14 @@ static int apply_fragments(struct image *img, struct patch *patch)
const char *name = patch->old_name ? patch->old_name : patch->new_name;
unsigned ws_rule = patch->ws_rule;
unsigned inaccurate_eof = patch->inaccurate_eof;
+ int nth = 0;
if (patch->is_binary)
return apply_binary(img, patch);
while (frag) {
- if (apply_one_fragment(img, frag, inaccurate_eof, ws_rule)) {
+ nth++;
+ if (apply_one_fragment(img, frag, inaccurate_eof, ws_rule, nth)) {
error("patch failed: %s:%ld", name, frag->oldpos);
if (!apply_with_reject)
return -1;
diff --git a/builtin/blame.c b/builtin/blame.c
index aa30ec5269..f6b03f750a 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -1312,8 +1312,7 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
/*
* Information on commits, used for output.
*/
-struct commit_info
-{
+struct commit_info {
const char *author;
const char *author_mail;
unsigned long author_time;
diff --git a/builtin/branch.c b/builtin/branch.c
index 9e546e4a83..b9ba011f7b 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -134,7 +134,7 @@ static int branch_merged(int kind, const char *name,
in_merge_bases(rev, &head_rev, 1) != merged) {
if (merged)
warning("deleting branch '%s' that has been merged to\n"
- " '%s', but it is not yet merged to HEAD.",
+ " '%s', but not yet been merged to HEAD.",
name, reference_name);
else
warning("not deleting branch '%s' that is not yet merged to\n"
@@ -390,6 +390,30 @@ static int matches_merge_filter(struct commit *commit)
return (is_merged == (merge_filter == SHOW_MERGED));
}
+static void add_verbose_info(struct strbuf *out, struct ref_item *item,
+ int verbose, int abbrev)
+{
+ struct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT;
+ const char *sub = " **** invalid ref ****";
+ struct commit *commit = item->commit;
+
+ if (commit && !parse_commit(commit)) {
+ struct pretty_print_context ctx = {0};
+ pretty_print_commit(CMIT_FMT_ONELINE, commit,
+ &subject, &ctx);
+ sub = subject.buf;
+ }
+
+ if (item->kind == REF_LOCAL_BRANCH)
+ fill_tracking_info(&stat, item->name, verbose > 1);
+
+ strbuf_addf(out, " %s %s%s",
+ find_unique_abbrev(item->commit->object.sha1, abbrev),
+ stat.buf, sub);
+ strbuf_release(&stat);
+ strbuf_release(&subject);
+}
+
static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
int abbrev, int current, char *prefix)
{
@@ -430,27 +454,9 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
if (item->dest)
strbuf_addf(&out, " -> %s", item->dest);
- else if (verbose) {
- struct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT;
- const char *sub = " **** invalid ref ****";
-
- commit = item->commit;
- if (commit && !parse_commit(commit)) {
- struct pretty_print_context ctx = {0};
- pretty_print_commit(CMIT_FMT_ONELINE, commit,
- &subject, &ctx);
- sub = subject.buf;
- }
-
- if (item->kind == REF_LOCAL_BRANCH)
- fill_tracking_info(&stat, item->name, verbose > 1);
-
- strbuf_addf(&out, " %s %s%s",
- find_unique_abbrev(item->commit->object.sha1, abbrev),
- stat.buf, sub);
- strbuf_release(&stat);
- strbuf_release(&subject);
- }
+ else if (verbose)
+ /* " f7c0c00 [ahead 58, behind 197] vcs-svn: drop obj_pool.h" */
+ add_verbose_info(&out, item, verbose, abbrev);
printf("%s\n", out.buf);
strbuf_release(&name);
strbuf_release(&out);
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 757f9a08dd..e98576f22e 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -404,7 +404,7 @@ static int merge_working_tree(struct checkout_opts *opts,
topts.dir->exclude_per_dir = ".gitignore";
tree = parse_tree_indirect(old->commit ?
old->commit->object.sha1 :
- (unsigned char *)EMPTY_TREE_SHA1_BIN);
+ EMPTY_TREE_SHA1_BIN);
init_tree_desc(&trees[0], tree->buffer, tree->size);
tree = parse_tree_indirect(new->commit->object.sha1);
init_tree_desc(&trees[1], tree->buffer, tree->size);
@@ -678,7 +678,7 @@ static const char *unique_tracking_name(const char *name)
int cmd_checkout(int argc, const char **argv, const char *prefix)
{
struct checkout_opts opts;
- unsigned char rev[20];
+ unsigned char rev[20], branch_rev[20];
const char *arg;
struct branch_info new;
struct tree *source_tree = NULL;
@@ -832,18 +832,21 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
argc--;
new.name = arg;
- if ((new.commit = lookup_commit_reference_gently(rev, 1))) {
- setup_branch_path(&new);
+ setup_branch_path(&new);
- if ((check_ref_format(new.path) == CHECK_REF_FORMAT_OK) &&
- resolve_ref(new.path, rev, 1, NULL))
- ;
- else
- new.path = NULL;
+ if (check_ref_format(new.path) == CHECK_REF_FORMAT_OK &&
+ resolve_ref(new.path, branch_rev, 1, NULL))
+ hashcpy(rev, branch_rev);
+ else
+ new.path = NULL; /* not an existing branch */
+
+ if (!(new.commit = lookup_commit_reference_gently(rev, 1))) {
+ /* not a commit */
+ source_tree = parse_tree_indirect(rev);
+ } else {
parse_commit(new.commit);
source_tree = new.commit->tree;
- } else
- source_tree = parse_tree_indirect(rev);
+ }
if (!source_tree) /* case (1): want a tree */
die("reference is not a tree: %s", arg);
diff --git a/builtin/clone.c b/builtin/clone.c
index 61e0989b5a..2ee1fa9846 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -66,10 +66,10 @@ static struct option builtin_clone_options[] = {
"setup as shared repository"),
OPT_BOOLEAN(0, "recursive", &option_recursive,
"initialize submodules in the clone"),
- OPT_BOOLEAN(0, "recurse_submodules", &option_recursive,
+ OPT_BOOLEAN(0, "recurse-submodules", &option_recursive,
"initialize submodules in the clone"),
- OPT_STRING(0, "template", &option_template, "path",
- "path the template repository"),
+ OPT_STRING(0, "template", &option_template, "template-directory",
+ "directory from which templates will be used"),
OPT_STRING(0, "reference", &option_reference, "repo",
"reference repository"),
OPT_STRING('o', "origin", &option_origin, "branch",
@@ -413,7 +413,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (path)
repo = xstrdup(make_nonrelative_path(repo_name));
else if (!strchr(repo_name, ':'))
- repo = xstrdup(make_absolute_path(repo_name));
+ die("repository '%s' does not exist", repo_name);
else
repo = repo_name;
is_local = path && !is_bundle;
diff --git a/builtin/commit.c b/builtin/commit.c
index 03cff5af63..d71e1e0c9c 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -118,14 +118,14 @@ static struct option builtin_commit_options[] = {
OPT__VERBOSE(&verbose, "show diff in commit message template"),
OPT_GROUP("Commit message options"),
- OPT_FILENAME('F', "file", &logfile, "read log from file"),
- OPT_STRING(0, "author", &force_author, "AUTHOR", "override author for commit"),
- OPT_STRING(0, "date", &force_date, "DATE", "override date for commit"),
- OPT_CALLBACK('m', "message", &message, "MESSAGE", "specify commit message", opt_parse_m),
- OPT_STRING('c', "reedit-message", &edit_message, "COMMIT", "reuse and edit message from specified commit"),
- OPT_STRING('C', "reuse-message", &use_message, "COMMIT", "reuse message from specified commit"),
- OPT_STRING(0, "fixup", &fixup_message, "COMMIT", "use autosquash formatted message to fixup specified commit"),
- OPT_STRING(0, "squash", &squash_message, "COMMIT", "use autosquash formatted message to squash specified commit"),
+ OPT_FILENAME('F', "file", &logfile, "read message from file"),
+ OPT_STRING(0, "author", &force_author, "author", "override author for commit"),
+ OPT_STRING(0, "date", &force_date, "date", "override date for commit"),
+ OPT_CALLBACK('m', "message", &message, "message", "commit message", opt_parse_m),
+ OPT_STRING('c', "reedit-message", &edit_message, "commit", "reuse and edit message from specified commit"),
+ OPT_STRING('C', "reuse-message", &use_message, "commit", "reuse message from specified commit"),
+ OPT_STRING(0, "fixup", &fixup_message, "commit", "use autosquash formatted message to fixup specified commit"),
+ OPT_STRING(0, "squash", &squash_message, "commit", "use autosquash formatted message to squash specified commit"),
OPT_BOOLEAN(0, "reset-author", &renew_authorship, "the commit is authored by me now (used with -C-c/--amend)"),
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
OPT_FILENAME('t', "template", &template_file, "use specified template file"),
@@ -145,12 +145,12 @@ static struct option builtin_commit_options[] = {
STATUS_FORMAT_SHORT),
OPT_BOOLEAN(0, "branch", &status_show_branch, "show branch information"),
OPT_SET_INT(0, "porcelain", &status_format,
- "show porcelain output format", STATUS_FORMAT_PORCELAIN),
+ "machine-readable output", STATUS_FORMAT_PORCELAIN),
OPT_BOOLEAN('z', "null", &null_termination,
"terminate entries with NUL"),
OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
OPT_BOOLEAN(0, "no-post-rewrite", &no_post_rewrite, "bypass post-rewrite hook"),
- { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
+ { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no. (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
/* end commit contents options */
{ OPTION_BOOLEAN, 0, "allow-empty", &allow_empty, NULL,
@@ -634,7 +634,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
if (strbuf_read_file(&sb, git_path("SQUASH_MSG"), 0) < 0)
die_errno("could not read SQUASH_MSG");
hook_arg1 = "squash";
- } else if (template_file && !stat(template_file, &statbuf)) {
+ } else if (template_file) {
if (strbuf_read_file(&sb, template_file, 0) < 0)
die_errno("could not read '%s'", template_file);
hook_arg1 = "template";
@@ -1092,7 +1092,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
OPT_BOOLEAN('b', "branch", &status_show_branch,
"show branch information"),
OPT_SET_INT(0, "porcelain", &status_format,
- "show porcelain output format",
+ "machine-readable output",
STATUS_FORMAT_PORCELAIN),
OPT_BOOLEAN('z', "null", &null_termination,
"terminate entries with NUL"),
diff --git a/builtin/config.c b/builtin/config.c
index ca4a0db4a7..f87443698a 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -52,7 +52,7 @@ static struct option builtin_config_options[] = {
OPT_BOOLEAN(0, "global", &use_global_config, "use global config file"),
OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
OPT_BOOLEAN(0, "local", &use_local_config, "use repository config file"),
- OPT_STRING('f', "file", &given_config_file, "FILE", "use given config file"),
+ OPT_STRING('f', "file", &given_config_file, "file", "use given config file"),
OPT_GROUP("Action"),
OPT_BIT(0, "get", &actions, "get value: name [value-regex]", ACTION_GET),
OPT_BIT(0, "get-all", &actions, "get all values: key [value-regex]", ACTION_GET_ALL),
@@ -153,7 +153,6 @@ static int show_config(const char *key_, const char *value_, void *cb)
static int get_value(const char *key_, const char *regex_)
{
int ret = -1;
- char *tl;
char *global = NULL, *repo_config = NULL;
const char *system_wide = NULL, *local;
@@ -167,18 +166,32 @@ static int get_value(const char *key_, const char *regex_)
system_wide = git_etc_gitconfig();
}
- key = xstrdup(key_);
- for (tl=key+strlen(key)-1; tl >= key && *tl != '.'; --tl)
- *tl = tolower(*tl);
- for (tl=key; *tl && *tl != '.'; ++tl)
- *tl = tolower(*tl);
-
if (use_key_regexp) {
+ char *tl;
+
+ /*
+ * NEEDSWORK: this naive pattern lowercasing obviously does not
+ * work for more complex patterns like "^[^.]*Foo.*bar".
+ * Perhaps we should deprecate this altogether someday.
+ */
+
+ key = xstrdup(key_);
+ for (tl = key + strlen(key) - 1;
+ tl >= key && *tl != '.';
+ tl--)
+ *tl = tolower(*tl);
+ for (tl = key; *tl && *tl != '.'; tl++)
+ *tl = tolower(*tl);
+
key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
if (regcomp(key_regexp, key, REG_EXTENDED)) {
fprintf(stderr, "Invalid key pattern: %s\n", key_);
+ free(key);
goto free_strings;
}
+ } else {
+ if (git_config_parse_key(key_, &key, NULL))
+ goto free_strings;
}
if (regex_) {
diff --git a/builtin/describe.c b/builtin/describe.c
index 95915960d4..4afd1504a6 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -63,7 +63,7 @@ static inline struct commit_name *find_commit_name(const unsigned char *peeled)
return n;
}
-static int set_util(void *chain)
+static int set_util(void *chain, void *data)
{
struct commit_name *n;
for (n = chain; n; n = n->next) {
@@ -289,7 +289,7 @@ static void describe(const char *arg, int last_one)
fprintf(stderr, "searching to describe %s\n", arg);
if (!have_util) {
- for_each_hash(&names, set_util);
+ for_each_hash(&names, set_util, NULL);
have_util = 1;
}
diff --git a/builtin/diff.c b/builtin/diff.c
index 945e7583a8..42822cd537 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -330,8 +330,11 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
else if (!strcmp(arg, "--cached") ||
!strcmp(arg, "--staged")) {
add_head_to_pending(&rev);
- if (!rev.pending.nr)
- die("No HEAD commit to compare with (yet)");
+ if (!rev.pending.nr) {
+ struct tree *tree;
+ tree = lookup_tree((const unsigned char*)EMPTY_TREE_SHA1_BIN);
+ add_pending_object(&rev, &tree->object, "HEAD");
+ }
break;
}
}
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index c8fd46b872..b18fc85c4c 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -619,9 +619,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
OPT_CALLBACK(0, "tag-of-filtered-object", &tag_of_filtered_mode, "mode",
"select handling of tags that tag filtered objects",
parse_opt_tag_of_filtered_mode),
- OPT_STRING(0, "export-marks", &export_filename, "FILE",
+ OPT_STRING(0, "export-marks", &export_filename, "file",
"Dump marks to this file"),
- OPT_STRING(0, "import-marks", &import_filename, "FILE",
+ OPT_STRING(0, "import-marks", &import_filename, "file",
"Import marks from this file"),
OPT_BOOLEAN(0, "fake-missing-tagger", &fake_missing_tagger,
"Fake a tagger when tags lack one"),
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 357f3cdbbf..7efecfe1cf 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -49,7 +49,7 @@ static struct option builtin_fetch_options[] = {
"fetch from all remotes"),
OPT_BOOLEAN('a', "append", &append,
"append to .git/FETCH_HEAD instead of overwriting"),
- OPT_STRING(0, "upload-pack", &upload_pack, "PATH",
+ OPT_STRING(0, "upload-pack", &upload_pack, "path",
"path to upload pack on remote end"),
OPT__FORCE(&force, "force overwrite of local branch"),
OPT_BOOLEAN('m', "multiple", &multiple,
@@ -69,9 +69,9 @@ static struct option builtin_fetch_options[] = {
OPT_BOOLEAN('u', "update-head-ok", &update_head_ok,
"allow updating of HEAD ref"),
OPT_BOOLEAN(0, "progress", &progress, "force progress reporting"),
- OPT_STRING(0, "depth", &depth, "DEPTH",
+ OPT_STRING(0, "depth", &depth, "depth",
"deepen history of shallow clone"),
- { OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, "DIR",
+ { OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, "dir",
"prepend this to submodule path output", PARSE_OPT_HIDDEN },
OPT_END()
};
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 6d5ebca7a9..795aba087f 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -74,7 +74,13 @@ static int mark_object(struct object *obj, int type, void *data)
{
struct object *parent = data;
+ /*
+ * The only case data is NULL or type is OBJ_ANY is when
+ * mark_object_reachable() calls us. All the callers of
+ * that function has non-NULL obj hence ...
+ */
if (!obj) {
+ /* ... these references to parent->fld are safe here */
printf("broken link from %7s %s\n",
typename(parent->type), sha1_to_hex(parent->sha1));
printf("broken link from %7s %s\n",
@@ -84,6 +90,7 @@ static int mark_object(struct object *obj, int type, void *data)
}
if (type != OBJ_ANY && obj->type != type)
+ /* ... and the reference to parent is safe here */
objerror(parent, "wrong object type in link");
if (obj->flags & REACHABLE)
@@ -109,7 +116,7 @@ static void mark_object_reachable(struct object *obj)
mark_object(obj, OBJ_ANY, NULL);
}
-static int traverse_one_object(struct object *obj, struct object *parent)
+static int traverse_one_object(struct object *obj)
{
int result;
struct tree *tree = NULL;
@@ -138,7 +145,7 @@ static int traverse_reachable(void)
entry = pending.objects + --pending.nr;
obj = entry->item;
parent = (struct object *) entry->name;
- result |= traverse_one_object(obj, parent);
+ result |= traverse_one_object(obj);
}
return !!result;
}
@@ -385,10 +392,20 @@ static void add_sha1_list(unsigned char *sha1, unsigned long ino)
sha1_list.nr = ++nr;
}
+static inline int is_loose_object_file(struct dirent *de,
+ char *name, unsigned char *sha1)
+{
+ if (strlen(de->d_name) != 38)
+ return 0;
+ memcpy(name + 2, de->d_name, 39);
+ return !get_sha1_hex(name, sha1);
+}
+
static void fsck_dir(int i, char *path)
{
DIR *dir = opendir(path);
struct dirent *de;
+ char name[100];
if (!dir)
return;
@@ -396,17 +413,13 @@ static void fsck_dir(int i, char *path)
if (verbose)
fprintf(stderr, "Checking directory %s\n", path);
+ sprintf(name, "%02x", i);
while ((de = readdir(dir)) != NULL) {
- char name[100];
unsigned char sha1[20];
if (is_dot_or_dotdot(de->d_name))
continue;
- if (strlen(de->d_name) == 38) {
- sprintf(name, "%02x", i);
- memcpy(name+2, de->d_name, 39);
- if (get_sha1_hex(name, sha1) < 0)
- break;
+ if (is_loose_object_file(de, name, sha1)) {
add_sha1_list(sha1, DIRENT_SORT_HINT(de));
continue;
}
@@ -556,8 +569,8 @@ static int fsck_cache_tree(struct cache_tree *it)
sha1_to_hex(it->sha1));
return 1;
}
- mark_object_reachable(obj);
obj->used = 1;
+ mark_object_reachable(obj);
if (obj->type != OBJ_TREE)
err |= objerror(obj, "non-tree in cache-tree");
}
diff --git a/builtin/grep.c b/builtin/grep.c
index fdf7131efd..bb0f93208f 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -40,8 +40,7 @@ enum work_type {WORK_SHA1, WORK_FILE};
* threads. The producer adds struct work_items to 'todo' and the
* consumers pick work items from the same array.
*/
-struct work_item
-{
+struct work_item {
enum work_type type;
char *name;
@@ -865,7 +864,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
OPT_BOOLEAN('F', "fixed-strings", &opt.fixed,
"interpret patterns as fixed strings"),
OPT_GROUP(""),
- OPT_BOOLEAN('n', NULL, &opt.linenum, "show line numbers"),
+ OPT_BOOLEAN('n', "line-number", &opt.linenum, "show line numbers"),
OPT_NEGBIT('h', NULL, &opt.pathname, "don't show filenames", 1),
OPT_BIT('H', NULL, &opt.pathname, "show filenames", 1),
OPT_NEGBIT(0, "full-name", &opt.relative,
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 8dc5c0b541..c7e600db47 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -13,8 +13,7 @@
static const char index_pack_usage[] =
"git index-pack [-v] [-o <index-file>] [ --keep | --keep=<msg> ] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])";
-struct object_entry
-{
+struct object_entry {
struct pack_idx_entry idx;
unsigned long size;
unsigned int hdr_size;
@@ -44,8 +43,7 @@ struct base_data {
#define FLAG_LINK (1u<<20)
#define FLAG_CHECKED (1u<<21)
-struct delta_entry
-{
+struct delta_entry {
union delta_base base;
int obj_no;
};
diff --git a/builtin/init-db.c b/builtin/init-db.c
index e3af9eaa87..fbeb380ee2 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -419,7 +419,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
unsigned int flags = 0;
const struct option init_db_options[] = {
OPT_STRING(0, "template", &template_dir, "template-directory",
- "provide the directory from which templates will be used"),
+ "directory from which templates will be used"),
OPT_SET_INT(0, "bare", &is_bare_repository_cfg,
"create a bare repository", 1),
{ OPTION_CALLBACK, 0, "shared", &init_shared_repository,
@@ -498,13 +498,11 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
is_bare_repository_cfg = guess_repository_type(git_dir);
if (!is_bare_repository_cfg) {
- if (git_dir) {
- const char *git_dir_parent = strrchr(git_dir, '/');
- if (git_dir_parent) {
- char *rel = xstrndup(git_dir, git_dir_parent - git_dir);
- git_work_tree_cfg = xstrdup(make_absolute_path(rel));
- free(rel);
- }
+ const char *git_dir_parent = strrchr(git_dir, '/');
+ if (git_dir_parent) {
+ char *rel = xstrndup(git_dir, git_dir_parent - git_dir);
+ git_work_tree_cfg = xstrdup(make_absolute_path(rel));
+ free(rel);
}
if (!git_work_tree_cfg) {
git_work_tree_cfg = xcalloc(PATH_MAX, 1);
diff --git a/builtin/log.c b/builtin/log.c
index d8c6c28d2f..9a15d69617 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -263,7 +263,13 @@ static int cmd_log_walk(struct rev_info *rev)
* retain that state information if replacing rev->diffopt in this loop
*/
while ((commit = get_revision(rev)) != NULL) {
- log_tree_commit(rev, commit);
+ if (!log_tree_commit(rev, commit) &&
+ rev->max_count >= 0)
+ /*
+ * We decremented max_count in get_revision,
+ * but we didn't actually show the commit.
+ */
+ rev->max_count++;
if (!rev->reflog_info) {
/* we allow cycles in reflog ancestry */
free(commit->buffer);
@@ -1352,6 +1358,23 @@ static const char * const cherry_usage[] = {
NULL
};
+static void print_commit(char sign, struct commit *commit, int verbose,
+ int abbrev)
+{
+ if (!verbose) {
+ printf("%c %s\n", sign,
+ find_unique_abbrev(commit->object.sha1, abbrev));
+ } else {
+ struct strbuf buf = STRBUF_INIT;
+ struct pretty_print_context ctx = {0};
+ pretty_print_commit(CMIT_FMT_ONELINE, commit, &buf, &ctx);
+ printf("%c %s %s\n", sign,
+ find_unique_abbrev(commit->object.sha1, abbrev),
+ buf.buf);
+ strbuf_release(&buf);
+ }
+}
+
int cmd_cherry(int argc, const char **argv, const char *prefix)
{
struct rev_info revs;
@@ -1436,22 +1459,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
commit = list->item;
if (has_commit_patch_id(commit, &ids))
sign = '-';
-
- if (verbose) {
- struct strbuf buf = STRBUF_INIT;
- struct pretty_print_context ctx = {0};
- pretty_print_commit(CMIT_FMT_ONELINE, commit,
- &buf, &ctx);
- printf("%c %s %s\n", sign,
- find_unique_abbrev(commit->object.sha1, abbrev),
- buf.buf);
- strbuf_release(&buf);
- }
- else {
- printf("%c %s\n", sign,
- find_unique_abbrev(commit->object.sha1, abbrev));
- }
-
+ print_commit(sign, commit, verbose, abbrev);
list = list->next;
}
diff --git a/builtin/merge.c b/builtin/merge.c
index 42fff387e6..f9fb26dc33 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -195,7 +195,7 @@ static struct option builtin_merge_options[] = {
OPT_CALLBACK('X', "strategy-option", &xopts, "option=value",
"option for selected merge strategy", option_parse_x),
OPT_CALLBACK('m', "message", &merge_msg, "message",
- "message to be used for the merge commit (if any)",
+ "merge commit message (for a non-fast-forward merge)",
option_parse_message),
OPT__VERBOSITY(&verbosity),
OPT_BOOLEAN(0, "abort", &abort_current_merge,
@@ -795,6 +795,32 @@ static void add_strategies(const char *string, unsigned attr)
}
+static void write_merge_msg(void)
+{
+ int fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666);
+ if (fd < 0)
+ die_errno("Could not open '%s' for writing",
+ git_path("MERGE_MSG"));
+ if (write_in_full(fd, merge_msg.buf, merge_msg.len) != merge_msg.len)
+ die_errno("Could not write to '%s'", git_path("MERGE_MSG"));
+ close(fd);
+}
+
+static void read_merge_msg(void)
+{
+ strbuf_reset(&merge_msg);
+ if (strbuf_read_file(&merge_msg, git_path("MERGE_MSG"), 0) < 0)
+ die_errno("Could not read from '%s'", git_path("MERGE_MSG"));
+}
+
+static void run_prepare_commit_msg(void)
+{
+ write_merge_msg();
+ run_hook(get_index_file(), "prepare-commit-msg",
+ git_path("MERGE_MSG"), "merge", NULL, NULL);
+ read_merge_msg();
+}
+
static int merge_trivial(void)
{
unsigned char result_tree[20], result_commit[20];
@@ -806,6 +832,7 @@ static int merge_trivial(void)
parent->next = xmalloc(sizeof(*parent->next));
parent->next->item = remoteheads->item;
parent->next->next = NULL;
+ run_prepare_commit_msg();
commit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL);
finish(result_commit, "In-index merge");
drop_save();
@@ -835,6 +862,7 @@ static int finish_automerge(struct commit_list *common,
}
free_commit_list(remoteheads);
strbuf_addch(&merge_msg, '\n');
+ run_prepare_commit_msg();
commit_tree(merge_msg.buf, result_tree, parents, result_commit, NULL);
strbuf_addf(&buf, "Merge made by %s.", wt_strategy);
finish(result_commit, buf.buf);
@@ -1316,14 +1344,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
die_errno("Could not write to '%s'", git_path("MERGE_HEAD"));
close(fd);
strbuf_addch(&merge_msg, '\n');
- fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666);
- if (fd < 0)
- die_errno("Could not open '%s' for writing",
- git_path("MERGE_MSG"));
- if (write_in_full(fd, merge_msg.buf, merge_msg.len) !=
- merge_msg.len)
- die_errno("Could not write to '%s'", git_path("MERGE_MSG"));
- close(fd);
+ write_merge_msg();
fd = open(git_path("MERGE_MODE"), O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0)
die_errno("Could not open '%s' for writing",
diff --git a/builtin/notes.c b/builtin/notes.c
index 4d5556e2cb..0aab150c52 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -537,16 +537,16 @@ static int add(int argc, const char **argv, const char *prefix)
const unsigned char *note;
struct msg_arg msg = { 0, 0, STRBUF_INIT };
struct option options[] = {
- { OPTION_CALLBACK, 'm', "message", &msg, "MSG",
+ { OPTION_CALLBACK, 'm', "message", &msg, "msg",
"note contents as a string", PARSE_OPT_NONEG,
parse_msg_arg},
- { OPTION_CALLBACK, 'F', "file", &msg, "FILE",
+ { OPTION_CALLBACK, 'F', "file", &msg, "file",
"note contents in a file", PARSE_OPT_NONEG,
parse_file_arg},
- { OPTION_CALLBACK, 'c', "reedit-message", &msg, "OBJECT",
+ { OPTION_CALLBACK, 'c', "reedit-message", &msg, "object",
"reuse and edit specified note object", PARSE_OPT_NONEG,
parse_reedit_arg},
- { OPTION_CALLBACK, 'C', "reuse-message", &msg, "OBJECT",
+ { OPTION_CALLBACK, 'C', "reuse-message", &msg, "object",
"reuse specified note object", PARSE_OPT_NONEG,
parse_reuse_arg},
OPT__FORCE(&force, "replace existing notes"),
@@ -682,16 +682,16 @@ static int append_edit(int argc, const char **argv, const char *prefix)
const char * const *usage;
struct msg_arg msg = { 0, 0, STRBUF_INIT };
struct option options[] = {
- { OPTION_CALLBACK, 'm', "message", &msg, "MSG",
+ { OPTION_CALLBACK, 'm', "message", &msg, "msg",
"note contents as a string", PARSE_OPT_NONEG,
parse_msg_arg},
- { OPTION_CALLBACK, 'F', "file", &msg, "FILE",
+ { OPTION_CALLBACK, 'F', "file", &msg, "file",
"note contents in a file", PARSE_OPT_NONEG,
parse_file_arg},
- { OPTION_CALLBACK, 'c', "reedit-message", &msg, "OBJECT",
+ { OPTION_CALLBACK, 'c', "reedit-message", &msg, "object",
"reuse and edit specified note object", PARSE_OPT_NONEG,
parse_reedit_arg},
- { OPTION_CALLBACK, 'C', "reuse-message", &msg, "OBJECT",
+ { OPTION_CALLBACK, 'C', "reuse-message", &msg, "object",
"reuse specified note object", PARSE_OPT_NONEG,
parse_reuse_arg},
OPT_END()
diff --git a/builtin/patch-id.c b/builtin/patch-id.c
index 512530022e..49a0472a9b 100644
--- a/builtin/patch-id.c
+++ b/builtin/patch-id.c
@@ -73,6 +73,8 @@ int get_one_patchid(unsigned char *next_sha1, git_SHA_CTX *ctx)
p += 7;
else if (!memcmp(line, "From ", 5))
p += 5;
+ else if (!memcmp(line, "\\ ", 2) && 12 < strlen(line))
+ continue;
if (!get_sha1_hex(p, next_sha1)) {
found_next = 1;
diff --git a/builtin/push.c b/builtin/push.c
index e655eb7695..31da418cf4 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -64,17 +64,17 @@ static void set_refspecs(const char **refs, int nr)
}
}
-static void setup_push_tracking(void)
+static void setup_push_upstream(void)
{
struct strbuf refspec = STRBUF_INIT;
struct branch *branch = branch_get(NULL);
if (!branch)
die("You are not currently on a branch.");
if (!branch->merge_nr || !branch->merge)
- die("The current branch %s is not tracking anything.",
+ die("The current branch %s has no upstream branch.",
branch->name);
if (branch->merge_nr != 1)
- die("The current branch %s is tracking multiple branches, "
+ die("The current branch %s has multiple upstream branches, "
"refusing to push.", branch->name);
strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
add_refspec(refspec.buf);
@@ -88,8 +88,8 @@ static void setup_default_push_refspecs(void)
add_refspec(":");
break;
- case PUSH_DEFAULT_TRACKING:
- setup_push_tracking();
+ case PUSH_DEFAULT_UPSTREAM:
+ setup_push_upstream();
break;
case PUSH_DEFAULT_CURRENT:
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index 73c89ed15b..93c92814cf 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -104,8 +104,8 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
struct unpack_trees_options opts;
int prefix_set = 0;
const struct option read_tree_options[] = {
- { OPTION_CALLBACK, 0, "index-output", NULL, "FILE",
- "write resulting index to <FILE>",
+ { OPTION_CALLBACK, 0, "index-output", NULL, "file",
+ "write resulting index to <file>",
PARSE_OPT_NONEG, index_output_cb },
OPT_SET_INT(0, "empty", &read_empty,
"only empty the index", 1),
diff --git a/builtin/tag.c b/builtin/tag.c
index aa1f87d47a..7cf48abca8 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -376,9 +376,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
OPT_GROUP("Tag creation options"),
OPT_BOOLEAN('a', NULL, &annotate,
"annotated tag, needs a message"),
- OPT_CALLBACK('m', NULL, &msg, "msg",
- "message for the tag", parse_msg_arg),
- OPT_FILENAME('F', NULL, &msgfile, "message in a file"),
+ OPT_CALLBACK('m', NULL, &msg, "message",
+ "tag message", parse_msg_arg),
+ OPT_FILENAME('F', NULL, &msgfile, "read message from file"),
OPT_BOOLEAN('s', NULL, &sign, "annotated and GPG-signed tag"),
OPT_STRING('u', NULL, &keyid, "key-id",
"use another key to sign the tag"),
diff --git a/bundle.c b/bundle.c
index 65ea26bdb8..f48fd7d4c1 100644
--- a/bundle.c
+++ b/bundle.c
@@ -200,7 +200,7 @@ int create_bundle(struct bundle_header *header, const char *path,
int bundle_fd = -1;
int bundle_to_stdout;
const char **argv_boundary = xmalloc((argc + 4) * sizeof(const char *));
- const char **argv_pack = xmalloc(5 * sizeof(const char *));
+ const char **argv_pack = xmalloc(6 * sizeof(const char *));
int i, ref_count = 0;
char buffer[1024];
struct rev_info revs;
@@ -346,7 +346,8 @@ int create_bundle(struct bundle_header *header, const char *path,
argv_pack[1] = "--all-progress-implied";
argv_pack[2] = "--stdout";
argv_pack[3] = "--thin";
- argv_pack[4] = NULL;
+ argv_pack[4] = "--delta-base-offset";
+ argv_pack[5] = NULL;
memset(&rls, 0, sizeof(rls));
rls.argv = argv_pack;
rls.in = -1;
diff --git a/cache.h b/cache.h
index 8d73d88962..50de992c5c 100644
--- a/cache.h
+++ b/cache.h
@@ -546,7 +546,6 @@ extern int assume_unchanged;
extern int prefer_symlink_refs;
extern int log_all_ref_updates;
extern int warn_ambiguous_refs;
-extern int unique_abbrev_extra_length;
extern int shared_repository;
extern const char *apply_default_whitespace;
extern const char *apply_default_ignorewhitespace;
@@ -572,7 +571,7 @@ extern enum safe_crlf safe_crlf;
enum auto_crlf {
AUTO_CRLF_FALSE = 0,
AUTO_CRLF_TRUE = 1,
- AUTO_CRLF_INPUT = -1,
+ AUTO_CRLF_INPUT = -1
};
extern enum auto_crlf auto_crlf;
@@ -609,7 +608,7 @@ enum rebase_setup_type {
enum push_default_type {
PUSH_DEFAULT_NOTHING = 0,
PUSH_DEFAULT_MATCHING,
- PUSH_DEFAULT_TRACKING,
+ PUSH_DEFAULT_UPSTREAM,
PUSH_DEFAULT_CURRENT
};
@@ -677,9 +676,11 @@ static inline void hashclr(unsigned char *hash)
#define EMPTY_TREE_SHA1_HEX \
"4b825dc642cb6eb9a060e54bf8d69288fbee4904"
-#define EMPTY_TREE_SHA1_BIN \
+#define EMPTY_TREE_SHA1_BIN_LITERAL \
"\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60" \
"\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04"
+#define EMPTY_TREE_SHA1_BIN \
+ ((const unsigned char *) EMPTY_TREE_SHA1_BIN_LITERAL)
int git_mkstemp(char *path, size_t n, const char *template);
@@ -898,7 +899,8 @@ extern struct packed_git {
time_t mtime;
int pack_fd;
unsigned pack_local:1,
- pack_keep:1;
+ pack_keep:1,
+ do_not_close:1;
unsigned char sha1[20];
/* something like ".git/objects/pack/xxxxx.pack" */
char pack_name[FLEX_ARRAY]; /* more */
@@ -998,6 +1000,7 @@ extern int git_config_maybe_bool(const char *, const char *);
extern int git_config_string(const char **, const char *, const char *);
extern int git_config_pathname(const char **, const char *, const char *);
extern int git_config_set(const char *, const char *);
+extern int git_config_parse_key(const char *, char **, int *);
extern int git_config_set_multivar(const char *, const char *, const char *, int);
extern int git_config_rename_section(const char *, const char *);
extern const char *git_etc_gitconfig(void);
diff --git a/commit.c b/commit.c
index 74d6601880..ac337c7d7d 100644
--- a/commit.c
+++ b/commit.c
@@ -245,10 +245,10 @@ int unregister_shallow(const unsigned char *sha1)
return 0;
}
-int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
+int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size)
{
- char *tail = buffer;
- char *bufptr = buffer;
+ const char *tail = buffer;
+ const char *bufptr = buffer;
unsigned char parent[20];
struct commit_list **pptr;
struct commit_graft *graft;
diff --git a/commit.h b/commit.h
index eb6c5af1f6..41985130d1 100644
--- a/commit.h
+++ b/commit.h
@@ -38,7 +38,7 @@ struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
int quiet);
struct commit *lookup_commit_reference_by_name(const char *name);
-int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size);
+int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size);
int parse_commit(struct commit *item);
/* Find beginning and length of commit subject. */
@@ -68,8 +68,7 @@ enum cmit_fmt {
CMIT_FMT_UNSPECIFIED
};
-struct pretty_print_context
-{
+struct pretty_print_context {
int abbrev;
const char *subject;
const char *after_subject;
diff --git a/compat/bswap.h b/compat/bswap.h
index 54756dbb05..5061214f73 100644
--- a/compat/bswap.h
+++ b/compat/bswap.h
@@ -21,14 +21,16 @@ static inline uint32_t default_swab32(uint32_t val)
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-#define bswap32(x) ({ \
- uint32_t __res; \
- if (__builtin_constant_p(x)) { \
- __res = default_swab32(x); \
- } else { \
- __asm__("bswap %0" : "=r" (__res) : "0" ((uint32_t)(x))); \
- } \
- __res; })
+#define bswap32 git_bswap32
+static inline uint32_t git_bswap32(uint32_t x)
+{
+ uint32_t result;
+ if (__builtin_constant_p(x))
+ result = default_swab32(x);
+ else
+ __asm__("bswap %0" : "=r" (result) : "0" (x));
+ return result;
+}
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
diff --git a/compat/mingw.h b/compat/mingw.h
index cafc1eb08a..14211c6214 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -233,6 +233,22 @@ int mingw_getpagesize(void);
#define getpagesize mingw_getpagesize
#endif
+struct rlimit {
+ unsigned int rlim_cur;
+};
+#define RLIMIT_NOFILE 0
+
+static inline int getrlimit(int resource, struct rlimit *rlp)
+{
+ if (resource != RLIMIT_NOFILE) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ rlp->rlim_cur = 2048;
+ return 0;
+}
+
/* Use mingw_lstat() instead of lstat()/stat() and
* mingw_fstat() instead of fstat() on Windows.
*/
diff --git a/config.c b/config.c
index 79e6c1896e..749e5afc45 100644
--- a/config.c
+++ b/config.c
@@ -20,8 +20,7 @@ static int zlib_compression_seen;
const char *config_exclusive_filename = NULL;
-struct config_item
-{
+struct config_item {
struct config_item *next;
char *name;
char *value;
@@ -499,13 +498,6 @@ static int git_default_core_config(const char *var, const char *value)
return 0;
}
- if (!strcmp(var, "core.abbrevguard")) {
- unique_abbrev_extra_length = git_config_int(var, value);
- if (unique_abbrev_extra_length < 0)
- unique_abbrev_extra_length = 0;
- return 0;
- }
-
if (!strcmp(var, "core.bare")) {
is_bare_repository_cfg = git_config_bool(var, value);
return 0;
@@ -745,8 +737,10 @@ static int git_default_push_config(const char *var, const char *value)
push_default = PUSH_DEFAULT_NOTHING;
else if (!strcmp(value, "matching"))
push_default = PUSH_DEFAULT_MATCHING;
- else if (!strcmp(value, "tracking"))
- push_default = PUSH_DEFAULT_TRACKING;
+ else if (!strcmp(value, "upstream"))
+ push_default = PUSH_DEFAULT_UPSTREAM;
+ else if (!strcmp(value, "tracking")) /* deprecated */
+ push_default = PUSH_DEFAULT_UPSTREAM;
else if (!strcmp(value, "current"))
push_default = PUSH_DEFAULT_CURRENT;
else {
@@ -1107,6 +1101,75 @@ int git_config_set(const char *key, const char *value)
}
/*
+ * Auxiliary function to sanity-check and split the key into the section
+ * identifier and variable name.
+ *
+ * Returns 0 on success, -1 when there is an invalid character in the key and
+ * -2 if there is no section name in the key.
+ *
+ * store_key - pointer to char* which will hold a copy of the key with
+ * lowercase section and variable name
+ * baselen - pointer to int which will hold the length of the
+ * section + subsection part, can be NULL
+ */
+int git_config_parse_key(const char *key, char **store_key, int *baselen_)
+{
+ int i, dot, baselen;
+ const char *last_dot = strrchr(key, '.');
+
+ /*
+ * Since "key" actually contains the section name and the real
+ * key name separated by a dot, we have to know where the dot is.
+ */
+
+ if (last_dot == NULL || last_dot == key) {
+ error("key does not contain a section: %s", key);
+ return -2;
+ }
+
+ if (!last_dot[1]) {
+ error("key does not contain variable name: %s", key);
+ return -2;
+ }
+
+ baselen = last_dot - key;
+ if (baselen_)
+ *baselen_ = baselen;
+
+ /*
+ * Validate the key and while at it, lower case it for matching.
+ */
+ *store_key = xmalloc(strlen(key) + 1);
+
+ dot = 0;
+ for (i = 0; key[i]; i++) {
+ unsigned char c = key[i];
+ if (c == '.')
+ dot = 1;
+ /* Leave the extended basename untouched.. */
+ if (!dot || i > baselen) {
+ if (!iskeychar(c) ||
+ (i == baselen + 1 && !isalpha(c))) {
+ error("invalid key: %s", key);
+ goto out_free_ret_1;
+ }
+ c = tolower(c);
+ } else if (c == '\n') {
+ error("invalid key (newline): %s", key);
+ goto out_free_ret_1;
+ }
+ (*store_key)[i] = c;
+ }
+ (*store_key)[i] = 0;
+
+ return 0;
+
+out_free_ret_1:
+ free(*store_key);
+ return -1;
+}
+
+/*
* If value==NULL, unset in (remove from) config,
* if value_regex!=NULL, disregard key/value pairs where value does not match.
* if multi_replace==0, nothing, or only one matching key/value is replaced,
@@ -1132,59 +1195,23 @@ int git_config_set(const char *key, const char *value)
int git_config_set_multivar(const char *key, const char *value,
const char *value_regex, int multi_replace)
{
- int i, dot;
int fd = -1, in_fd;
int ret;
char *config_filename;
struct lock_file *lock = NULL;
- const char *last_dot = strrchr(key, '.');
if (config_exclusive_filename)
config_filename = xstrdup(config_exclusive_filename);
else
config_filename = git_pathdup("config");
- /*
- * Since "key" actually contains the section name and the real
- * key name separated by a dot, we have to know where the dot is.
- */
-
- if (last_dot == NULL) {
- error("key does not contain a section: %s", key);
- ret = 2;
+ /* parse-key returns negative; flip the sign to feed exit(3) */
+ ret = 0 - git_config_parse_key(key, &store.key, &store.baselen);
+ if (ret)
goto out_free;
- }
- store.baselen = last_dot - key;
store.multi_replace = multi_replace;
- /*
- * Validate the key and while at it, lower case it for matching.
- */
- store.key = xmalloc(strlen(key) + 1);
- dot = 0;
- for (i = 0; key[i]; i++) {
- unsigned char c = key[i];
- if (c == '.')
- dot = 1;
- /* Leave the extended basename untouched.. */
- if (!dot || i > store.baselen) {
- if (!iskeychar(c) || (i == store.baselen+1 && !isalpha(c))) {
- error("invalid key: %s", key);
- free(store.key);
- ret = 1;
- goto out_free;
- }
- c = tolower(c);
- } else if (c == '\n') {
- error("invalid key (newline): %s", key);
- free(store.key);
- ret = 1;
- goto out_free;
- }
- store.key[i] = c;
- }
- store.key[i] = 0;
/*
* The lock serves a purpose in addition to locking: the new
diff --git a/configure.ac b/configure.ac
index 5792425a49..20039c546f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -345,7 +345,7 @@ esac
AC_CACHE_CHECK([if linker supports -R], git_cv_ld_dashr, [
SAVE_LDFLAGS="${LDFLAGS}"
LDFLAGS="${SAVE_LDFLAGS} -R /"
- AC_LINK_IFELSE(AC_LANG_PROGRAM([], []), [git_cv_ld_dashr=yes], [git_cv_ld_dashr=no])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [git_cv_ld_dashr=yes], [git_cv_ld_dashr=no])
LDFLAGS="${SAVE_LDFLAGS}"
])
if test "$git_cv_ld_dashr" = "yes"; then
@@ -354,7 +354,7 @@ else
AC_CACHE_CHECK([if linker supports -Wl,-rpath,], git_cv_ld_wl_rpath, [
SAVE_LDFLAGS="${LDFLAGS}"
LDFLAGS="${SAVE_LDFLAGS} -Wl,-rpath,/"
- AC_LINK_IFELSE(AC_LANG_PROGRAM([], []), [git_cv_ld_wl_rpath=yes], [git_cv_ld_wl_rpath=no])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [git_cv_ld_wl_rpath=yes], [git_cv_ld_wl_rpath=no])
LDFLAGS="${SAVE_LDFLAGS}"
])
if test "$git_cv_ld_wl_rpath" = "yes"; then
@@ -363,7 +363,7 @@ else
AC_CACHE_CHECK([if linker supports -rpath], git_cv_ld_rpath, [
SAVE_LDFLAGS="${LDFLAGS}"
LDFLAGS="${SAVE_LDFLAGS} -rpath /"
- AC_LINK_IFELSE(AC_LANG_PROGRAM([], []), [git_cv_ld_rpath=yes], [git_cv_ld_rpath=no])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [git_cv_ld_rpath=yes], [git_cv_ld_rpath=no])
LDFLAGS="${SAVE_LDFLAGS}"
])
if test "$git_cv_ld_rpath" = "yes"; then
@@ -472,15 +472,9 @@ if test -z "$NO_ICONV"; then
GIT_STASH_FLAGS($ICONVDIR)
-AC_DEFUN([ICONVTEST_SRC], [
-#include <iconv.h>
-
-int main(void)
-{
- iconv_open("", "");
- return 0;
-}
-])
+AC_DEFUN([ICONVTEST_SRC],
+[AC_LANG_PROGRAM([#include <iconv.h>],
+ [iconv_open("", "");])])
if test -n "$ICONVDIR"; then
lib_order="-liconv -lc"
@@ -500,7 +494,7 @@ for l in $lib_order; do
old_LIBS="$LIBS"
LIBS="$LIBS $l"
AC_MSG_CHECKING([for iconv in $l])
- AC_LINK_IFELSE(ICONVTEST_SRC,
+ AC_LINK_IFELSE([ICONVTEST_SRC],
[AC_MSG_RESULT([yes])
NO_ICONV=
break],
@@ -528,18 +522,12 @@ fi
GIT_STASH_FLAGS($ZLIB_PATH)
AC_DEFUN([ZLIBTEST_SRC], [
-#include <zlib.h>
-
-int main(void)
-{
- deflateBound(0, 0);
- return 0;
-}
-])
+AC_LANG_PROGRAM([#include <zlib.h>],
+ [deflateBound(0, 0);])])
AC_MSG_CHECKING([for deflateBound in -lz])
old_LIBS="$LIBS"
LIBS="$LIBS -lz"
-AC_LINK_IFELSE(ZLIBTEST_SRC,
+AC_LINK_IFELSE([ZLIBTEST_SRC],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
NO_DEFLATE_BOUND=yes])
@@ -631,23 +619,19 @@ AC_SUBST(NO_INTTYPES_H)
#
# Define OLD_ICONV if your library has an old iconv(), where the second
# (input buffer pointer) parameter is declared with type (const char **).
-AC_DEFUN([OLDICONVTEST_SRC], [[
+AC_DEFUN([OLDICONVTEST_SRC], [
+AC_LANG_PROGRAM([[
#include <iconv.h>
extern size_t iconv(iconv_t cd,
char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft);
-
-int main(void)
-{
- return 0;
-}
-]])
+]], [])])
GIT_STASH_FLAGS($ICONVDIR)
AC_MSG_CHECKING([for old iconv()])
-AC_COMPILE_IFELSE(OLDICONVTEST_SRC,
+AC_COMPILE_IFELSE([OLDICONVTEST_SRC],
[AC_MSG_RESULT([no])],
[AC_MSG_RESULT([yes])
OLD_ICONV=UnfortunatelyYes])
@@ -931,18 +915,16 @@ AC_SUBST(NO_INITGROUPS)
#
# Define PTHREAD_LIBS to the linker flag used for Pthread support.
AC_DEFUN([PTHREADTEST_SRC], [
+AC_LANG_PROGRAM([[
#include <pthread.h>
-
-int main(void)
-{
+]], [[
pthread_mutex_t test_mutex;
int retcode = 0;
retcode |= pthread_mutex_init(&test_mutex,(void *)0);
retcode |= pthread_mutex_lock(&test_mutex);
retcode |= pthread_mutex_unlock(&test_mutex);
return retcode;
-}
-])
+]])])
dnl AC_LANG_CONFTEST([AC_LANG_PROGRAM(
dnl [[#include <pthread.h>]],
@@ -962,7 +944,7 @@ elif test -z "$PTHREAD_CFLAGS"; then
old_CFLAGS="$CFLAGS"
CFLAGS="$opt $CFLAGS"
AC_MSG_CHECKING([Checking for POSIX Threads with '$opt'])
- AC_LINK_IFELSE(PTHREADTEST_SRC,
+ AC_LINK_IFELSE([PTHREADTEST_SRC],
[AC_MSG_RESULT([yes])
NO_PTHREADS=
PTHREAD_LIBS="$opt"
@@ -982,7 +964,7 @@ else
old_CFLAGS="$CFLAGS"
CFLAGS="$PTHREAD_CFLAGS $CFLAGS"
AC_MSG_CHECKING([Checking for POSIX Threads with '$PTHREAD_CFLAGS'])
- AC_LINK_IFELSE(PTHREADTEST_SRC,
+ AC_LINK_IFELSE([PTHREADTEST_SRC],
[AC_MSG_RESULT([yes])
NO_PTHREADS=
PTHREAD_LIBS="$PTHREAD_CFLAGS"
diff --git a/contrib/hooks/post-receive-email b/contrib/hooks/post-receive-email
index f99ea95850..21989fc6ab 100755
--- a/contrib/hooks/post-receive-email
+++ b/contrib/hooks/post-receive-email
@@ -709,7 +709,7 @@ if [ -z "$GIT_DIR" ]; then
exit 1
fi
-projectdesc=$(sed -ne '1p' "$GIT_DIR/description")
+projectdesc=$(sed -ne '1p' "$GIT_DIR/description" 2>/dev/null)
# Check if the description is unchanged from it's default, and shorten it to
# a more manageable length if it is
if expr "$projectdesc" : "Unnamed repository.*$" >/dev/null
diff --git a/contrib/svn-fe/svn-fe.txt b/contrib/svn-fe/svn-fe.txt
index 35f84bd9e7..cd075b96c5 100644
--- a/contrib/svn-fe/svn-fe.txt
+++ b/contrib/svn-fe/svn-fe.txt
@@ -18,6 +18,9 @@ Subversion repository mirrored on the local disk. Remote Subversion
repositories can be mirrored on local disk using the `svnsync`
command.
+Note: this tool is very young. The details of its commandline
+interface may change in backward incompatible ways.
+
INPUT FORMAT
------------
Subversion's repository dump format is documented in full in
diff --git a/contrib/thunderbird-patch-inline/appp.sh b/contrib/thunderbird-patch-inline/appp.sh
index cc518f3c89..5eb4a51643 100755
--- a/contrib/thunderbird-patch-inline/appp.sh
+++ b/contrib/thunderbird-patch-inline/appp.sh
@@ -1,8 +1,8 @@
-#!/bin/bash
+#!/bin/sh
# Copyright 2008 Lukas Sandström <luksan@gmail.com>
#
# AppendPatch - A script to be used together with ExternalEditor
-# for Mozilla Thunderbird to properly include pathes inline i e-mails.
+# for Mozilla Thunderbird to properly include patches inline in e-mails.
# ExternalEditor can be downloaded at http://globs.org/articles.php?lng=en&pg=2
diff --git a/convert.c b/convert.c
index d5aebed48d..7eb51b16ed 100644
--- a/convert.c
+++ b/convert.c
@@ -18,7 +18,7 @@ enum action {
CRLF_TEXT,
CRLF_INPUT,
CRLF_CRLF,
- CRLF_AUTO,
+ CRLF_AUTO
};
struct text_stat {
diff --git a/diff-lib.c b/diff-lib.c
index 392ce2bef0..f8e33256eb 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -103,7 +103,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
unsigned dirty_submodule = 0;
if (DIFF_OPT_TST(&revs->diffopt, QUICK) &&
- DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES))
+ !revs->diffopt.filter &&
+ DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES))
break;
if (!ce_path_match(ce, revs->prune_data))
diff --git a/diff.c b/diff.c
index 5422c43882..3fd9e0c703 100644
--- a/diff.c
+++ b/diff.c
@@ -245,6 +245,15 @@ static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
return 0;
}
+/* like fill_mmfile, but only for size, so we can avoid retrieving blob */
+static unsigned long diff_filespec_size(struct diff_filespec *one)
+{
+ if (!DIFF_FILE_VALID(one))
+ return 0;
+ diff_populate_filespec(one, 1);
+ return one->size;
+}
+
static int count_trailing_blank(mmfile_t *mf, unsigned ws_rule)
{
char *ptr = mf->ptr;
@@ -606,16 +615,14 @@ static void diff_words_append(char *line, unsigned long len,
buffer->text.ptr[buffer->text.size] = '\0';
}
-struct diff_words_style_elem
-{
+struct diff_words_style_elem {
const char *prefix;
const char *suffix;
const char *color; /* NULL; filled in by the setup code if
* color is enabled */
};
-struct diff_words_style
-{
+struct diff_words_style {
enum diff_words_type type;
struct diff_words_style_elem new, old, ctx;
const char *newline;
@@ -2079,25 +2086,28 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
data->is_unmerged = 1;
return;
}
- if (complete_rewrite) {
+
+ if (diff_filespec_is_binary(one) || diff_filespec_is_binary(two)) {
+ data->is_binary = 1;
+ data->added = diff_filespec_size(two);
+ data->deleted = diff_filespec_size(one);
+ }
+
+ else if (complete_rewrite) {
diff_populate_filespec(one, 0);
diff_populate_filespec(two, 0);
data->deleted = count_lines(one->data, one->size);
data->added = count_lines(two->data, two->size);
- goto free_and_return;
}
- if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
- die("unable to read files to diff");
- if (diff_filespec_is_binary(one) || diff_filespec_is_binary(two)) {
- data->is_binary = 1;
- data->added = mf2.size;
- data->deleted = mf1.size;
- } else {
+ else {
/* Crazy xdl interfaces.. */
xpparam_t xpp;
xdemitconf_t xecfg;
+ if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
+ die("unable to read files to diff");
+
memset(&xpp, 0, sizeof(xpp));
memset(&xecfg, 0, sizeof(xecfg));
xpp.flags = o->xdl_opts;
@@ -2105,7 +2115,6 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
&xpp, &xecfg);
}
- free_and_return:
diff_free_filespec_data(one);
diff_free_filespec_data(two);
}
diff --git a/diffcore-rename.c b/diffcore-rename.c
index df41be56de..0cd4c1305b 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -170,7 +170,7 @@ static int estimate_similarity(struct diff_filespec *src,
* and the final score computation below would not have a
* divide-by-zero issue.
*/
- if (base_size * (MAX_SCORE-minimum_score) < delta_size * MAX_SCORE)
+ if (max_size * (MAX_SCORE-minimum_score) < delta_size * MAX_SCORE)
return 0;
if (!src->cnt_data && diff_populate_filespec(src, 0))
@@ -247,7 +247,8 @@ struct file_similarity {
};
static int find_identical_files(struct file_similarity *src,
- struct file_similarity *dst)
+ struct file_similarity *dst,
+ struct diff_options *options)
{
int renames = 0;
@@ -277,6 +278,8 @@ static int find_identical_files(struct file_similarity *src,
}
/* Give higher scores to sources that haven't been used already */
score = !source->rename_used;
+ if (source->rename_used && options->detect_rename != DIFF_DETECT_COPY)
+ continue;
score += basename_same(source, target);
if (score > best_score) {
best = p;
@@ -306,11 +309,12 @@ static void free_similarity_list(struct file_similarity *p)
}
}
-static int find_same_files(void *ptr)
+static int find_same_files(void *ptr, void *data)
{
int ret;
struct file_similarity *p = ptr;
struct file_similarity *src = NULL, *dst = NULL;
+ struct diff_options *options = data;
/* Split the hash list up into sources and destinations */
do {
@@ -329,7 +333,7 @@ static int find_same_files(void *ptr)
* If we have both sources *and* destinations, see if
* we can match them up
*/
- ret = (src && dst) ? find_identical_files(src, dst) : 0;
+ ret = (src && dst) ? find_identical_files(src, dst, options) : 0;
/* Free the hashes and return the number of renames found */
free_similarity_list(src);
@@ -377,7 +381,7 @@ static void insert_file_table(struct hash_table *table, int src_dst, int index,
* and then during the second round we try to match
* cache-dirty entries as well.
*/
-static int find_exact_renames(void)
+static int find_exact_renames(struct diff_options *options)
{
int i;
struct hash_table file_table;
@@ -390,7 +394,7 @@ static int find_exact_renames(void)
insert_file_table(&file_table, 1, i, rename_dst[i].two);
/* Find the renames */
- i = for_each_hash(&file_table, find_same_files);
+ i = for_each_hash(&file_table, find_same_files, options);
/* .. and free the hash data structure */
free_hash(&file_table);
@@ -414,6 +418,27 @@ static void record_if_better(struct diff_score m[], struct diff_score *o)
m[worst] = *o;
}
+static int find_renames(struct diff_score *mx, int dst_cnt, int minimum_score, int copies)
+{
+ int count = 0, i;
+
+ for (i = 0; i < dst_cnt * NUM_CANDIDATE_PER_DST; i++) {
+ struct diff_rename_dst *dst;
+
+ if ((mx[i].dst < 0) ||
+ (mx[i].score < minimum_score))
+ break; /* there is no more usable pair. */
+ dst = &rename_dst[mx[i].dst];
+ if (dst->pair)
+ continue; /* already done, either exact or fuzzy. */
+ if (!copies && rename_src[mx[i].src].one->rename_used)
+ continue;
+ record_rename_pair(mx[i].dst, mx[i].src, mx[i].score);
+ count++;
+ }
+ return count;
+}
+
void diffcore_rename(struct diff_options *options)
{
int detect_rename = options->detect_rename;
@@ -467,7 +492,7 @@ void diffcore_rename(struct diff_options *options)
* We really want to cull the candidates list early
* with cheap tests in order to avoid doing deltas.
*/
- rename_count = find_exact_renames();
+ rename_count = find_exact_renames(options);
/* Did we only want exact renames? */
if (minimum_score == MAX_SCORE)
@@ -536,33 +561,9 @@ void diffcore_rename(struct diff_options *options)
/* cost matrix sorted by most to least similar pair */
qsort(mx, dst_cnt * NUM_CANDIDATE_PER_DST, sizeof(*mx), score_compare);
- for (i = 0; i < dst_cnt * NUM_CANDIDATE_PER_DST; i++) {
- struct diff_rename_dst *dst;
-
- if ((mx[i].dst < 0) ||
- (mx[i].score < minimum_score))
- break; /* there is no more usable pair. */
- dst = &rename_dst[mx[i].dst];
- if (dst->pair)
- continue; /* already done, either exact or fuzzy. */
- if (rename_src[mx[i].src].one->rename_used)
- continue;
- record_rename_pair(mx[i].dst, mx[i].src, mx[i].score);
- rename_count++;
- }
-
- for (i = 0; i < dst_cnt * NUM_CANDIDATE_PER_DST; i++) {
- struct diff_rename_dst *dst;
-
- if ((mx[i].dst < 0) ||
- (mx[i].score < minimum_score))
- break; /* there is no more usable pair. */
- dst = &rename_dst[mx[i].dst];
- if (dst->pair)
- continue; /* already done, either exact or fuzzy. */
- record_rename_pair(mx[i].dst, mx[i].src, mx[i].score);
- rename_count++;
- }
+ rename_count += find_renames(mx, dst_cnt, minimum_score, 0);
+ if (detect_rename == DIFF_DETECT_COPY)
+ rename_count += find_renames(mx, dst_cnt, minimum_score, 1);
free(mx);
cleanup:
diff --git a/environment.c b/environment.c
index f2d90a807b..33c806421e 100644
--- a/environment.c
+++ b/environment.c
@@ -22,7 +22,6 @@ int prefer_symlink_refs;
int is_bare_repository_cfg = -1; /* unspecified */
int log_all_ref_updates = -1; /* unspecified */
int warn_ambiguous_refs = 1;
-int unique_abbrev_extra_length;
int repository_format_version;
const char *git_commit_encoding;
const char *git_log_output_encoding;
diff --git a/fast-import.c b/fast-import.c
index 60f26fe473..b3ba778924 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -166,8 +166,7 @@ Format of STDIN stream:
#define DEPTH_BITS 13
#define MAX_DEPTH ((1<<DEPTH_BITS)-1)
-struct object_entry
-{
+struct object_entry {
struct pack_idx_entry idx;
struct object_entry *next;
uint32_t type : TYPE_BITS,
@@ -175,16 +174,14 @@ struct object_entry
depth : DEPTH_BITS;
};
-struct object_entry_pool
-{
+struct object_entry_pool {
struct object_entry_pool *next_pool;
struct object_entry *next_free;
struct object_entry *end;
struct object_entry entries[FLEX_ARRAY]; /* more */
};
-struct mark_set
-{
+struct mark_set {
union {
struct object_entry *marked[1024];
struct mark_set *sets[1024];
@@ -192,57 +189,49 @@ struct mark_set
unsigned int shift;
};
-struct last_object
-{
+struct last_object {
struct strbuf data;
off_t offset;
unsigned int depth;
unsigned no_swap : 1;
};
-struct mem_pool
-{
+struct mem_pool {
struct mem_pool *next_pool;
char *next_free;
char *end;
uintmax_t space[FLEX_ARRAY]; /* more */
};
-struct atom_str
-{
+struct atom_str {
struct atom_str *next_atom;
unsigned short str_len;
char str_dat[FLEX_ARRAY]; /* more */
};
struct tree_content;
-struct tree_entry
-{
+struct tree_entry {
struct tree_content *tree;
struct atom_str *name;
- struct tree_entry_ms
- {
+ struct tree_entry_ms {
uint16_t mode;
unsigned char sha1[20];
} versions[2];
};
-struct tree_content
-{
+struct tree_content {
unsigned int entry_capacity; /* must match avail_tree_content */
unsigned int entry_count;
unsigned int delta_depth;
struct tree_entry *entries[FLEX_ARRAY]; /* more */
};
-struct avail_tree_content
-{
+struct avail_tree_content {
unsigned int entry_capacity; /* must match tree_content */
struct avail_tree_content *next_avail;
};
-struct branch
-{
+struct branch {
struct branch *table_next_branch;
struct branch *active_next_branch;
const char *name;
@@ -254,16 +243,14 @@ struct branch
unsigned char sha1[20];
};
-struct tag
-{
+struct tag {
struct tag *next_tag;
const char *name;
unsigned int pack_id;
unsigned char sha1[20];
};
-struct hash_list
-{
+struct hash_list {
struct hash_list *next;
unsigned char sha1[20];
};
@@ -274,8 +261,7 @@ typedef enum {
WHENSPEC_NOW
} whenspec_type;
-struct recent_command
-{
+struct recent_command {
struct recent_command *prev;
struct recent_command *next;
char *buf;
@@ -871,6 +857,7 @@ static void start_packfile(void)
p = xcalloc(1, sizeof(*p) + strlen(tmpfile) + 2);
strcpy(p->pack_name, tmpfile);
p->pack_fd = pack_fd;
+ p->do_not_close = 1;
pack_file = sha1fd(pack_fd, p->pack_name);
hdr.hdr_signature = htonl(PACK_SIGNATURE);
@@ -2991,6 +2978,8 @@ static int parse_one_feature(const char *feature, int from_stream)
relative_marks_paths = 0;
} else if (!prefixcmp(feature, "force")) {
force_update = 1;
+ } else if (!strcmp(feature, "notes")) {
+ ; /* do nothing; we have the feature */
} else {
return 0;
}
diff --git a/fetch-pack.h b/fetch-pack.h
index fbe85ac05f..0608edae3f 100644
--- a/fetch-pack.h
+++ b/fetch-pack.h
@@ -1,8 +1,7 @@
#ifndef FETCH_PACK_H
#define FETCH_PACK_H
-struct fetch_pack_args
-{
+struct fetch_pack_args {
const char *uploadpack;
int unpacklimit;
int depth;
diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh
index 75c68d948f..3ef4861d04 100755
--- a/generate-cmdlist.sh
+++ b/generate-cmdlist.sh
@@ -1,8 +1,7 @@
#!/bin/sh
echo "/* Automatically generated by $0 */
-struct cmdname_help
-{
+struct cmdname_help {
char name[16];
char help[80];
};
diff --git a/git-bisect.sh b/git-bisect.sh
index c21e33c8d1..415a8d04cc 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -288,10 +288,12 @@ bisect_visualize() {
if test $# = 0
then
- case "${DISPLAY+set}${SESSIONNAME+set}${MSYSTEM+set}${SECURITYSESSIONID+set}" in
- '') set git log ;;
- set*) set gitk ;;
- esac
+ if test -n "${DISPLAY+set}${SESSIONNAME+set}${MSYSTEM+set}${SECURITYSESSIONID+set}" &&
+ type gitk >/dev/null 2>&1; then
+ set gitk
+ else
+ set git log
+ fi
else
case "$1" in
git*|tig) ;;
diff --git a/git-compat-util.h b/git-compat-util.h
index d6d269f138..79b5122b4f 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -31,6 +31,9 @@
#define maximum_signed_value_of_type(a) \
(INTMAX_MAX >> (bitsizeof(intmax_t) - bitsizeof(a)))
+#define maximum_unsigned_value_of_type(a) \
+ (UINTMAX_MAX >> (bitsizeof(uintmax_t) - bitsizeof(a)))
+
/*
* Signed integer overflow is undefined in C, so here's a helper macro
* to detect if the sum of two integers will overflow.
@@ -40,6 +43,9 @@
#define signed_add_overflows(a, b) \
((b) > maximum_signed_value_of_type(a) - (a))
+#define unsigned_add_overflows(a, b) \
+ ((b) > maximum_unsigned_value_of_type(a) - (a))
+
#ifdef __GNUC__
#define TYPEOF(x) (__typeof__(x))
#else
@@ -112,6 +118,7 @@
#endif
#ifndef __MINGW32__
#include <sys/wait.h>
+#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <termios.h>
@@ -208,7 +215,10 @@ extern char *gitbasename(char *);
#define is_dir_sep(c) ((c) == '/')
#endif
-#ifdef __GNUC__
+#if __HP_cc >= 61000
+#define NORETURN __attribute__((noreturn))
+#define NORETURN_PTR
+#elif defined(__GNUC__)
#define NORETURN __attribute__((__noreturn__))
#define NORETURN_PTR __attribute__((__noreturn__))
#elif defined(_MSC_VER)
diff --git a/git-cvsimport.perl b/git-cvsimport.perl
index 8e683e5478..bbf327f3e8 100755
--- a/git-cvsimport.perl
+++ b/git-cvsimport.perl
@@ -366,7 +366,9 @@ sub conn {
$self->{'socketo'}->write("valid-requests\n");
$self->{'socketo'}->flush();
- chomp(my $rep=$self->readline());
+ my $rep=$self->readline();
+ die "Failed to read from server" unless defined $rep;
+ chomp($rep);
if ($rep !~ s/^Valid-requests\s*//) {
$rep="<unknown>" unless $rep;
die "Expected Valid-requests from server, but got: $rep\n";
diff --git a/git-instaweb.sh b/git-instaweb.sh
index 10fcebb119..8bfa8a055c 100755
--- a/git-instaweb.sh
+++ b/git-instaweb.sh
@@ -558,12 +558,14 @@ my \$app = builder {
# make it runnable as standalone app,
# like it would be run via 'plackup' utility
-if (__FILE__ eq \$0) {
+if (caller) {
+ return \$app;
+} else {
require Plack::Runner;
my \$runner = Plack::Runner->new();
\$runner->parse_options(qw(--env deployment --port $port),
- "$local" ? qw(--host 127.0.0.1) : ());
+ "$local" ? qw(--host 127.0.0.1) : ());
\$runner->run(\$app);
}
__END__
diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh
index 77d4aee20e..78ce49e984 100644
--- a/git-mergetool--lib.sh
+++ b/git-mergetool--lib.sh
@@ -182,7 +182,7 @@ run_merge_tool () {
fi
check_unchanged
else
- "$merge_tool_path" -f -d -c "wincmd l" \
+ "$merge_tool_path" -R -f -d -c "wincmd l" \
"$LOCAL" "$REMOTE"
fi
;;
@@ -193,7 +193,7 @@ run_merge_tool () {
"$LOCAL" "$MERGED" "$REMOTE"
check_unchanged
else
- "$merge_tool_path" -f -d -c "wincmd l" \
+ "$merge_tool_path" -R -f -d -c "wincmd l" \
"$LOCAL" "$REMOTE"
fi
;;
diff --git a/git-parse-remote.sh b/git-parse-remote.sh
index 1cc2ba6e09..9b950be28d 100644
--- a/git-parse-remote.sh
+++ b/git-parse-remote.sh
@@ -55,7 +55,8 @@ get_remote_url () {
}
get_default_remote () {
- curr_branch=$(git symbolic-ref -q HEAD | sed -e 's|^refs/heads/||')
+ curr_branch=$(git symbolic-ref -q HEAD)
+ curr_branch="${curr_branch#refs/heads/}"
origin=$(git config --get "branch.$curr_branch.remote")
echo ${origin:-origin}
}
diff --git a/git-pull.sh b/git-pull.sh
index eb87f49062..f6b7b84048 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -114,7 +114,7 @@ do
--d|--dr|--dry|--dry-|--dry-r|--dry-ru|--dry-run)
dry_run=--dry-run
;;
- -h|--h|--he|--hel|--help)
+ -h|--h|--he|--hel|--help|--help-|--help-a|--help-al|--help-all)
usage
;;
*)
diff --git a/git-stash.sh b/git-stash.sh
index 7561b374d2..a305fb19f1 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -12,12 +12,14 @@ USAGE="list [<options>]
SUBDIRECTORY_OK=Yes
OPTIONS_SPEC=
+START_DIR=`pwd`
. git-sh-setup
require_work_tree
cd_to_toplevel
TMP="$GIT_DIR/.git-stash.$$"
-trap 'rm -f "$TMP-*"' 0
+TMPindex=${GIT_INDEX_FILE-"$GIT_DIR/index"}.stash.$$
+trap 'rm -f "$TMP-"* "$TMPindex"' 0
ref_stash=refs/stash
@@ -81,14 +83,12 @@ create_stash () {
# state of the working tree
w_tree=$( (
- rm -f "$TMP-index" &&
- cp -p ${GIT_INDEX_FILE-"$GIT_DIR/index"} "$TMP-index" &&
- GIT_INDEX_FILE="$TMP-index" &&
+ git read-tree --index-output="$TMPindex" -m $i_tree &&
+ GIT_INDEX_FILE="$TMPindex" &&
export GIT_INDEX_FILE &&
- git read-tree -m $i_tree &&
git diff --name-only -z HEAD | git update-index -z --add --remove --stdin &&
git write-tree &&
- rm -f "$TMP-index"
+ rm -f "$TMPindex"
) ) ||
die "Cannot save the current worktree state"
@@ -394,7 +394,7 @@ apply_stash () {
then
squelch='>/dev/null 2>&1'
fi
- eval "git status $squelch" || :
+ (cd "$START_DIR" && eval "git status $squelch") || :
else
# Merge conflict; keep the exit status from merge-recursive
status=$?
diff --git a/git-submodule.sh b/git-submodule.sh
index 8b90589717..3a13397e05 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -423,6 +423,7 @@ cmd_update()
cmd_init "--" "$@" || return
fi
+ cloned_modules=
module_list "$@" |
while read mode sha1 stage path
do
@@ -442,6 +443,7 @@ cmd_update()
if ! test -d "$path"/.git -o -f "$path"/.git
then
module_clone "$path" "$url" "$reference"|| exit
+ cloned_modules="$cloned_modules;$name"
subsha1=
else
subsha1=$(clear_local_git_env; cd "$path" &&
@@ -469,6 +471,13 @@ cmd_update()
die "Unable to fetch in submodule path '$path'"
fi
+ # Is this something we just cloned?
+ case ";$cloned_modules;" in
+ *";$name;"*)
+ # then there is no local change to integrate
+ update_module= ;;
+ esac
+
case "$update_module" in
rebase)
command="git rebase"
diff --git a/gitweb/INSTALL b/gitweb/INSTALL
index 823053173c..4964a679b3 100644
--- a/gitweb/INSTALL
+++ b/gitweb/INSTALL
@@ -237,6 +237,12 @@ Requirements
- Perl modules: CGI, Encode, Fcntl, File::Find, File::Basename.
- web server
+The following optional Perl modules are required for extra features
+ - Digest::MD5 - for gravatar support
+ - CGI::Fast and FCGI - for running gitweb as FastCGI script
+ - HTML::TagCloud - for fancy tag cloud in project list view
+ - HTTP::Date or Time::ParseDate - to support If-Modified-Since for feeds
+
Example web server configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 0779f12d61..46186ab909 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -2913,8 +2913,10 @@ sub parse_date {
$date{'iso-8601'} = sprintf "%04d-%02d-%02dT%02d:%02d:%02dZ",
1900+$year, 1+$mon, $mday, $hour ,$min, $sec;
- $tz =~ m/^([+\-][0-9][0-9])([0-9][0-9])$/;
- my $local = $epoch + ((int $1 + ($2/60)) * 3600);
+ my ($tz_sign, $tz_hour, $tz_min) =
+ ($tz =~ m/^([-+])(\d\d)(\d\d)$/);
+ $tz_sign = ($tz_sign eq '-' ? -1 : +1);
+ my $local = $epoch + $tz_sign*((($tz_hour*60) + $tz_min)*60);
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($local);
$date{'hour_local'} = $hour;
$date{'minute_local'} = $min;
@@ -3468,7 +3470,7 @@ sub run_highlighter {
close $fd;
open $fd, quote_command(git_cmd(), "cat-file", "blob", $hash)." | ".
quote_command($highlight_bin).
- " --fragment --syntax $syntax |"
+ " --replace-tabs=8 --fragment --syntax $syntax |"
or die_error(500, "Couldn't open file or run syntax highlighter");
return $fd;
}
@@ -3501,7 +3503,7 @@ sub print_feed_meta {
$href_params{'-title'} = 'log';
}
- foreach my $format qw(RSS Atom) {
+ foreach my $format (qw(RSS Atom)) {
my $type = lc($format);
my %link_attr = (
'-rel' => 'alternate',
@@ -3682,7 +3684,7 @@ sub git_footer_html {
}
$href_params{'-title'} ||= 'log';
- foreach my $format qw(RSS Atom) {
+ foreach my $format (qw(RSS Atom)) {
$href_params{'action'} = lc($format);
print $cgi->a({-href => href(%href_params),
-title => "$href_params{'-title'} $format feed",
@@ -4412,7 +4414,7 @@ sub git_difftree_body {
}
if ($diff->{'from_mode'} ne ('0' x 6)) {
$from_mode_oct = oct $diff->{'from_mode'};
- if (S_ISREG($to_mode_oct)) { # only for regular file
+ if (S_ISREG($from_mode_oct)) { # only for regular file
$from_mode_str = sprintf("%04o", $from_mode_oct & 0777); # permission bits
}
$from_file_type = file_type($diff->{'from_mode'});
@@ -4906,7 +4908,6 @@ sub git_log_body {
next if !%co;
my $commit = $co{'id'};
my $ref = format_ref_marker($refs, $commit);
- my %ad = parse_date($co{'author_epoch'});
git_print_header_div('commit',
"<span class=\"age\">$co{'age_string'}</span>" .
esc_html($co{'title'}) . $ref,
@@ -7064,7 +7065,7 @@ sub git_feed {
if (defined($commitlist[0])) {
%latest_commit = %{$commitlist[0]};
my $latest_epoch = $latest_commit{'committer_epoch'};
- %latest_date = parse_date($latest_epoch);
+ %latest_date = parse_date($latest_epoch, $latest_commit{'comitter_tz'});
my $if_modified = $cgi->http('IF_MODIFIED_SINCE');
if (defined $if_modified) {
my $since;
@@ -7195,7 +7196,7 @@ XML
if (($i >= 20) && ((time - $co{'author_epoch'}) > 48*60*60)) {
last;
}
- my %cd = parse_date($co{'author_epoch'});
+ my %cd = parse_date($co{'author_epoch'}, $co{'author_tz'});
# get list of changed files
open my $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
diff --git a/hash.c b/hash.c
index 1cd4c9d5c0..749ecfe484 100644
--- a/hash.c
+++ b/hash.c
@@ -81,7 +81,7 @@ void **insert_hash(unsigned int hash, void *ptr, struct hash_table *table)
return insert_hash_entry(hash, ptr, table);
}
-int for_each_hash(const struct hash_table *table, int (*fn)(void *))
+int for_each_hash(const struct hash_table *table, int (*fn)(void *, void *), void *data)
{
int sum = 0;
unsigned int i;
@@ -92,7 +92,7 @@ int for_each_hash(const struct hash_table *table, int (*fn)(void *))
void *ptr = array->ptr;
array++;
if (ptr) {
- int val = fn(ptr);
+ int val = fn(ptr, data);
if (val < 0)
return val;
sum += val;
diff --git a/hash.h b/hash.h
index 69e33a47b9..b875ce67c4 100644
--- a/hash.h
+++ b/hash.h
@@ -30,7 +30,7 @@ struct hash_table {
extern void *lookup_hash(unsigned int hash, const struct hash_table *table);
extern void **insert_hash(unsigned int hash, void *ptr, struct hash_table *table);
-extern int for_each_hash(const struct hash_table *table, int (*fn)(void *));
+extern int for_each_hash(const struct hash_table *table, int (*fn)(void *, void *), void *data);
extern void free_hash(struct hash_table *table);
static inline void init_hash(struct hash_table *table)
diff --git a/http-push.c b/http-push.c
index ff41a0e183..d18346c0f5 100644
--- a/http-push.c
+++ b/http-push.c
@@ -82,8 +82,7 @@ static int helper_status;
static struct object_list *objects;
-struct repo
-{
+struct repo {
char *url;
char *path;
int path_len;
@@ -108,8 +107,7 @@ enum transfer_state {
COMPLETE
};
-struct transfer_request
-{
+struct transfer_request {
struct object *obj;
char *url;
char *dest;
@@ -127,8 +125,7 @@ struct transfer_request
static struct transfer_request *request_queue_head;
-struct xml_ctx
-{
+struct xml_ctx {
char *name;
int len;
char *cdata;
@@ -136,8 +133,7 @@ struct xml_ctx
void *userData;
};
-struct remote_lock
-{
+struct remote_lock {
char *url;
char *owner;
char *token;
@@ -156,8 +152,7 @@ struct remote_lock
/* Flags that remote_ls passes to callback functions */
#define IS_DIR (1u << 0)
-struct remote_ls_ctx
-{
+struct remote_ls_ctx {
char *path;
void (*userFunc)(struct remote_ls_ctx *ls);
void *userData;
diff --git a/http-walker.c b/http-walker.c
index 18bd6504be..9bc8114c3b 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -3,8 +3,7 @@
#include "walker.h"
#include "http.h"
-struct alt_base
-{
+struct alt_base {
char *base;
int got_indices;
struct packed_git *packs;
@@ -18,8 +17,7 @@ enum object_request_state {
COMPLETE
};
-struct object_request
-{
+struct object_request {
struct walker *walker;
unsigned char sha1[20];
struct alt_base *repo;
diff --git a/http.h b/http.h
index 5c6e243dde..e9ed3c2e82 100644
--- a/http.h
+++ b/http.h
@@ -42,14 +42,12 @@
#define NO_CURL_IOCTL
#endif
-struct slot_results
-{
+struct slot_results {
CURLcode curl_result;
long http_code;
};
-struct active_request_slot
-{
+struct active_request_slot {
CURL *curl;
FILE *local;
int in_use;
@@ -62,8 +60,7 @@ struct active_request_slot
struct active_request_slot *next;
};
-struct buffer
-{
+struct buffer {
struct strbuf buf;
size_t posn;
};
@@ -149,8 +146,7 @@ extern int http_fetch_ref(const char *base, struct ref *ref);
extern int http_get_info_packs(const char *base_url,
struct packed_git **packs_head);
-struct http_pack_request
-{
+struct http_pack_request {
char *url;
struct packed_git *target;
struct packed_git **lst;
@@ -166,8 +162,7 @@ extern int finish_http_pack_request(struct http_pack_request *preq);
extern void release_http_pack_request(struct http_pack_request *preq);
/* Helpers for fetching object */
-struct http_object_request
-{
+struct http_object_request {
char *url;
char tmpfile[PATH_MAX];
int localfile;
diff --git a/list-objects.c b/list-objects.c
index 8953548c07..44fa5a92e2 100644
--- a/list-objects.c
+++ b/list-objects.c
@@ -148,7 +148,12 @@ void traverse_commit_list(struct rev_info *revs,
struct commit *commit;
while ((commit = get_revision(revs)) != NULL) {
- add_pending_tree(revs, commit->tree);
+ /*
+ * an uninteresting boundary commit may not have its tree
+ * parsed yet, but we are not going to show them anyway
+ */
+ if (commit->tree)
+ add_pending_tree(revs, commit->tree);
show_commit(commit, data);
}
for (i = 0; i < revs->pending.nr; i++) {
diff --git a/merge-recursive.c b/merge-recursive.c
index 16c2dbeab9..42d52cb5bc 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -83,10 +83,8 @@ struct rename_df_conflict_info {
* Since we want to write the index eventually, we cannot reuse the index
* for these (temporary) data.
*/
-struct stage_data
-{
- struct
- {
+struct stage_data {
+ struct {
unsigned mode;
unsigned char sha[20];
} stages[4];
@@ -403,8 +401,7 @@ static void make_room_for_directories_of_df_conflicts(struct merge_options *o,
}
}
-struct rename
-{
+struct rename {
struct diff_filepair *pair;
struct stage_data *src_entry;
struct stage_data *dst_entry;
@@ -717,8 +714,7 @@ static void update_file(struct merge_options *o,
/* Low level file merging, update and removal */
-struct merge_file_info
-{
+struct merge_file_info {
unsigned char sha[20];
unsigned mode;
unsigned clean:1,
diff --git a/notes-merge.c b/notes-merge.c
index 71c4d45fcd..1467ad3179 100644
--- a/notes-merge.c
+++ b/notes-merge.c
@@ -615,7 +615,7 @@ int notes_merge(struct notes_merge_options *o,
bases = get_merge_bases(local, remote, 1);
if (!bases) {
base_sha1 = null_sha1;
- base_tree_sha1 = (unsigned char *)EMPTY_TREE_SHA1_BIN;
+ base_tree_sha1 = EMPTY_TREE_SHA1_BIN;
OUTPUT(o, 4, "No merge base found; doing history-less merge");
} else if (!bases->next) {
base_sha1 = bases->item->object.sha1;
diff --git a/pack-check.c b/pack-check.c
index 9d0cb9a114..c3bf21dbcb 100644
--- a/pack-check.c
+++ b/pack-check.c
@@ -2,8 +2,7 @@
#include "pack.h"
#include "pack-revindex.h"
-struct idx_entry
-{
+struct idx_entry {
off_t offset;
const unsigned char *sha1;
unsigned int nr;
diff --git a/parse-options.h b/parse-options.h
index 31ec5d2476..d1b12fe979 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -141,7 +141,7 @@ struct option {
{ OPTION_NUMBER, 0, NULL, (v), NULL, (h), \
PARSE_OPT_NOARG | PARSE_OPT_NONEG, (f) }
#define OPT_FILENAME(s, l, v, h) { OPTION_FILENAME, (s), (l), (v), \
- "FILE", (h) }
+ "file", (h) }
#define OPT_COLOR_FLAG(s, l, v, h) \
{ OPTION_CALLBACK, (s), (l), (v), "when", (h), PARSE_OPT_OPTARG, \
parse_opt_color_flag_cb, (intptr_t)"always" }
diff --git a/patch-delta.c b/patch-delta.c
index d218faa02b..56e0a5ede2 100644
--- a/patch-delta.c
+++ b/patch-delta.c
@@ -48,7 +48,7 @@ void *patch_delta(const void *src_buf, unsigned long src_size,
if (cmd & 0x20) cp_size |= (*data++ << 8);
if (cmd & 0x40) cp_size |= (*data++ << 16);
if (cp_size == 0) cp_size = 0x10000;
- if (cp_off + cp_size < cp_size ||
+ if (unsigned_add_overflows(cp_off, cp_size) ||
cp_off + cp_size > src_size ||
cp_size > size)
break;
diff --git a/perl/Git.pm b/perl/Git.pm
index 205e48aa3a..a86ab709c2 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -99,7 +99,7 @@ increase notwithstanding).
use Carp qw(carp croak); # but croak is bad - throw instead
use Error qw(:try);
-use Cwd qw(abs_path);
+use Cwd qw(abs_path cwd);
use IPC::Open2 qw(open2);
use Fcntl qw(SEEK_SET SEEK_CUR);
}
@@ -396,7 +396,16 @@ See C<command_close_bidi_pipe()> for details.
sub command_bidi_pipe {
my ($pid, $in, $out);
+ my ($self) = _maybe_self(@_);
+ local %ENV = %ENV;
+ my $cwd_save = undef;
+ if ($self) {
+ shift;
+ $cwd_save = cwd();
+ _setup_git_cmd_env($self);
+ }
$pid = open2($in, $out, 'git', @_);
+ chdir($cwd_save) if $cwd_save;
return ($pid, $in, $out, join(' ', @_));
}
@@ -843,7 +852,7 @@ sub _open_hash_and_insert_object_if_needed {
($self->{hash_object_pid}, $self->{hash_object_in},
$self->{hash_object_out}, $self->{hash_object_ctx}) =
- command_bidi_pipe(qw(hash-object -w --stdin-paths --no-filters));
+ $self->command_bidi_pipe(qw(hash-object -w --stdin-paths --no-filters));
}
sub _close_hash_and_insert_object {
@@ -932,7 +941,7 @@ sub _open_cat_blob_if_needed {
($self->{cat_blob_pid}, $self->{cat_blob_in},
$self->{cat_blob_out}, $self->{cat_blob_ctx}) =
- command_bidi_pipe(qw(cat-file --batch));
+ $self->command_bidi_pipe(qw(cat-file --batch));
}
sub _close_cat_blob {
@@ -1279,6 +1288,14 @@ sub _command_common_pipe {
# for the given repository and execute the git command.
sub _cmd_exec {
my ($self, @args) = @_;
+ _setup_git_cmd_env($self);
+ _execv_git_cmd(@args);
+ die qq[exec "@args" failed: $!];
+}
+
+# set up the appropriate state for git command
+sub _setup_git_cmd_env {
+ my $self = shift;
if ($self) {
$self->repo_path() and $ENV{'GIT_DIR'} = $self->repo_path();
$self->repo_path() and $self->wc_path()
@@ -1286,8 +1303,6 @@ sub _cmd_exec {
$self->wc_path() and chdir($self->wc_path());
$self->wc_subdir() and chdir($self->wc_subdir());
}
- _execv_git_cmd(@args);
- die qq[exec "@args" failed: $!];
}
# Execute the given Git command ($_[0]) with arguments ($_[1..])
diff --git a/pretty.c b/pretty.c
index 8549934751..65d20a7a2e 100644
--- a/pretty.c
+++ b/pretty.c
@@ -216,36 +216,53 @@ static int is_rfc2047_special(char ch)
static void add_rfc2047(struct strbuf *sb, const char *line, int len,
const char *encoding)
{
- int i, last;
+ static const int max_length = 78; /* per rfc2822 */
+ int i;
+ int line_len;
+
+ /* How many bytes are already used on the current line? */
+ for (i = sb->len - 1; i >= 0; i--)
+ if (sb->buf[i] == '\n')
+ break;
+ line_len = sb->len - (i+1);
for (i = 0; i < len; i++) {
int ch = line[i];
- if (non_ascii(ch))
+ if (non_ascii(ch) || ch == '\n')
goto needquote;
if ((i + 1 < len) && (ch == '=' && line[i+1] == '?'))
goto needquote;
}
- strbuf_add(sb, line, len);
+ strbuf_add_wrapped_bytes(sb, line, len, 0, 1, max_length - line_len);
return;
needquote:
strbuf_grow(sb, len * 3 + strlen(encoding) + 100);
strbuf_addf(sb, "=?%s?q?", encoding);
- for (i = last = 0; i < len; i++) {
+ line_len += strlen(encoding) + 5; /* 5 for =??q? */
+ for (i = 0; i < len; i++) {
unsigned ch = line[i] & 0xFF;
+
+ if (line_len >= max_length - 2) {
+ strbuf_addf(sb, "?=\n =?%s?q?", encoding);
+ line_len = strlen(encoding) + 5 + 1; /* =??q? plus SP */
+ }
+
/*
* We encode ' ' using '=20' even though rfc2047
* allows using '_' for readability. Unfortunately,
* many programs do not understand this and just
* leave the underscore in place.
*/
- if (is_rfc2047_special(ch) || ch == ' ') {
- strbuf_add(sb, line + last, i - last);
+ if (is_rfc2047_special(ch) || ch == ' ' || ch == '\n') {
strbuf_addf(sb, "=%02X", ch);
- last = i + 1;
+ line_len += 3;
+ }
+ else {
+ strbuf_addch(sb, ch);
+ line_len++;
}
}
- strbuf_add(sb, line + last, len - last);
strbuf_addstr(sb, "?=");
}
@@ -1106,11 +1123,10 @@ void pp_title_line(enum cmit_fmt fmt,
const char *encoding,
int need_8bit_cte)
{
- const char *line_separator = (fmt == CMIT_FMT_EMAIL) ? "\n " : " ";
struct strbuf title;
strbuf_init(&title, 80);
- *msg_p = format_subject(&title, *msg_p, line_separator);
+ *msg_p = format_subject(&title, *msg_p, " ");
strbuf_grow(sb, title.len + 1024);
if (subject) {
diff --git a/quote.h b/quote.h
index 38003bff5f..024e21d80c 100644
--- a/quote.h
+++ b/quote.h
@@ -1,8 +1,7 @@
#ifndef QUOTE_H
#define QUOTE_H
-#include <stddef.h>
-#include <stdio.h>
+struct strbuf;
/* Help to copy the thing properly quoted for the shell safety.
* any single quote is replaced with '\'', any exclamation point
diff --git a/run-command.c b/run-command.c
index 2a1041ef65..f91e446c86 100644
--- a/run-command.c
+++ b/run-command.c
@@ -194,6 +194,7 @@ fail_pipe:
}
trace_argv_printf(cmd->argv, "trace: run_command:");
+ fflush(NULL);
#ifndef WIN32
{
@@ -201,7 +202,6 @@ fail_pipe:
if (pipe(notify_pipe))
notify_pipe[0] = notify_pipe[1] = -1;
- fflush(NULL);
cmd->pid = fork();
if (!cmd->pid) {
/*
diff --git a/sha1_file.c b/sha1_file.c
index d86a8db69a..e194f6a128 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -37,6 +37,41 @@ const unsigned char null_sha1[20];
static int git_open_noatime(const char *name, struct packed_git *p);
+/*
+ * This is meant to hold a *small* number of objects that you would
+ * want read_sha1_file() to be able to return, but yet you do not want
+ * to write them into the object store (e.g. a browse-only
+ * application).
+ */
+static struct cached_object {
+ unsigned char sha1[20];
+ enum object_type type;
+ void *buf;
+ unsigned long size;
+} *cached_objects;
+static int cached_object_nr, cached_object_alloc;
+
+static struct cached_object empty_tree = {
+ EMPTY_TREE_SHA1_BIN_LITERAL,
+ OBJ_TREE,
+ "",
+ 0
+};
+
+static struct cached_object *find_cached_object(const unsigned char *sha1)
+{
+ int i;
+ struct cached_object *co = cached_objects;
+
+ for (i = 0; i < cached_object_nr; i++, co++) {
+ if (!hashcmp(co->sha1, sha1))
+ return co;
+ }
+ if (!hashcmp(sha1, empty_tree.sha1))
+ return &empty_tree;
+ return NULL;
+}
+
int safe_create_leading_directories(char *path)
{
char *pos = path + offset_1st_component(path);
@@ -382,6 +417,8 @@ static unsigned int pack_used_ctr;
static unsigned int pack_mmap_calls;
static unsigned int peak_pack_open_windows;
static unsigned int pack_open_windows;
+static unsigned int pack_open_fds;
+static unsigned int pack_max_fds;
static size_t peak_pack_mapped;
static size_t pack_mapped;
struct packed_git *packed_git;
@@ -559,8 +596,10 @@ static int unuse_one_window(struct packed_git *current, int keep_fd)
lru_l->next = lru_w->next;
else {
lru_p->windows = lru_w->next;
- if (!lru_p->windows && lru_p->pack_fd != keep_fd) {
+ if (!lru_p->windows && lru_p->pack_fd != -1
+ && lru_p->pack_fd != keep_fd) {
close(lru_p->pack_fd);
+ pack_open_fds--;
lru_p->pack_fd = -1;
}
}
@@ -645,8 +684,10 @@ void free_pack_by_name(const char *pack_name)
if (strcmp(pack_name, p->pack_name) == 0) {
clear_delta_base_cache();
close_pack_windows(p);
- if (p->pack_fd != -1)
+ if (p->pack_fd != -1) {
close(p->pack_fd);
+ pack_open_fds--;
+ }
close_pack_index(p);
free(p->bad_object_sha1);
*pp = p->next;
@@ -672,9 +713,29 @@ static int open_packed_git_1(struct packed_git *p)
if (!p->index_data && open_pack_index(p))
return error("packfile %s index unavailable", p->pack_name);
+ if (!pack_max_fds) {
+ struct rlimit lim;
+ unsigned int max_fds;
+
+ if (getrlimit(RLIMIT_NOFILE, &lim))
+ die_errno("cannot get RLIMIT_NOFILE");
+
+ max_fds = lim.rlim_cur;
+
+ /* Save 3 for stdin/stdout/stderr, 22 for work */
+ if (25 < max_fds)
+ pack_max_fds = max_fds - 25;
+ else
+ pack_max_fds = 1;
+ }
+
+ while (pack_max_fds <= pack_open_fds && unuse_one_window(NULL, -1))
+ ; /* nothing */
+
p->pack_fd = git_open_noatime(p->pack_name, p);
if (p->pack_fd < 0 || fstat(p->pack_fd, &st))
return -1;
+ pack_open_fds++;
/* If we created the struct before we had the pack we lack size. */
if (!p->pack_size) {
@@ -726,6 +787,7 @@ static int open_packed_git(struct packed_git *p)
return 0;
if (p->pack_fd != -1) {
close(p->pack_fd);
+ pack_open_fds--;
p->pack_fd = -1;
}
return -1;
@@ -751,14 +813,13 @@ unsigned char *use_pack(struct packed_git *p,
{
struct pack_window *win = *w_cursor;
- if (p->pack_fd == -1 && open_packed_git(p))
- die("packfile %s cannot be accessed", p->pack_name);
-
/* Since packfiles end in a hash of their content and it's
* pointless to ask for an offset into the middle of that
* hash, and the in_window function above wouldn't match
* don't allow an offset too close to the end of the file.
*/
+ if (!p->pack_size && p->pack_fd == -1 && open_packed_git(p))
+ die("packfile %s cannot be accessed", p->pack_name);
if (offset > (p->pack_size - 20))
die("offset beyond end of packfile (truncated pack?)");
@@ -772,6 +833,10 @@ unsigned char *use_pack(struct packed_git *p,
if (!win) {
size_t window_align = packed_git_window_size / 2;
off_t len;
+
+ if (p->pack_fd == -1 && open_packed_git(p))
+ die("packfile %s cannot be accessed", p->pack_name);
+
win = xcalloc(1, sizeof(*win));
win->offset = (offset / window_align) * window_align;
len = p->pack_size - win->offset;
@@ -789,6 +854,12 @@ unsigned char *use_pack(struct packed_git *p,
die("packfile %s cannot be mapped: %s",
p->pack_name,
strerror(errno));
+ if (!win->offset && win->len == p->pack_size
+ && !p->do_not_close) {
+ close(p->pack_fd);
+ pack_open_fds--;
+ p->pack_fd = -1;
+ }
pack_mmap_calls++;
pack_open_windows++;
if (pack_mapped > peak_pack_mapped)
@@ -883,6 +954,9 @@ struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path)
void install_packed_git(struct packed_git *pack)
{
+ if (pack->pack_fd != -1)
+ pack_open_fds++;
+
pack->next = packed_git;
packed_git = pack;
}
@@ -900,8 +974,6 @@ static void prepare_packed_git_one(char *objdir, int local)
sprintf(path, "%s/pack", objdir);
len = strlen(path);
dir = opendir(path);
- while (!dir && errno == EMFILE && unuse_one_window(NULL, -1))
- dir = opendir(path);
if (!dir) {
if (errno != ENOENT)
error("unable to open object pack directory: %s: %s",
@@ -1057,14 +1129,6 @@ static int git_open_noatime(const char *name, struct packed_git *p)
if (fd >= 0)
return fd;
- /* Might the failure be insufficient file descriptors? */
- if (errno == EMFILE) {
- if (unuse_one_window(p, -1))
- continue;
- else
- return -1;
- }
-
/* Might the failure be due to O_NOATIME? */
if (errno != ENOENT && sha1_file_open_flag) {
sha1_file_open_flag = 0;
@@ -1896,6 +1960,27 @@ off_t find_pack_entry_one(const unsigned char *sha1,
return 0;
}
+static int is_pack_valid(struct packed_git *p)
+{
+ /* An already open pack is known to be valid. */
+ if (p->pack_fd != -1)
+ return 1;
+
+ /* If the pack has one window completely covering the
+ * file size, the pack is known to be valid even if
+ * the descriptor is not currently open.
+ */
+ if (p->windows) {
+ struct pack_window *w = p->windows;
+
+ if (!w->offset && w->len == p->pack_size)
+ return 1;
+ }
+
+ /* Force the pack to open to prove its valid. */
+ return !open_packed_git(p);
+}
+
static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
{
static struct packed_git *last_found = (void *)1;
@@ -1925,7 +2010,7 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
* it may have been deleted since the index
* was loaded!
*/
- if (p->pack_fd == -1 && open_packed_git(p)) {
+ if (!is_pack_valid(p)) {
error("packfile %s cannot be accessed", p->pack_name);
goto next;
}
@@ -1985,9 +2070,17 @@ static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *size
int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
{
+ struct cached_object *co;
struct pack_entry e;
int status;
+ co = find_cached_object(sha1);
+ if (co) {
+ if (sizep)
+ *sizep = co->size;
+ return co->type;
+ }
+
if (!find_pack_entry(sha1, &e)) {
/* Most likely it's a loose object. */
status = sha1_loose_object_info(sha1, sizep);
@@ -2033,41 +2126,6 @@ static void *read_packed_sha1(const unsigned char *sha1,
return data;
}
-/*
- * This is meant to hold a *small* number of objects that you would
- * want read_sha1_file() to be able to return, but yet you do not want
- * to write them into the object store (e.g. a browse-only
- * application).
- */
-static struct cached_object {
- unsigned char sha1[20];
- enum object_type type;
- void *buf;
- unsigned long size;
-} *cached_objects;
-static int cached_object_nr, cached_object_alloc;
-
-static struct cached_object empty_tree = {
- EMPTY_TREE_SHA1_BIN,
- OBJ_TREE,
- "",
- 0
-};
-
-static struct cached_object *find_cached_object(const unsigned char *sha1)
-{
- int i;
- struct cached_object *co = cached_objects;
-
- for (i = 0; i < cached_object_nr; i++, co++) {
- if (!hashcmp(co->sha1, sha1))
- return co;
- }
- if (!hashcmp(sha1, empty_tree.sha1))
- return &empty_tree;
- return NULL;
-}
-
int pretend_sha1_file(void *buf, unsigned long len, enum object_type type,
unsigned char *sha1)
{
@@ -2351,8 +2409,6 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
filename = sha1_file_name(sha1);
fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
- while (fd < 0 && errno == EMFILE && unuse_one_window(NULL, -1))
- fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
if (fd < 0) {
if (errno == EACCES)
return error("insufficient permission for adding an object to repository database %s\n", get_object_directory());
diff --git a/sha1_name.c b/sha1_name.c
index 709ff2eee6..faea58dc8c 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -208,9 +208,7 @@ const char *find_unique_abbrev(const unsigned char *sha1, int len)
if (exists
? !status
: status == SHORT_NAME_NOT_FOUND) {
- int cut_at = len + unique_abbrev_extra_length;
- cut_at = (cut_at < 40) ? cut_at : 40;
- hex[cut_at] = 0;
+ hex[len] = 0;
return hex;
}
len++;
diff --git a/strbuf.c b/strbuf.c
index 9b3c4457f2..07e8883ceb 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -63,7 +63,8 @@ void strbuf_attach(struct strbuf *sb, void *buf, size_t len, size_t alloc)
void strbuf_grow(struct strbuf *sb, size_t extra)
{
- if (sb->len + extra + 1 <= sb->len)
+ if (unsigned_add_overflows(extra, 1) ||
+ unsigned_add_overflows(sb->len, extra + 1))
die("you want to use way too much memory");
if (!sb->alloc)
sb->buf = NULL;
@@ -152,7 +153,7 @@ int strbuf_cmp(const struct strbuf *a, const struct strbuf *b)
void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
const void *data, size_t dlen)
{
- if (pos + len < pos)
+ if (unsigned_add_overflows(pos, len))
die("you want to use way too much memory");
if (pos > sb->len)
die("`pos' is too far after the end of the buffer");
diff --git a/strbuf.h b/strbuf.h
index 675a91f938..4ce7dedee0 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -1,42 +1,7 @@
#ifndef STRBUF_H
#define STRBUF_H
-/*
- * Strbuf's can be use in many ways: as a byte array, or to store arbitrary
- * long, overflow safe strings.
- *
- * Strbufs has some invariants that are very important to keep in mind:
- *
- * 1. the ->buf member is always malloc-ed, hence strbuf's can be used to
- * build complex strings/buffers whose final size isn't easily known.
- *
- * It is NOT legal to copy the ->buf pointer away.
- * `strbuf_detach' is the operation that detaches a buffer from its shell
- * while keeping the shell valid wrt its invariants.
- *
- * 2. the ->buf member is a byte array that has at least ->len + 1 bytes
- * allocated. The extra byte is used to store a '\0', allowing the ->buf
- * member to be a valid C-string. Every strbuf function ensures this
- * invariant is preserved.
- *
- * Note that it is OK to "play" with the buffer directly if you work it
- * that way:
- *
- * strbuf_grow(sb, SOME_SIZE);
- * ... Here, the memory array starting at sb->buf, and of length
- * ... strbuf_avail(sb) is all yours, and you are sure that
- * ... strbuf_avail(sb) is at least SOME_SIZE.
- * strbuf_setlen(sb, sb->len + SOME_OTHER_SIZE);
- *
- * Of course, SOME_OTHER_SIZE must be smaller or equal to strbuf_avail(sb).
- *
- * Doing so is safe, though if it has to be done in many places, adding the
- * missing API to the strbuf module is the way to go.
- *
- * XXX: do _not_ assume that the area that is yours is of size ->alloc - 1
- * even if it's true in the current implementation. Alloc is somehow a
- * "private" member that should not be messed with.
- */
+/* See Documentation/technical/api-strbuf.txt */
#include <assert.h>
diff --git a/string-list.c b/string-list.c
index 9b023a2584..51681189e8 100644
--- a/string-list.c
+++ b/string-list.c
@@ -153,6 +153,7 @@ struct string_list_item *string_list_append(struct string_list *list, const char
ALLOC_GROW(list->items, list->nr + 1, list->alloc);
list->items[list->nr].string =
list->strdup_strings ? xstrdup(string) : (char *)string;
+ list->items[list->nr].util = NULL;
return list->items + list->nr++;
}
diff --git a/string-list.h b/string-list.h
index 494693898b..bda6983983 100644
--- a/string-list.h
+++ b/string-list.h
@@ -5,8 +5,7 @@ struct string_list_item {
char *string;
void *util;
};
-struct string_list
-{
+struct string_list {
struct string_list_item *items;
unsigned int nr, alloc;
unsigned int strdup_strings:1;
diff --git a/submodule.c b/submodule.c
index 6f1c10722f..e9f2b19e1c 100644
--- a/submodule.c
+++ b/submodule.c
@@ -152,17 +152,69 @@ void handle_ignore_submodules_arg(struct diff_options *diffopt,
die("bad --ignore-submodules argument: %s", arg);
}
+static int prepare_submodule_summary(struct rev_info *rev, const char *path,
+ struct commit *left, struct commit *right,
+ int *fast_forward, int *fast_backward)
+{
+ struct commit_list *merge_bases, *list;
+
+ init_revisions(rev, NULL);
+ setup_revisions(0, NULL, rev, NULL);
+ rev->left_right = 1;
+ rev->first_parent_only = 1;
+ left->object.flags |= SYMMETRIC_LEFT;
+ add_pending_object(rev, &left->object, path);
+ add_pending_object(rev, &right->object, path);
+ merge_bases = get_merge_bases(left, right, 1);
+ if (merge_bases) {
+ if (merge_bases->item == left)
+ *fast_forward = 1;
+ else if (merge_bases->item == right)
+ *fast_backward = 1;
+ }
+ for (list = merge_bases; list; list = list->next) {
+ list->item->object.flags |= UNINTERESTING;
+ add_pending_object(rev, &list->item->object,
+ sha1_to_hex(list->item->object.sha1));
+ }
+ return prepare_revision_walk(rev);
+}
+
+static void print_submodule_summary(struct rev_info *rev, FILE *f,
+ const char *del, const char *add, const char *reset)
+{
+ static const char format[] = " %m %s";
+ struct strbuf sb = STRBUF_INIT;
+ struct commit *commit;
+
+ while ((commit = get_revision(rev))) {
+ struct pretty_print_context ctx = {0};
+ ctx.date_mode = rev->date_mode;
+ strbuf_setlen(&sb, 0);
+ if (commit->object.flags & SYMMETRIC_LEFT) {
+ if (del)
+ strbuf_addstr(&sb, del);
+ }
+ else if (add)
+ strbuf_addstr(&sb, add);
+ format_commit_message(commit, format, &sb, &ctx);
+ if (reset)
+ strbuf_addstr(&sb, reset);
+ strbuf_addch(&sb, '\n');
+ fprintf(f, "%s", sb.buf);
+ }
+ strbuf_release(&sb);
+}
+
void show_submodule_summary(FILE *f, const char *path,
unsigned char one[20], unsigned char two[20],
unsigned dirty_submodule,
const char *del, const char *add, const char *reset)
{
struct rev_info rev;
- struct commit *commit, *left = left, *right = right;
- struct commit_list *merge_bases, *list;
+ struct commit *left = left, *right = right;
const char *message = NULL;
struct strbuf sb = STRBUF_INIT;
- static const char *format = " %m %s";
int fast_forward = 0, fast_backward = 0;
if (is_null_sha1(two))
@@ -175,29 +227,10 @@ void show_submodule_summary(FILE *f, const char *path,
!(right = lookup_commit_reference(two)))
message = "(commits not present)";
- if (!message) {
- init_revisions(&rev, NULL);
- setup_revisions(0, NULL, &rev, NULL);
- rev.left_right = 1;
- rev.first_parent_only = 1;
- left->object.flags |= SYMMETRIC_LEFT;
- add_pending_object(&rev, &left->object, path);
- add_pending_object(&rev, &right->object, path);
- merge_bases = get_merge_bases(left, right, 1);
- if (merge_bases) {
- if (merge_bases->item == left)
- fast_forward = 1;
- else if (merge_bases->item == right)
- fast_backward = 1;
- }
- for (list = merge_bases; list; list = list->next) {
- list->item->object.flags |= UNINTERESTING;
- add_pending_object(&rev, &list->item->object,
- sha1_to_hex(list->item->object.sha1));
- }
- if (prepare_revision_walk(&rev))
- message = "(revision walker failed)";
- }
+ if (!message &&
+ prepare_submodule_summary(&rev, path, left, right,
+ &fast_forward, &fast_backward))
+ message = "(revision walker failed)";
if (dirty_submodule & DIRTY_SUBMODULE_UNTRACKED)
fprintf(f, "Submodule %s contains untracked content\n", path);
@@ -221,25 +254,11 @@ void show_submodule_summary(FILE *f, const char *path,
fwrite(sb.buf, sb.len, 1, f);
if (!message) {
- while ((commit = get_revision(&rev))) {
- struct pretty_print_context ctx = {0};
- ctx.date_mode = rev.date_mode;
- strbuf_setlen(&sb, 0);
- if (commit->object.flags & SYMMETRIC_LEFT) {
- if (del)
- strbuf_addstr(&sb, del);
- }
- else if (add)
- strbuf_addstr(&sb, add);
- format_commit_message(commit, format, &sb, &ctx);
- if (reset)
- strbuf_addstr(&sb, reset);
- strbuf_addch(&sb, '\n');
- fprintf(f, "%s", sb.buf);
- }
+ print_submodule_summary(&rev, f, del, add, reset);
clear_commit_marks(left, ~0);
clear_commit_marks(right, ~0);
}
+
strbuf_release(&sb);
}
diff --git a/symlinks.c b/symlinks.c
index 3cacebd91a..034943bda0 100644
--- a/symlinks.c
+++ b/symlinks.c
@@ -223,7 +223,7 @@ int check_leading_path(const char *name, int len)
int flags;
int match_len = lstat_cache_matchlen(cache, name, len, &flags,
FL_SYMLINK|FL_NOENT|FL_DIR, USE_ONLY_LSTAT);
- if (flags & (FL_SYMLINK|FL_NOENT))
+ if (flags & FL_NOENT)
return 0;
else if (flags & FL_DIR)
return -1;
diff --git a/t/README b/t/README
index 25f7d2d2e3..6122a6c733 100644
--- a/t/README
+++ b/t/README
@@ -98,6 +98,13 @@ appropriately before running "make".
not see any output, this option implies --verbose. For
convenience, it also implies --tee.
+ Note that valgrind is run with the option --leak-check=no,
+ as the git process is short-lived and some errors are not
+ interesting. In order to run a single command under the same
+ conditions manually, you should set GIT_VALGRIND to point to
+ the 't/valgrind/' directory and use the commands under
+ 't/valgrind/bin/'.
+
--tee::
In addition to printing the test output to the terminal,
write it to files named 't/test-results/$TEST_NAME.out'.
@@ -190,7 +197,7 @@ we are testing.
If you create files under t/ directory (i.e. here) that is not
the top-level test script, never name the file to match the above
pattern. The Makefile here considers all such files as the
-top-level test script and tries to run all of them. A care is
+top-level test script and tries to run all of them. Care is
especially needed if you are creating a common test library
file, similar to test-lib.sh, because such a library file may
not be suitable for standalone execution.
@@ -274,9 +281,8 @@ Do:
- Check the test coverage for your tests. See the "Test coverage"
below.
- Don't blindly follow test coverage metrics, they're a good way to
- spot if you've missed something. If a new function you added
- doesn't have any coverage you're probably doing something wrong,
+ Don't blindly follow test coverage metrics; if a new function you added
+ doesn't have any coverage, then you're probably doing something wrong,
but having 100% coverage doesn't necessarily mean that you tested
everything.
@@ -328,7 +334,7 @@ Keep in mind:
Skipping tests
--------------
-If you need to skip tests you should do so be using the three-arg form
+If you need to skip tests you should do so by using the three-arg form
of the test_* functions (see the "Test harness library" section
below), e.g.:
@@ -420,7 +426,7 @@ library for your script to use.
- test_tick
Make commit and tag names consistent by setting the author and
- committer times to defined stated. Subsequent calls will
+ committer times to defined state. Subsequent calls will
advance the times by a fixed amount.
- test_commit <message> [<filename> [<contents>]]
diff --git a/t/gitweb-lib.sh b/t/gitweb-lib.sh
index b9bb95feaa..143eb1f240 100644
--- a/t/gitweb-lib.sh
+++ b/t/gitweb-lib.sh
@@ -82,7 +82,12 @@ gitweb_run () {
}
close O;
' gitweb.output &&
- if grep '^[[]' gitweb.log >/dev/null 2>&1; then false; else true; fi
+ if grep '^[[]' gitweb.log >/dev/null 2>&1; then
+ test_debug 'cat gitweb.log >&2' &&
+ false
+ else
+ true
+ fi
# gitweb.log is left for debugging
# gitweb.output is used to parse HTTP output
diff --git a/t/lib-terminal.sh b/t/lib-terminal.sh
index c383b57ed9..58d911d21b 100644
--- a/t/lib-terminal.sh
+++ b/t/lib-terminal.sh
@@ -1,8 +1,24 @@
#!/bin/sh
-test_expect_success 'set up terminal for tests' '
- if
- test_have_prereq PERL &&
+test_expect_success PERL 'set up terminal for tests' '
+ # 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.
+ #
+ # Reproduction recipe: run
+ #
+ # i=0
+ # while ./test-terminal.perl echo hi $i
+ # do
+ # : $((i = $i + 1))
+ # done
+ #
+ # After 2000 iterations or so it hangs.
+ # https://rt.cpan.org/Ticket/Display.html?id=65692
+ #
+ if test "$(uname -s)" = Darwin
+ then
+ :
+ elif
"$PERL_PATH" "$TEST_DIRECTORY"/test-terminal.perl \
sh -c "test -t 1 && test -t 2"
then
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index 20924506af..ae266147b6 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -19,7 +19,7 @@ usage: test-parse-options <options>
--set23 set integer to 23
-t <time> get timestamp of <time>
-L, --length <str> get length of <str>
- -F, --file <FILE> set file to <FILE>
+ -F, --file <file> set file to <file>
String options
-s, --string <string>
diff --git a/t/t0070-fundamental.sh b/t/t0070-fundamental.sh
index 680d7d6861..9bee8bfd2e 100755
--- a/t/t0070-fundamental.sh
+++ b/t/t0070-fundamental.sh
@@ -12,4 +12,17 @@ test_expect_success 'character classes (isspace, isalpha etc.)' '
test-ctype
'
+test_expect_success 'mktemp to nonexistent directory prints filename' '
+ test_must_fail test-mktemp doesnotexist/testXXXXXX 2>err &&
+ grep "doesnotexist/test" err
+'
+
+test_expect_success POSIXPERM 'mktemp to unwritable directory prints filename' '
+ mkdir cannotwrite &&
+ chmod -w cannotwrite &&
+ test_when_finished "chmod +w cannotwrite" &&
+ test_must_fail test-mktemp cannotwrite/testXXXXXX 2>err &&
+ grep "cannotwrite/test" err
+'
+
test_done
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index d0e55465ff..53fb8228cf 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -876,11 +876,25 @@ test_expect_success 'check split_cmdline return' "
"
test_expect_success 'git -c "key=value" support' '
- test "z$(git -c name=value config name)" = zvalue &&
test "z$(git -c core.name=value config core.name)" = zvalue &&
- test "z$(git -c CamelCase=value config camelcase)" = zvalue &&
- test "z$(git -c flag config --bool flag)" = ztrue &&
- test_must_fail git -c core.name=value config name
+ test "z$(git -c foo.CamelCase=value config foo.camelcase)" = zvalue &&
+ test "z$(git -c foo.flag config --bool foo.flag)" = ztrue &&
+ test_must_fail git -c name=value config core.name
+'
+
+test_expect_success 'key sanity-checking' '
+ test_must_fail git config foo=bar &&
+ test_must_fail git config foo=.bar &&
+ test_must_fail git config foo.ba=r &&
+ test_must_fail git config foo.1bar &&
+ test_must_fail git config foo."ba
+ z".bar &&
+ test_must_fail git config . false &&
+ test_must_fail git config .foo false &&
+ test_must_fail git config foo. false &&
+ test_must_fail git config .foo. false &&
+ git config foo.bar true &&
+ git config foo."ba =z".bar false
'
test_done
diff --git a/t/t2019-checkout-ambiguous-ref.sh b/t/t2019-checkout-ambiguous-ref.sh
new file mode 100755
index 0000000000..943541d40d
--- /dev/null
+++ b/t/t2019-checkout-ambiguous-ref.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+
+test_description='checkout handling of ambiguous (branch/tag) refs'
+. ./test-lib.sh
+
+test_expect_success 'setup ambiguous refs' '
+ test_commit branch file &&
+ git branch ambiguity &&
+ git branch vagueness &&
+ test_commit tag file &&
+ git tag ambiguity &&
+ git tag vagueness HEAD:file &&
+ test_commit other file
+'
+
+test_expect_success 'checkout ambiguous ref succeeds' '
+ git checkout ambiguity >stdout 2>stderr
+'
+
+test_expect_success 'checkout produces ambiguity warning' '
+ grep "warning.*ambiguous" stderr
+'
+
+test_expect_success 'checkout chooses branch over tag' '
+ echo refs/heads/ambiguity >expect &&
+ git symbolic-ref HEAD >actual &&
+ test_cmp expect actual &&
+ echo branch >expect &&
+ test_cmp expect file
+'
+
+test_expect_success 'checkout reports switch to branch' '
+ grep "Switched to branch" stderr &&
+ ! grep "^HEAD is now at" stderr
+'
+
+test_expect_success 'checkout vague ref succeeds' '
+ git checkout vagueness >stdout 2>stderr &&
+ test_set_prereq VAGUENESS_SUCCESS
+'
+
+test_expect_success VAGUENESS_SUCCESS 'checkout produces ambiguity warning' '
+ grep "warning.*ambiguous" stderr
+'
+
+test_expect_success VAGUENESS_SUCCESS 'checkout chooses branch over tag' '
+ echo refs/heads/vagueness >expect &&
+ git symbolic-ref HEAD >actual &&
+ test_cmp expect actual &&
+ echo branch >expect &&
+ test_cmp expect file
+'
+
+test_expect_success VAGUENESS_SUCCESS 'checkout reports switch to branch' '
+ grep "Switched to branch" stderr &&
+ ! grep "^HEAD is now at" stderr
+'
+
+test_done
diff --git a/t/t2021-checkout-overwrite.sh b/t/t2021-checkout-overwrite.sh
new file mode 100755
index 0000000000..27db2ad529
--- /dev/null
+++ b/t/t2021-checkout-overwrite.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+test_description='checkout must not overwrite an untracked objects'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+
+ mkdir -p a/b/c &&
+ >a/b/c/d &&
+ git add -A &&
+ git commit -m base &&
+ git tag start
+'
+
+test_expect_success 'create a commit where dir a/b changed to file' '
+
+ git checkout -b file &&
+ rm -rf a/b &&
+ >a/b &&
+ git add -A &&
+ git commit -m "dir to file"
+'
+
+test_expect_success 'checkout commit with dir must not remove untracked a/b' '
+
+ git rm --cached a/b &&
+ git commit -m "un-track the file" &&
+ test_must_fail git checkout start &&
+ test -f a/b
+'
+
+test_expect_success SYMLINKS 'create a commit where dir a/b changed to symlink' '
+
+ rm -rf a/b && # cleanup if previous test failed
+ git checkout -f -b symlink start &&
+ rm -rf a/b &&
+ ln -s foo a/b &&
+ git add -A &&
+ git commit -m "dir to symlink"
+'
+
+test_expect_failure SYMLINKS 'checkout commit with dir must not remove untracked a/b' '
+
+ git rm --cached a/b &&
+ git commit -m "un-track the symlink" &&
+ test_must_fail git checkout start &&
+ test -h a/b
+'
+
+test_done
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index f308235f5d..78ce09f9d7 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -223,6 +223,11 @@ test_expect_success \
'branch from non-branch HEAD w/--track causes failure' \
'test_must_fail git branch --track my10 HEAD^'
+test_expect_success \
+ 'branch from tag w/--track causes failure' \
+ 'git tag foobar &&
+ test_must_fail git branch --track my11 foobar'
+
# Keep this test last, as it changes the current branch
cat >expect <<EOF
0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 branch: Created from master
@@ -488,6 +493,15 @@ test_expect_success 'autosetuprebase always on an untracked remote branch' '
test "z$(git config branch.myr20.rebase)" = z
'
+test_expect_success 'autosetuprebase always on detached HEAD' '
+ git config branch.autosetupmerge always &&
+ test_when_finished git checkout master &&
+ git checkout HEAD^0 &&
+ git branch my11 &&
+ test -z "$(git config branch.my11.remote)" &&
+ test -z "$(git config branch.my11.merge)"
+'
+
test_expect_success 'detect misconfigured autosetuprebase (bad value)' '
git config branch.autosetuprebase garbage &&
test_must_fail git branch
diff --git a/t/t3509-cherry-pick-merge-df.sh b/t/t3509-cherry-pick-merge-df.sh
index 948ca1bce6..df921d1f33 100755
--- a/t/t3509-cherry-pick-merge-df.sh
+++ b/t/t3509-cherry-pick-merge-df.sh
@@ -3,12 +3,14 @@
test_description='Test cherry-pick with directory/file conflicts'
. ./test-lib.sh
-test_expect_success SYMLINKS 'Setup rename across paths each below D/F conflicts' '
+test_expect_success 'Initialize repository' '
mkdir a &&
>a/f &&
git add a &&
- git commit -m a &&
+ git commit -m a
+'
+test_expect_success SYMLINKS 'Setup rename across paths each below D/F conflicts' '
mkdir b &&
ln -s ../a b/a &&
git add b &&
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 6fd560ccf1..f62aaf5816 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -556,4 +556,23 @@ test_expect_success 'stash branch should not drop the stash if the branch exists
git rev-parse stash@{0} --
'
+test_expect_success 'stash apply shows status same as git status (relative to current directory)' '
+ git stash clear &&
+ echo 1 >subdir/subfile1 &&
+ echo 2 >subdir/subfile2 &&
+ git add subdir/subfile1 &&
+ git commit -m subdir &&
+ (
+ cd subdir &&
+ echo x >subfile1 &&
+ echo x >../file &&
+ git status >../expect &&
+ git stash &&
+ sane_unset GIT_MERGE_VERBOSITY &&
+ git stash apply
+ ) |
+ sed -e 1,2d >actual && # drop "Saved..." and "HEAD is now..."
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t4003-diff-rename-1.sh b/t/t4003-diff-rename-1.sh
index c6130c4019..bfa8835638 100755
--- a/t/t4003-diff-rename-1.sh
+++ b/t/t4003-diff-rename-1.sh
@@ -29,7 +29,7 @@ test_expect_success \
# copy-and-edit one, and rename-and-edit the other. We do not say
# anything about rezrov.
-GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current
+GIT_DIFF_OPTS=--unified=0 git diff-index -C -p $tree >current
cat >expected <<\EOF
diff --git a/COPYING b/COPYING.1
copy from COPYING
diff --git a/t/t4004-diff-rename-symlink.sh b/t/t4004-diff-rename-symlink.sh
index 92a65f4852..6e562c80d1 100755
--- a/t/t4004-diff-rename-symlink.sh
+++ b/t/t4004-diff-rename-symlink.sh
@@ -35,7 +35,7 @@ test_expect_success SYMLINKS \
# a new creation.
test_expect_success SYMLINKS 'setup diff output' "
- GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current &&
+ GIT_DIFF_OPTS=--unified=0 git diff-index -C -p $tree >current &&
cat >expected <<\EOF
diff --git a/bozbar b/bozbar
new file mode 120000
diff --git a/t/t4005-diff-rename-2.sh b/t/t4005-diff-rename-2.sh
index 1ba359d478..77d7f4946f 100755
--- a/t/t4005-diff-rename-2.sh
+++ b/t/t4005-diff-rename-2.sh
@@ -29,7 +29,7 @@ test_expect_success \
# and COPYING.2 are based on COPYING, and do not say anything about
# rezrov.
-git diff-index -M $tree >current
+git diff-index -C $tree >current
cat >expected <<\EOF
:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 COPYING COPYING.1
diff --git a/t/t4008-diff-break-rewrite.sh b/t/t4008-diff-break-rewrite.sh
index d79d9e1e71..73b4a24f5e 100755
--- a/t/t4008-diff-break-rewrite.sh
+++ b/t/t4008-diff-break-rewrite.sh
@@ -173,8 +173,8 @@ test_expect_success \
'compare_diff_raw expected current'
test_expect_success \
- 'run diff with -B -M' \
- 'git diff-index -B -M "$tree" >current'
+ 'run diff with -B -C' \
+ 'git diff-index -B -C "$tree" >current'
cat >expected <<\EOF
:100644 100644 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 08bb2fb671deff4c03a4d4a0a1315dff98d5732c C095 file0 file1
diff --git a/t/t4009-diff-rename-4.sh b/t/t4009-diff-rename-4.sh
index de3f17478e..f22c8e3dba 100755
--- a/t/t4009-diff-rename-4.sh
+++ b/t/t4009-diff-rename-4.sh
@@ -29,7 +29,7 @@ test_expect_success \
# and COPYING.2 are based on COPYING, and do not say anything about
# rezrov.
-git diff-index -z -M $tree >current
+git diff-index -z -C $tree >current
cat >expected <<\EOF
:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 9a66520588..5daa0f2a0c 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -210,6 +210,9 @@ log -m -p master
log -SF master
log -S F master
log -SF -p master
+log -SF master --max-count=0
+log -SF master --max-count=1
+log -SF master --max-count=2
log -GF master
log -GF -p master
log -GF -p --pickaxe-all master
@@ -290,4 +293,15 @@ test_expect_success 'log -S requires an argument' '
test_must_fail git log -S
'
+test_expect_success 'diff --cached on unborn branch' '
+ echo ref: refs/heads/unborn >.git/HEAD &&
+ git diff --cached >result &&
+ test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--cached" result
+'
+
+test_expect_success 'diff --cached -- file on unborn branch' '
+ git diff --cached -- file0 >result &&
+ test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--cached_--_file0" result
+'
+
test_done
diff --git a/t/t4013/diff.diff_--cached b/t/t4013/diff.diff_--cached
new file mode 100644
index 0000000000..ff16e83e7c
--- /dev/null
+++ b/t/t4013/diff.diff_--cached
@@ -0,0 +1,38 @@
+diff --git a/dir/sub b/dir/sub
+new file mode 100644
+index 0000000..992913c
+--- /dev/null
++++ b/dir/sub
+@@ -0,0 +1,8 @@
++A
++B
++C
++D
++E
++F
++1
++2
+diff --git a/file0 b/file0
+new file mode 100644
+index 0000000..10a8a9f
+--- /dev/null
++++ b/file0
+@@ -0,0 +1,9 @@
++1
++2
++3
++4
++5
++6
++A
++B
++C
+diff --git a/file1 b/file1
+new file mode 100644
+index 0000000..b1e6722
+--- /dev/null
++++ b/file1
+@@ -0,0 +1,3 @@
++A
++B
++C
diff --git a/t/t4013/diff.diff_--cached_--_file0 b/t/t4013/diff.diff_--cached_--_file0
new file mode 100644
index 0000000000..b9bb858a03
--- /dev/null
+++ b/t/t4013/diff.diff_--cached_--_file0
@@ -0,0 +1,15 @@
+diff --git a/file0 b/file0
+new file mode 100644
+index 0000000..10a8a9f
+--- /dev/null
++++ b/file0
+@@ -0,0 +1,9 @@
++1
++2
++3
++4
++5
++6
++A
++B
++C
diff --git a/t/t4013/diff.log_-SF_master_--max-count=0 b/t/t4013/diff.log_-SF_master_--max-count=0
new file mode 100644
index 0000000000..c1fc6c8731
--- /dev/null
+++ b/t/t4013/diff.log_-SF_master_--max-count=0
@@ -0,0 +1,2 @@
+$ git log -SF master --max-count=0
+$
diff --git a/t/t4013/diff.log_-SF_master_--max-count=1 b/t/t4013/diff.log_-SF_master_--max-count=1
new file mode 100644
index 0000000000..c981a03814
--- /dev/null
+++ b/t/t4013/diff.log_-SF_master_--max-count=1
@@ -0,0 +1,7 @@
+$ git log -SF master --max-count=1
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+Author: A U Thor <author@example.com>
+Date: Mon Jun 26 00:02:00 2006 +0000
+
+ Third
+$
diff --git a/t/t4013/diff.log_-SF_master_--max-count=2 b/t/t4013/diff.log_-SF_master_--max-count=2
new file mode 100644
index 0000000000..a6c55fd482
--- /dev/null
+++ b/t/t4013/diff.log_-SF_master_--max-count=2
@@ -0,0 +1,7 @@
+$ git log -SF master --max-count=2
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+Author: A U Thor <author@example.com>
+Date: Mon Jun 26 00:02:00 2006 +0000
+
+ Third
+$
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 027c13d52c..9c663677df 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -709,4 +709,88 @@ test_expect_success TTY 'format-patch --stdout paginates' '
test_path_is_missing .git/pager_used
'
+test_expect_success 'format-patch handles multi-line subjects' '
+ rm -rf patches/ &&
+ echo content >>file &&
+ for i in one two three; do echo $i; done >msg &&
+ git add file &&
+ git commit -F msg &&
+ git format-patch -o patches -1 &&
+ grep ^Subject: patches/0001-one.patch >actual &&
+ echo "Subject: [PATCH] one two three" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'format-patch handles multi-line encoded subjects' '
+ rm -rf patches/ &&
+ echo content >>file &&
+ for i in en två tre; do echo $i; done >msg &&
+ git add file &&
+ git commit -F msg &&
+ git format-patch -o patches -1 &&
+ grep ^Subject: patches/0001-en.patch >actual &&
+ echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
+ test_cmp expect actual
+'
+
+M8="foo bar "
+M64=$M8$M8$M8$M8$M8$M8$M8$M8
+M512=$M64$M64$M64$M64$M64$M64$M64$M64
+cat >expect <<'EOF'
+Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
+ bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
+ foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
+ bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
+ foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
+ bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
+ foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
+ bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
+ foo bar foo bar foo bar foo bar
+EOF
+test_expect_success 'format-patch wraps extremely long headers (ascii)' '
+ echo content >>file &&
+ git add file &&
+ git commit -m "$M512" &&
+ git format-patch --stdout -1 >patch &&
+ sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
+ test_cmp expect subject
+'
+
+M8="föö bar "
+M64=$M8$M8$M8$M8$M8$M8$M8$M8
+M512=$M64$M64$M64$M64$M64$M64$M64$M64
+cat >expect <<'EOF'
+Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
+EOF
+test_expect_success 'format-patch wraps extremely long headers (rfc2047)' '
+ rm -rf patches/ &&
+ echo content >>file &&
+ git add file &&
+ git commit -m "$M512" &&
+ git format-patch --stdout -1 >patch &&
+ sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
+ test_cmp expect subject
+'
+
test_done
diff --git a/t/t4031-diff-rewrite-binary.sh b/t/t4031-diff-rewrite-binary.sh
index 7e7b307a24..7d7470f21b 100755
--- a/t/t4031-diff-rewrite-binary.sh
+++ b/t/t4031-diff-rewrite-binary.sh
@@ -44,6 +44,13 @@ test_expect_success 'rewrite diff can show binary patch' '
grep "GIT binary patch" diff
'
+test_expect_success 'rewrite diff --stat shows binary changes' '
+ git diff -B --stat --summary >diff &&
+ grep "Bin" diff &&
+ grep "0 insertions.*0 deletions" diff &&
+ grep " rewrite file" diff
+'
+
{
echo "#!$SHELL_PATH"
cat <<'EOF'
diff --git a/t/t4040-whitespace-status.sh b/t/t4040-whitespace-status.sh
index a30b03bcf2..abc49348b1 100755
--- a/t/t4040-whitespace-status.sh
+++ b/t/t4040-whitespace-status.sh
@@ -60,4 +60,11 @@ test_expect_success 'diff-files -b -p --exit-code' '
git diff-files -b -p --exit-code
'
+test_expect_success 'diff-files --diff-filter --quiet' '
+ git reset --hard &&
+ rm a/d &&
+ echo x >>b/e &&
+ test_must_fail git diff-files --diff-filter=M --quiet
+'
+
test_done
diff --git a/t/t4120-apply-popt.sh b/t/t4120-apply-popt.sh
index 579c9e6105..a33d510bf6 100755
--- a/t/t4120-apply-popt.sh
+++ b/t/t4120-apply-popt.sh
@@ -6,6 +6,7 @@
test_description='git apply -p handling.'
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh
test_expect_success setup '
mkdir sub &&
@@ -62,8 +63,12 @@ test_expect_success 'apply (-p2) diff, mode change only' '
old mode 100644
new mode 100755
EOF
- chmod 644 file1 &&
- git apply -p2 patch.chmod &&
+ test_chmod -x file1 &&
+ git apply --index -p2 patch.chmod &&
+ case $(git ls-files -s file1) in 100755*) : good;; *) false;; esac
+'
+
+test_expect_success FILEMODE 'file mode was changed' '
test -x file1
'
diff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh
index 68e2652814..d2c930de87 100755
--- a/t/t4204-patch-id.sh
+++ b/t/t4204-patch-id.sh
@@ -63,4 +63,40 @@ test_expect_success 'patch-id supports git-format-patch MIME output' '
test_cmp patch-id_master patch-id_same
'
+cat >nonl <<\EOF
+diff --git i/a w/a
+index e69de29..2e65efe 100644
+--- i/a
++++ w/a
+@@ -0,0 +1 @@
++a
+\ No newline at end of file
+diff --git i/b w/b
+index e69de29..6178079 100644
+--- i/b
++++ w/b
+@@ -0,0 +1 @@
++b
+EOF
+
+cat >withnl <<\EOF
+diff --git i/a w/a
+index e69de29..7898192 100644
+--- i/a
++++ w/a
+@@ -0,0 +1 @@
++a
+diff --git i/b w/b
+index e69de29..6178079 100644
+--- i/b
++++ w/b
+@@ -0,0 +1 @@
++b
+EOF
+
+test_expect_success 'patch-id handles no-nl-at-eof markers' '
+ cat nonl | calc_patch_id nonl &&
+ cat withnl | calc_patch_id withnl &&
+ test_cmp patch-id_nonl patch-id_withnl
+'
test_done
diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh
index 884a5e567c..a5f458533f 100755
--- a/t/t5526-fetch-submodules.sh
+++ b/t/t5526-fetch-submodules.sh
@@ -124,7 +124,7 @@ test_expect_success "--recurse-submodules overrides fetchRecurseSubmodules setti
(
cd downstream &&
git fetch --recurse-submodules >../actual.out 2>../actual.err &&
- git config -f --unset .gitmodules submodule.submodule.fetchRecurseSubmodules true &&
+ git config --unset -f .gitmodules submodule.submodule.fetchRecurseSubmodules &&
git config --unset submodule.submodule.fetchRecurseSubmodules
) &&
test_cmp expect.out actual.out &&
diff --git a/t/t5701-clone-local.sh b/t/t5701-clone-local.sh
index 0f4d487be3..6972258b27 100755
--- a/t/t5701-clone-local.sh
+++ b/t/t5701-clone-local.sh
@@ -144,4 +144,17 @@ test_expect_success 'clone empty repository, and then push should not segfault.'
test_must_fail git push)
'
+test_expect_success 'cloning non-existent directory fails' '
+ cd "$D" &&
+ rm -rf does-not-exist &&
+ test_must_fail git clone does-not-exist
+'
+
+test_expect_success 'cloning non-git directory fails' '
+ cd "$D" &&
+ rm -rf not-a-git-repo not-a-git-repo-clone &&
+ mkdir not-a-git-repo &&
+ test_must_fail git clone not-a-git-repo not-a-git-repo-clone
+'
+
test_done
diff --git a/t/t6035-merge-dir-to-symlink.sh b/t/t6035-merge-dir-to-symlink.sh
index 92e02d5d77..2599ae50eb 100755
--- a/t/t6035-merge-dir-to-symlink.sh
+++ b/t/t6035-merge-dir-to-symlink.sh
@@ -17,13 +17,21 @@ test_expect_success SYMLINKS 'create a commit where dir a/b changed to symlink'
git commit -m "dir to symlink"
'
-test_expect_success SYMLINKS 'keep a/b-2/c/d across checkout' '
+test_expect_success SYMLINKS 'checkout does not clobber untracked symlink' '
git checkout HEAD^0 &&
git reset --hard master &&
git rm --cached a/b &&
git commit -m "untracked symlink remains" &&
- git checkout start^0 &&
- test -f a/b-2/c/d
+ test_must_fail git checkout start^0
+'
+
+test_expect_success SYMLINKS 'a/b-2/c/d is kept when clobbering symlink b' '
+ git checkout HEAD^0 &&
+ git reset --hard master &&
+ git rm --cached a/b &&
+ git commit -m "untracked symlink remains" &&
+ git checkout -f start^0 &&
+ test -f a/b-2/c/d
'
test_expect_success SYMLINKS 'checkout should not have deleted a/b-2/c/d' '
diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh
index 1e0447f615..cb85132642 100755
--- a/t/t6040-tracking-info.sh
+++ b/t/t6040-tracking-info.sh
@@ -74,20 +74,20 @@ test_expect_success 'status' '
grep "have 1 and 1 different" actual
'
-test_expect_success 'status when tracking lightweight tags' '
+test_expect_success 'fail to track lightweight tags' '
git checkout master &&
git tag light &&
- git branch --track lighttrack light >actual &&
- grep "set up to track" actual &&
- git checkout lighttrack
+ test_must_fail git branch --track lighttrack light >actual &&
+ test_must_fail grep "set up to track" actual &&
+ test_must_fail git checkout lighttrack
'
-test_expect_success 'status when tracking annotated tags' '
+test_expect_success 'fail to track annotated tags' '
git checkout master &&
git tag -m heavy heavy &&
- git branch --track heavytrack heavy >actual &&
- grep "set up to track" actual &&
- git checkout heavytrack
+ test_must_fail git branch --track heavytrack heavy >actual &&
+ test_must_fail grep "set up to track" actual &&
+ test_must_fail git checkout heavytrack
'
test_expect_success 'setup tracking with branch --set-upstream on existing branch' '
diff --git a/t/t6110-rev-list-sparse.sh b/t/t6110-rev-list-sparse.sh
new file mode 100755
index 0000000000..2a267e84cd
--- /dev/null
+++ b/t/t6110-rev-list-sparse.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+test_description='operations that cull histories in unusual ways'
+. ./test-lib.sh
+
+test_commit () {
+ echo "$1" >"$1.file" &&
+ git add "$1.file" &&
+ test_tick &&
+ git commit -m "$1"
+}
+
+test_expect_success setup '
+ test_commit A &&
+ test_commit B &&
+ test_commit C &&
+ git checkout -b side HEAD^ &&
+ test_commit D &&
+ test_commit E &&
+ git merge master
+'
+
+test_expect_success 'rev-list --first-parent --boundary' '
+ git rev-list --first-parent --boundary HEAD^..
+'
+
+test_done
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 1337fa5a22..0c002ab695 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -408,6 +408,15 @@ test_expect_success 'checkout w/--track from non-branch HEAD fails' '
test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)"
'
+test_expect_success 'checkout w/--track from tag fails' '
+ git checkout master^0 &&
+ test_must_fail git symbolic-ref HEAD &&
+ test_must_fail git checkout --track -b track frotz &&
+ test_must_fail git rev-parse --verify track &&
+ test_must_fail git symbolic-ref HEAD &&
+ test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)"
+'
+
test_expect_success 'detach a symbolic link HEAD' '
git checkout master &&
git config --bool core.prefersymlinkrefs yes &&
@@ -423,7 +432,6 @@ test_expect_success 'detach a symbolic link HEAD' '
test_expect_success \
'checkout with --track fakes a sensible -b <name>' '
git update-ref refs/remotes/origin/koala/bear renamer &&
- git update-ref refs/new/koala/bear renamer &&
git checkout --track origin/koala/bear &&
test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
@@ -439,12 +447,6 @@ test_expect_success \
git checkout --track remotes/origin/koala/bear &&
test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
- test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
-
- git checkout master && git branch -D koala/bear &&
-
- git checkout --track refs/new/koala/bear &&
- test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)"
'
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index bfb4975e94..fa9d23aa31 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -203,4 +203,56 @@ test_expect_success 'submodule init picks up merge' '
)
'
+test_expect_success 'submodule update --merge - ignores --merge for new submodules' '
+ (cd super &&
+ rm -rf submodule &&
+ git submodule update submodule &&
+ git status -s submodule >expect &&
+ rm -rf submodule &&
+ git submodule update --merge submodule &&
+ git status -s submodule >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'submodule update --rebase - ignores --rebase for new submodules' '
+ (cd super &&
+ rm -rf submodule &&
+ git submodule update submodule &&
+ git status -s submodule >expect &&
+ rm -rf submodule &&
+ git submodule update --rebase submodule &&
+ git status -s submodule >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'submodule update ignores update=merge config for new submodules' '
+ (cd super &&
+ rm -rf submodule &&
+ git submodule update submodule &&
+ git status -s submodule >expect &&
+ rm -rf submodule &&
+ git config submodule.submodule.update merge &&
+ git submodule update submodule &&
+ git status -s submodule >actual &&
+ git config --unset submodule.submodule.update &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'submodule update ignores update=rebase config for new submodules' '
+ (cd super &&
+ rm -rf submodule &&
+ git submodule update submodule &&
+ git status -s submodule >expect &&
+ rm -rf submodule &&
+ git config submodule.submodule.update rebase &&
+ git submodule update submodule &&
+ git status -s submodule >actual &&
+ git config --unset submodule.submodule.update &&
+ test_cmp expect actual
+ )
+'
+
test_done
diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh
index d8ad25036f..e5be13c271 100755
--- a/t/t7407-submodule-foreach.sh
+++ b/t/t7407-submodule-foreach.sh
@@ -238,6 +238,10 @@ test_expect_success 'ensure "status --cached --recursive" preserves the --cached
) &&
git submodule status --cached --recursive -- nested1 > ../actual
) &&
+ if test_have_prereq MINGW
+ then
+ dos2unix actual
+ fi &&
test_cmp expect actual
'
diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh
index 162527c211..5976f598fc 100755
--- a/t/t7500-commit.sh
+++ b/t/t7500-commit.sh
@@ -10,7 +10,12 @@ Tests for selected commit options.'
. ./test-lib.sh
commit_msg_is () {
- test "`git log --pretty=format:%s%b -1`" = "$1"
+ expect=commit_msg_is.expect
+ actual=commit_msg_is.actual
+
+ printf "%s" "$(git log --pretty=format:%s%b -1)" >$expect &&
+ printf "%s" "$1" >$actual &&
+ test_cmp $expect $actual
}
# A sanity check to see if commit is working at all.
@@ -23,13 +28,21 @@ test_expect_success 'a basic commit in an empty tree should succeed' '
test_expect_success 'nonexistent template file should return error' '
echo changes >> foo &&
git add foo &&
- test_must_fail git commit --template "$PWD"/notexist
+ (
+ GIT_EDITOR="echo hello >\"\$1\"" &&
+ export GIT_EDITOR &&
+ test_must_fail git commit --template "$PWD"/notexist
+ )
'
test_expect_success 'nonexistent template file in config should return error' '
git config commit.template "$PWD"/notexist &&
- test_must_fail git commit &&
- git config --unset commit.template
+ test_when_finished "git config --unset commit.template" &&
+ (
+ GIT_EDITOR="echo hello >\"\$1\"" &&
+ export GIT_EDITOR &&
+ test_must_fail git commit
+ )
'
# From now on we'll use a template file that exists.
diff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh
index ff189624d4..5b4b694f18 100755
--- a/t/t7505-prepare-commit-msg-hook.sh
+++ b/t/t7505-prepare-commit-msg-hook.sh
@@ -132,6 +132,18 @@ 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 &&
+ git add file &&
+ git commit -m other &&
+ git checkout - &&
+ git merge other &&
+ test "`git log -1 --pretty=format:%s`" = merge
+'
+
cat > "$HOOK" <<'EOF'
#!/bin/sh
exit 1
diff --git a/t/t8001-annotate.sh b/t/t8001-annotate.sh
index 45cb60ea4b..41962f04a7 100755
--- a/t/t8001-annotate.sh
+++ b/t/t8001-annotate.sh
@@ -6,10 +6,11 @@ test_description='git annotate'
PROG='git annotate'
. "$TEST_DIRECTORY"/annotate-tests.sh
-test_expect_success \
- 'Annotating an old revision works' \
- '[ $(git annotate file master | awk "{print \$3}" | grep -c "^A$") -eq 2 ] && \
- [ $(git annotate file master | awk "{print \$3}" | grep -c "^B$") -eq 2 ]'
-
+test_expect_success 'Annotating an old revision works' '
+ git annotate file master >result &&
+ awk "{ print \$3; }" <result >authors &&
+ test 2 = $(grep A <authors | wc -l) &&
+ test 2 = $(grep B <authors | wc -l)
+'
test_done
diff --git a/t/t8006-blame-textconv.sh b/t/t8006-blame-textconv.sh
index ea64cd8d0f..32ec82ad67 100755
--- a/t/t8006-blame-textconv.sh
+++ b/t/t8006-blame-textconv.sh
@@ -25,7 +25,8 @@ test_expect_success 'setup ' '
echo "bin: test 1 version 2" >one.bin &&
echo "bin: test number 2 version 2" >>two.bin &&
if test_have_prereq SYMLINKS; then
- ln -sf two.bin symlink.bin
+ rm symlink.bin &&
+ ln -s two.bin symlink.bin
fi &&
GIT_AUTHOR_NAME=Number2 git commit -a -m Second --date="2010-01-01 20:00:00"
'
diff --git a/t/t9301-fast-import-notes.sh b/t/t9301-fast-import-notes.sh
index 7cf8cd8a2f..463254c727 100755
--- a/t/t9301-fast-import-notes.sh
+++ b/t/t9301-fast-import-notes.sh
@@ -120,6 +120,7 @@ test_expect_success 'add notes with simple M command' '
test_tick
cat >input <<INPUT_END
+feature notes
commit refs/notes/test
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<COMMIT
diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh
index 21cd286bb7..35c151d7ea 100755
--- a/t/t9500-gitweb-standalone-no-errors.sh
+++ b/t/t9500-gitweb-standalone-no-errors.sh
@@ -18,42 +18,34 @@ or warnings to log.'
test_expect_success \
'no commits: projects_list (implicit)' \
'gitweb_run'
-test_debug 'cat gitweb.log'
test_expect_success \
'no commits: projects_index' \
'gitweb_run "a=project_index"'
-test_debug 'cat gitweb.log'
test_expect_success \
'no commits: .git summary (implicit)' \
'gitweb_run "p=.git"'
-test_debug 'cat gitweb.log'
test_expect_success \
'no commits: .git commit (implicit HEAD)' \
'gitweb_run "p=.git;a=commit"'
-test_debug 'cat gitweb.log'
test_expect_success \
'no commits: .git commitdiff (implicit HEAD)' \
'gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'no commits: .git tree (implicit HEAD)' \
'gitweb_run "p=.git;a=tree"'
-test_debug 'cat gitweb.log'
test_expect_success \
'no commits: .git heads' \
'gitweb_run "p=.git;a=heads"'
-test_debug 'cat gitweb.log'
test_expect_success \
'no commits: .git tags' \
'gitweb_run "p=.git;a=tags"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
@@ -69,52 +61,42 @@ test_expect_success \
test_expect_success \
'projects_list (implicit)' \
'gitweb_run'
-test_debug 'cat gitweb.log'
test_expect_success \
'projects_index' \
'gitweb_run "a=project_index"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git summary (implicit)' \
'gitweb_run "p=.git"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git commit (implicit HEAD)' \
'gitweb_run "p=.git;a=commit"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git commitdiff (implicit HEAD, root commit)' \
'gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git commitdiff_plain (implicit HEAD, root commit)' \
'gitweb_run "p=.git;a=commitdiff_plain"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git commit (HEAD)' \
'gitweb_run "p=.git;a=commit;h=HEAD"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git tree (implicit HEAD)' \
'gitweb_run "p=.git;a=tree"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git blob (file)' \
'gitweb_run "p=.git;a=blob;f=file"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git blob_plain (file)' \
'gitweb_run "p=.git;a=blob_plain;f=file"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# nonexistent objects
@@ -122,37 +104,30 @@ test_debug 'cat gitweb.log'
test_expect_success \
'.git commit (non-existent)' \
'gitweb_run "p=.git;a=commit;h=non-existent"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git commitdiff (non-existent)' \
'gitweb_run "p=.git;a=commitdiff;h=non-existent"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git commitdiff (non-existent vs HEAD)' \
'gitweb_run "p=.git;a=commitdiff;hp=non-existent;h=HEAD"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git tree (0000000000000000000000000000000000000000)' \
'gitweb_run "p=.git;a=tree;h=0000000000000000000000000000000000000000"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git tag (0000000000000000000000000000000000000000)' \
'gitweb_run "p=.git;a=tag;h=0000000000000000000000000000000000000000"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git blob (non-existent)' \
'gitweb_run "p=.git;a=blob;f=non-existent"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git blob_plain (non-existent)' \
'gitweb_run "p=.git;a=blob_plain;f=non-existent"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
@@ -161,7 +136,6 @@ test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): root' \
'gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): file added' \
@@ -169,21 +143,18 @@ test_expect_success \
git add new_file &&
git commit -a -m "File added." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): mode change' \
'test_chmod +x new_file &&
git commit -a -m "Mode changed." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): file renamed' \
'git mv new_file renamed_file &&
git commit -a -m "File renamed." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success SYMLINKS \
'commitdiff(0): file to symlink' \
@@ -191,7 +162,6 @@ test_expect_success SYMLINKS \
ln -s file renamed_file &&
git commit -a -m "File to symlink." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): file deleted' \
@@ -199,7 +169,6 @@ test_expect_success \
rm -f renamed_file &&
git commit -a -m "File removed." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): file copied / new file' \
@@ -207,7 +176,6 @@ test_expect_success \
git add file2 &&
git commit -a -m "File copied." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): mode change and modified' \
@@ -215,7 +183,6 @@ test_expect_success \
test_chmod +x file2 &&
git commit -a -m "Mode change and modification." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): renamed and modified' \
@@ -233,7 +200,6 @@ EOF
echo "Propter nomen suum." >> file3 &&
git commit -a -m "File rename and modification." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): renamed, mode change and modified' \
@@ -242,7 +208,6 @@ test_expect_success \
test_chmod +x file2 &&
git commit -a -m "File rename, mode change and modification." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# commitdiff testing (taken from t4114-apply-typechange.sh)
@@ -279,42 +244,34 @@ test_expect_success SYMLINKS 'setup typechange commits' '
test_expect_success \
'commitdiff(2): file renamed from foo to foo/baz' \
'gitweb_run "p=.git;a=commitdiff;hp=initial;h=foo-baz-renamed-from-foo"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(2): file renamed from foo/baz to foo' \
'gitweb_run "p=.git;a=commitdiff;hp=foo-baz-renamed-from-foo;h=initial"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(2): directory becomes file' \
'gitweb_run "p=.git;a=commitdiff;hp=foo-becomes-a-directory;h=initial"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(2): file becomes directory' \
'gitweb_run "p=.git;a=commitdiff;hp=initial;h=foo-becomes-a-directory"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(2): file becomes symlink' \
'gitweb_run "p=.git;a=commitdiff;hp=initial;h=foo-symlinked-to-bar"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(2): symlink becomes file' \
'gitweb_run "p=.git;a=commitdiff;hp=foo-symlinked-to-bar;h=foo-back-to-file"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(2): symlink becomes directory' \
'gitweb_run "p=.git;a=commitdiff;hp=foo-symlinked-to-bar;h=foo-becomes-a-directory"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(2): directory becomes symlink' \
'gitweb_run "p=.git;a=commitdiff;hp=foo-becomes-a-directory;h=foo-symlinked-to-bar"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# commit, commitdiff: merge, large
@@ -330,12 +287,10 @@ test_expect_success \
test_expect_success \
'commit(0): merge commit' \
'gitweb_run "p=.git;a=commit"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): merge commit' \
'gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'Prepare large commit' \
@@ -371,12 +326,10 @@ test_expect_success \
test_expect_success \
'commit(1): large commit' \
'gitweb_run "p=.git;a=commit;h=b"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(1): large commit' \
'gitweb_run "p=.git;a=commitdiff;h=b"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# tags testing
@@ -394,17 +347,14 @@ test_expect_success \
git tag lightweight/tag-tree HEAD^{tree} &&
git tag lightweight/tag-blob HEAD:file &&
gitweb_run "p=.git;a=tags"'
-test_debug 'cat gitweb.log'
test_expect_success \
'tag: Tag to commit object' \
'gitweb_run "p=.git;a=tag;h=tag-commit"'
-test_debug 'cat gitweb.log'
test_expect_success \
'tag: on lightweight tag (invalid)' \
'gitweb_run "p=.git;a=tag;h=lightweight/tag-commit"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# logs
@@ -412,22 +362,18 @@ test_debug 'cat gitweb.log'
test_expect_success \
'logs: log (implicit HEAD)' \
'gitweb_run "p=.git;a=log"'
-test_debug 'cat gitweb.log'
test_expect_success \
'logs: shortlog (implicit HEAD)' \
'gitweb_run "p=.git;a=shortlog"'
-test_debug 'cat gitweb.log'
test_expect_success \
'logs: history (implicit HEAD, file)' \
'gitweb_run "p=.git;a=history;f=file"'
-test_debug 'cat gitweb.log'
test_expect_success \
'logs: history (implicit HEAD, non-existent file)' \
'gitweb_run "p=.git;a=history;f=non-existent"'
-test_debug 'cat gitweb.log'
test_expect_success \
'logs: history (implicit HEAD, deleted file)' \
@@ -438,55 +384,45 @@ test_expect_success \
git rm deleted_file &&
git commit -m "Delete file" &&
gitweb_run "p=.git;a=history;f=deleted_file"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# path_info links
test_expect_success \
'path_info: project' \
'gitweb_run "" "/.git"'
-test_debug 'cat gitweb.log'
test_expect_success \
'path_info: project/branch' \
'gitweb_run "" "/.git/b"'
-test_debug 'cat gitweb.log'
test_expect_success \
'path_info: project/branch:file' \
'gitweb_run "" "/.git/master:file"'
-test_debug 'cat gitweb.log'
test_expect_success \
'path_info: project/branch:dir/' \
'gitweb_run "" "/.git/master:foo/"'
-test_debug 'cat gitweb.log'
test_expect_success \
'path_info: project/branch:file (non-existent)' \
'gitweb_run "" "/.git/master:non-existent"'
-test_debug 'cat gitweb.log'
test_expect_success \
'path_info: project/branch:dir/ (non-existent)' \
'gitweb_run "" "/.git/master:non-existent/"'
-test_debug 'cat gitweb.log'
test_expect_success \
'path_info: project/branch:/file' \
'gitweb_run "" "/.git/master:/file"'
-test_debug 'cat gitweb.log'
test_expect_success \
'path_info: project/:/file (implicit HEAD)' \
'gitweb_run "" "/.git/:/file"'
-test_debug 'cat gitweb.log'
test_expect_success \
'path_info: project/:/ (implicit HEAD, top tree)' \
'gitweb_run "" "/.git/:/"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
@@ -495,17 +431,14 @@ test_debug 'cat gitweb.log'
test_expect_success \
'feeds: OPML' \
'gitweb_run "a=opml"'
-test_debug 'cat gitweb.log'
test_expect_success \
'feed: RSS' \
'gitweb_run "p=.git;a=rss"'
-test_debug 'cat gitweb.log'
test_expect_success \
'feed: Atom' \
'gitweb_run "p=.git;a=atom"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# encoding/decoding
@@ -517,7 +450,6 @@ test_expect_success \
git add file &&
git commit -F "$TEST_DIRECTORY"/t3900/1-UTF-8.txt &&
gitweb_run "p=.git;a=commit"'
-test_debug 'cat gitweb.log'
test_expect_success \
'encode(commit): iso-8859-1' \
@@ -528,12 +460,10 @@ test_expect_success \
git commit -F "$TEST_DIRECTORY"/t3900/ISO8859-1.txt &&
git config --unset i18n.commitencoding &&
gitweb_run "p=.git;a=commit"'
-test_debug 'cat gitweb.log'
test_expect_success \
'encode(log): utf-8 and iso-8859-1' \
'gitweb_run "p=.git;a=log"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# extra options
@@ -541,27 +471,22 @@ test_debug 'cat gitweb.log'
test_expect_success \
'opt: log --no-merges' \
'gitweb_run "p=.git;a=log;opt=--no-merges"'
-test_debug 'cat gitweb.log'
test_expect_success \
'opt: atom --no-merges' \
'gitweb_run "p=.git;a=log;opt=--no-merges"'
-test_debug 'cat gitweb.log'
test_expect_success \
'opt: "file" history --no-merges' \
'gitweb_run "p=.git;a=history;f=file;opt=--no-merges"'
-test_debug 'cat gitweb.log'
test_expect_success \
'opt: log --no-such-option (invalid option)' \
'gitweb_run "p=.git;a=log;opt=--no-such-option"'
-test_debug 'cat gitweb.log'
test_expect_success \
'opt: tree --no-merges (invalid option for action)' \
'gitweb_run "p=.git;a=tree;opt=--no-merges"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# testing config_to_multi / cloneurl
@@ -569,14 +494,12 @@ test_debug 'cat gitweb.log'
test_expect_success \
'URL: no project URLs, no base URL' \
'gitweb_run "p=.git;a=summary"'
-test_debug 'cat gitweb.log'
test_expect_success \
'URL: project URLs via gitweb.url' \
'git config --add gitweb.url git://example.com/git/trash.git &&
git config --add gitweb.url http://example.com/git/trash.git &&
gitweb_run "p=.git;a=summary"'
-test_debug 'cat gitweb.log'
cat >.git/cloneurl <<\EOF
git://example.com/git/trash.git
@@ -586,7 +509,6 @@ EOF
test_expect_success \
'URL: project URLs via cloneurl file' \
'gitweb_run "p=.git;a=summary"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# gitweb config and repo config
@@ -604,12 +526,10 @@ EOF
test_expect_success \
'config override: projects list (implicit)' \
'gitweb_run'
-test_debug 'cat gitweb.log'
test_expect_success \
'config override: tree view, features not overridden in repo config' \
'gitweb_run "p=.git;a=tree"'
-test_debug 'cat gitweb.log'
test_expect_success \
'config override: tree view, features disabled in repo config' \
@@ -617,14 +537,12 @@ test_expect_success \
git config gitweb.snapshot none &&
git config gitweb.avatar gravatar &&
gitweb_run "p=.git;a=tree"'
-test_debug 'cat gitweb.log'
test_expect_success \
'config override: tree view, features enabled in repo config (1)' \
'git config gitweb.blame yes &&
git config gitweb.snapshot "zip,tgz, tbz2" &&
gitweb_run "p=.git;a=tree"'
-test_debug 'cat gitweb.log'
cat >.git/config <<\EOF
# testing noval and alternate separator
@@ -635,7 +553,6 @@ EOF
test_expect_success \
'config override: tree view, features enabled in repo config (2)' \
'gitweb_run "p=.git;a=tree"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# non-ASCII in README.html
@@ -645,7 +562,6 @@ test_expect_success \
'echo "<b>UTF-8 example:</b><br />" > .git/README.html &&
cat "$TEST_DIRECTORY"/t3900/1-UTF-8.txt >> .git/README.html &&
gitweb_run "p=.git;a=summary"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# syntax highlighting
@@ -666,7 +582,6 @@ test_expect_success HIGHLIGHT \
'syntax highlighting (no highlight, unknown syntax)' \
'git config gitweb.highlight yes &&
gitweb_run "p=.git;a=blob;f=file"'
-test_debug 'cat gitweb.log'
test_expect_success HIGHLIGHT \
'syntax highlighting (highlighted, shell script)' \
@@ -675,6 +590,5 @@ test_expect_success HIGHLIGHT \
git add test.sh &&
git commit -m "Add test.sh" &&
gitweb_run "p=.git;a=blob;f=test.sh"'
-test_debug 'cat gitweb.log'
test_done
diff --git a/t/t9501-gitweb-standalone-http-status.sh b/t/t9501-gitweb-standalone-http-status.sh
index 18825aff89..26102ee9b0 100755
--- a/t/t9501-gitweb-standalone-http-status.sh
+++ b/t/t9501-gitweb-standalone-http-status.sh
@@ -126,7 +126,6 @@ test_expect_success 'load checking: load too high (default action)' '
grep "Status: 503 Service Unavailable" gitweb.headers &&
grep "503 - The load average on the server is too high" gitweb.body
'
-test_debug 'cat gitweb.log' # just in case
test_debug 'cat gitweb.headers'
# turn off load checking
diff --git a/t/t9700/test.pl b/t/t9700/test.pl
index c15ca2d647..13ba96e21a 100755
--- a/t/t9700/test.pl
+++ b/t/t9700/test.pl
@@ -113,6 +113,16 @@ like($last_commit, qr/^[0-9a-fA-F]{40}$/, 'rev-parse returned hash');
my $dir_commit = $r2->command_oneline('log', '-n1', '--pretty=format:%H', '.');
isnt($last_commit, $dir_commit, 'log . does not show last commit');
+# commands outside working tree
+chdir($abs_repo_dir . '/..');
+my $r3 = Git->repository(Directory => $abs_repo_dir);
+my $tmpfile3 = "$abs_repo_dir/file3.tmp";
+open TEMPFILE3, "+>$tmpfile3" or die "Can't open $tmpfile3: $!";
+is($r3->cat_blob($file1hash, \*TEMPFILE3), 15, "cat_blob(outside): size");
+close TEMPFILE3;
+unlink $tmpfile3;
+chdir($abs_repo_dir);
+
printf "1..%d\n", Test::More->builder->current_test;
my $is_passing = eval { Test::More->is_passing };
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 0fdc541a7c..c91e232437 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -1004,14 +1004,14 @@ rm -fr "$test" || {
exit 1
}
+HOME="$TRASH_DIRECTORY"
+export HOME
+
test_create_repo "$test"
# Use -P to resolve symlinks in our working directory so that the cwd
# in subprocesses like git equals our $PWD (for pathname comparisons).
cd -P "$test" || exit 1
-HOME=$(pwd)
-export HOME
-
this_test=${0##*/}
this_test=${this_test%%-*}
for skp in $GIT_SKIP_TESTS
diff --git a/t/valgrind/default.supp b/t/valgrind/default.supp
index 9e013fa3b2..0a6724fcc4 100644
--- a/t/valgrind/default.supp
+++ b/t/valgrind/default.supp
@@ -43,3 +43,9 @@
fun:write_buffer
fun:write_loose_object
}
+
+{
+ ignore-sse-strlen-invalid-read-size
+ Memcheck:Addr4
+ fun:copy_ref
+}
diff --git a/tag.c b/tag.c
index f789744cca..7d38cc0f4d 100644
--- a/tag.c
+++ b/tag.c
@@ -56,7 +56,7 @@ static unsigned long parse_tag_date(const char *buf, const char *tail)
return strtoul(dateptr, NULL, 10);
}
-int parse_tag_buffer(struct tag *item, void *data, unsigned long size)
+int parse_tag_buffer(struct tag *item, const void *data, unsigned long size)
{
unsigned char sha1[20];
char type[20];
@@ -97,7 +97,9 @@ int parse_tag_buffer(struct tag *item, void *data, unsigned long size)
item->tagged = NULL;
}
- if (prefixcmp(bufptr, "tag "))
+ if (bufptr + 4 < tail && !prefixcmp(bufptr, "tag "))
+ ; /* good */
+ else
return -1;
bufptr += 4;
nl = memchr(bufptr, '\n', tail - bufptr);
@@ -106,7 +108,7 @@ int parse_tag_buffer(struct tag *item, void *data, unsigned long size)
item->tag = xmemdupz(bufptr, nl - bufptr);
bufptr = nl + 1;
- if (!prefixcmp(bufptr, "tagger "))
+ if (bufptr + 7 < tail && !prefixcmp(bufptr, "tagger "))
item->date = parse_tag_date(bufptr, tail);
else
item->date = 0;
diff --git a/tag.h b/tag.h
index 8522370039..5ee88e6550 100644
--- a/tag.h
+++ b/tag.h
@@ -13,7 +13,7 @@ struct tag {
};
extern struct tag *lookup_tag(const unsigned char *sha1);
-extern int parse_tag_buffer(struct tag *item, void *data, unsigned long size);
+extern int parse_tag_buffer(struct tag *item, const void *data, unsigned long size);
extern int parse_tag(struct tag *item);
extern struct object *deref_tag(struct object *, const char *, int);
extern size_t parse_signature(const char *buf, unsigned long size);
diff --git a/test-mktemp.c b/test-mktemp.c
new file mode 100644
index 0000000000..c8c54213a3
--- /dev/null
+++ b/test-mktemp.c
@@ -0,0 +1,14 @@
+/*
+ * test-mktemp.c: code to exercise the creation of temporary files
+ */
+#include "git-compat-util.h"
+
+int main(int argc, char *argv[])
+{
+ if (argc != 2)
+ usage("Expected 1 parameter defining the temporary file template");
+
+ xmkstemp(xstrdup(argv[1]));
+
+ return 0;
+}
diff --git a/test-parse-options.c b/test-parse-options.c
index 0828592162..4e3710b9a8 100644
--- a/test-parse-options.c
+++ b/test-parse-options.c
@@ -46,7 +46,7 @@ int main(int argc, const char **argv)
OPT_DATE('t', NULL, &timestamp, "get timestamp of <time>"),
OPT_CALLBACK('L', "length", &integer, "str",
"get length of <str>", length_callback),
- OPT_FILENAME('F', "file", &file, "set file to <FILE>"),
+ OPT_FILENAME('F', "file", &file, "set file to <file>"),
OPT_GROUP("String options"),
OPT_STRING('s', "string", &string, "string", "get a string"),
OPT_STRING(0, "string2", &string, "str", "get another string"),
diff --git a/transport-helper.c b/transport-helper.c
index 4e4754c32b..8866adf088 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -12,8 +12,7 @@
static int debug;
-struct helper_data
-{
+struct helper_data {
const char *name;
struct child_process *helper;
FILE *out;
diff --git a/utf8.c b/utf8.c
index 84cfc72e6d..8acbc660d3 100644
--- a/utf8.c
+++ b/utf8.c
@@ -405,6 +405,15 @@ new_line:
}
}
+int strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
+ int indent, int indent2, int width)
+{
+ char *tmp = xstrndup(data, len);
+ int r = strbuf_add_wrapped_text(buf, tmp, indent, indent2, width);
+ free(tmp);
+ return r;
+}
+
int is_encoding_utf8(const char *name)
{
if (!name)
diff --git a/utf8.h b/utf8.h
index ebc4d2fa85..81f2c82fab 100644
--- a/utf8.h
+++ b/utf8.h
@@ -10,6 +10,8 @@ int is_encoding_utf8(const char *name);
int strbuf_add_wrapped_text(struct strbuf *buf,
const char *text, int indent, int indent2, int width);
+int strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
+ int indent, int indent2, int width);
#ifndef NO_ICONV
char *reencode_string(const char *in, const char *out_encoding, const char *in_encoding);
diff --git a/wrapper.c b/wrapper.c
index 8d7dd31c4b..4c147d6c48 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -53,7 +53,7 @@ void *xmalloc(size_t size)
void *xmallocz(size_t size)
{
void *ret;
- if (size + 1 < size)
+ if (unsigned_add_overflows(size, 1))
die("Data too large to fit into virtual memory space.");
ret = xmalloc(size + 1);
((char*)ret)[size] = 0;
@@ -198,10 +198,22 @@ FILE *xfdopen(int fd, const char *mode)
int xmkstemp(char *template)
{
int fd;
+ char origtemplate[PATH_MAX];
+ strlcpy(origtemplate, template, sizeof(origtemplate));
fd = mkstemp(template);
- if (fd < 0)
- die_errno("Unable to create temporary file");
+ if (fd < 0) {
+ int saved_errno = errno;
+ const char *nonrelative_template;
+
+ if (!template[0])
+ template = origtemplate;
+
+ nonrelative_template = make_nonrelative_path(template);
+ errno = saved_errno;
+ die_errno("Unable to create temporary file '%s'",
+ nonrelative_template);
+ }
return fd;
}
@@ -321,10 +333,22 @@ int gitmkstemps(char *pattern, int suffix_len)
int xmkstemp_mode(char *template, int mode)
{
int fd;
+ char origtemplate[PATH_MAX];
+ strlcpy(origtemplate, template, sizeof(origtemplate));
fd = git_mkstemp_mode(template, mode);
- if (fd < 0)
- die_errno("Unable to create temporary file");
+ if (fd < 0) {
+ int saved_errno = errno;
+ const char *nonrelative_template;
+
+ if (!template[0])
+ template = origtemplate;
+
+ nonrelative_template = make_nonrelative_path(template);
+ errno = saved_errno;
+ die_errno("Unable to create temporary file '%s'",
+ nonrelative_template);
+ }
return fd;
}