summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/CONTRIBUTING.md19
-rw-r--r--.github/PULL_REQUEST_TEMPLATE.md7
-rw-r--r--Documentation/RelNotes/1.7.10.1.txt2
-rw-r--r--Documentation/RelNotes/2.12.0.txt2
-rw-r--r--Documentation/RelNotes/2.13.2.txt17
-rw-r--r--Documentation/RelNotes/2.14.0.txt120
-rw-r--r--Documentation/config.txt17
-rw-r--r--Documentation/git-add.txt7
-rw-r--r--Documentation/git-fast-import.txt2
-rw-r--r--Documentation/git-filter-branch.txt17
-rw-r--r--Documentation/git-pull.txt2
-rw-r--r--Documentation/git-rebase.txt2
-rw-r--r--Documentation/git-reset.txt4
-rw-r--r--Documentation/git-stash.txt60
-rw-r--r--Documentation/git-status.txt3
-rw-r--r--Documentation/git-submodule.txt51
-rw-r--r--Documentation/gitattributes.txt2
-rw-r--r--Documentation/gitcli.txt2
-rw-r--r--Documentation/glossary-content.txt4
-rw-r--r--Documentation/pretty-formats.txt15
-rw-r--r--Documentation/rev-list-options.txt3
-rw-r--r--Makefile3
-rw-r--r--abspath.c2
-rw-r--r--advice.c2
-rw-r--r--advice.h1
-rw-r--r--alias.c6
-rw-r--r--apply.c49
-rw-r--r--attr.c6
-rw-r--r--blame.c3
-rw-r--r--branch.c3
-rw-r--r--builtin/add.c46
-rw-r--r--builtin/am.c18
-rw-r--r--builtin/clean.c6
-rw-r--r--builtin/commit.c7
-rw-r--r--builtin/config.c6
-rw-r--r--builtin/grep.c2
-rw-r--r--builtin/index-pack.c6
-rw-r--r--builtin/pack-objects.c12
-rw-r--r--builtin/show-branch.c13
-rw-r--r--builtin/unpack-objects.c3
-rw-r--r--builtin/worktree.c6
-rw-r--r--commit-slab.h3
-rw-r--r--commit.c3
-rw-r--r--compat/regex/regexec.c2
-rw-r--r--config.c3
-rw-r--r--configure.ac4
-rw-r--r--contrib/coccinelle/free.cocci15
-rw-r--r--contrib/diff-highlight/.gitignore2
-rw-r--r--[-rwxr-xr-x]contrib/diff-highlight/DiffHighlight.pm (renamed from contrib/diff-highlight/diff-highlight)40
-rw-r--r--contrib/diff-highlight/Makefile21
-rw-r--r--contrib/diff-highlight/README30
-rw-r--r--contrib/diff-highlight/diff-highlight.perl8
-rwxr-xr-xcontrib/hooks/multimail/git_multimail.py2
-rwxr-xr-xcontrib/mw-to-git/git-remote-mediawiki.perl2
-rw-r--r--contrib/mw-to-git/t/README2
-rw-r--r--credential.c9
-rw-r--r--date.c14
-rw-r--r--diff-lib.c3
-rw-r--r--diff.c6
-rw-r--r--diffcore-rename.c6
-rw-r--r--dir.c18
-rw-r--r--dir.h3
-rw-r--r--fast-import.c8
-rwxr-xr-xgit-add--interactive.perl3
-rw-r--r--git-compat-util.h6
-rwxr-xr-xgit-filter-branch.sh20
-rwxr-xr-xgit-rebase.sh4
-rwxr-xr-xgit-stash.sh9
-rwxr-xr-xgit-submodule.sh5
-rwxr-xr-xgitweb/gitweb.perl4
-rw-r--r--gpg-interface.c15
-rw-r--r--grep.c14
-rw-r--r--help.c21
-rw-r--r--http-push.c24
-rw-r--r--http.c15
-rw-r--r--imap-send.c3
-rw-r--r--line-log.c6
-rw-r--r--ll-merge.c3
-rw-r--r--mailinfo.c19
-rw-r--r--mergetools/meld2
-rw-r--r--object.c3
-rw-r--r--pack-bitmap.c2
-rw-r--r--pathspec.c5
-rw-r--r--perl/Git/I18N.pm2
-rw-r--r--pretty.c32
-rw-r--r--prio-queue.c3
-rw-r--r--read-cache.c16
-rw-r--r--ref-filter.c3
-rw-r--r--refs.c12
-rw-r--r--refs.h9
-rw-r--r--refs/files-backend.c35
-rw-r--r--refs/ref-cache.c3
-rw-r--r--remote-testsvn.c3
-rw-r--r--rerere.c3
-rw-r--r--revision.c89
-rw-r--r--revision.h5
-rw-r--r--send-pack.c2
-rw-r--r--sequencer.c14
-rw-r--r--sha1-array.c3
-rw-r--r--sha1_file.c3
-rw-r--r--sha1dc/sha1.c2
-rw-r--r--split-index.c60
-rw-r--r--split-index.h1
-rw-r--r--strbuf.c48
-rw-r--r--strbuf.h16
-rw-r--r--submodule.c4
-rw-r--r--t/helper/test-strcmp-offset.c2
-rwxr-xr-xt/t0006-date.sh16
-rwxr-xr-xt/t2203-add-intent.sh6
-rwxr-xr-xt/t3070-wildmatch.sh4
-rwxr-xr-xt/t3200-branch.sh17
-rwxr-xr-xt/t3404-rebase-interactive.sh7
-rwxr-xr-xt/t3420-rebase-autostash.sh138
-rwxr-xr-xt/t3701-add-interactive.sh8
-rwxr-xr-xt/t3903-stash.sh16
-rwxr-xr-xt/t4005-diff-rename-2.sh95
-rwxr-xr-xt/t4041-diff-submodule-option.sh8
-rwxr-xr-xt/t4060-diff-submodule-option-diff-format.sh8
-rwxr-xr-xt/t4129-apply-samemode.sh16
-rwxr-xr-xt/t4133-apply-filenames.sh24
-rwxr-xr-xt/t4136-apply-check.sh18
-rwxr-xr-xt/t4213-log-tabexpand.sh2
-rwxr-xr-xt/t5100-mailinfo.sh42
-rwxr-xr-xt/t5614-clone-submodules-shallow.sh4
-rwxr-xr-xt/t6002-rev-list-bisect.sh14
-rwxr-xr-xt/t6120-describe.sh2
-rwxr-xr-xt/t7401-submodule-summary.sh8
-rwxr-xr-xt/t7412-submodule-absorbgitdirs.sh2
-rwxr-xr-xt/t7413-submodule-is-active.sh2
-rwxr-xr-xt/t7414-submodule-mistakes.sh37
-rwxr-xr-xt/t7501-commit.sh2
-rwxr-xr-xt/t7508-status.sh64
-rwxr-xr-xt/t9300-fast-import.sh2
-rw-r--r--transport-helper.c27
-rw-r--r--transport.c3
-rw-r--r--tree-diff.c6
-rw-r--r--tree.c3
-rw-r--r--usage.c18
-rw-r--r--wt-status.c31
-rw-r--r--wt-status.h2
140 files changed, 1320 insertions, 647 deletions
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
new file mode 100644
index 0000000000..64e605a02b
--- /dev/null
+++ b/.github/CONTRIBUTING.md
@@ -0,0 +1,19 @@
+## Contributing to Git
+
+Thanks for taking the time to contribute to Git! Please be advised that the
+Git community does not use github.com for their contributions. Instead, we use
+a mailing list (git@vger.kernel.org) for code submissions, code
+reviews, and bug reports.
+
+Nevertheless, you can use [submitGit](http://submitgit.herokuapp.com/) to
+conveniently send your Pull Requests commits to our mailing list.
+
+Please read ["A note from the maintainer"](https://git.kernel.org/pub/scm/git/git.git/plain/MaintNotes?h=todo)
+to learn how the Git project is managed, and how you can work with it.
+In addition, we highly recommend you to read [our submission guidelines](../Documentation/SubmittingPatches).
+
+If you prefer video, then [this talk](https://www.youtube.com/watch?v=Q7i_qQW__q4&feature=youtu.be&t=6m4s)
+might be useful to you as the presenter walks you through the contribution
+process by example.
+
+Your friendly Git community!
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000000..adba13e5ba
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,7 @@
+Thanks for taking the time to contribute to Git! Please be advised that the
+Git community does not use github.com for their contributions. Instead, we use
+a mailing list (git@vger.kernel.org) for code submissions, code reviews, and
+bug reports. Nevertheless, you can use submitGit to conveniently send your Pull
+Requests commits to our mailing list.
+
+Please read the "guidelines for contributing" linked above!
diff --git a/Documentation/RelNotes/1.7.10.1.txt b/Documentation/RelNotes/1.7.10.1.txt
index be68524cff..71a86cb7c6 100644
--- a/Documentation/RelNotes/1.7.10.1.txt
+++ b/Documentation/RelNotes/1.7.10.1.txt
@@ -69,7 +69,7 @@ Fixes since v1.7.10
* The 'push to upstream' implementation was broken in some corner
cases. "git push $there" without refspec, when the current branch
is set to push to a remote different from $there, used to push to
- $there using the upstream information to a remote unreleated to
+ $there using the upstream information to a remote unrelated to
$there.
* Giving "--continue" to a conflicted "rebase -i" session skipped a
diff --git a/Documentation/RelNotes/2.12.0.txt b/Documentation/RelNotes/2.12.0.txt
index 29154805b4..ef8b97da9b 100644
--- a/Documentation/RelNotes/2.12.0.txt
+++ b/Documentation/RelNotes/2.12.0.txt
@@ -264,7 +264,7 @@ notes for details).
needed it so far.
* Git 2.11 had a minor regression in "merge --ff-only" that competed
- with another process that simultanously attempted to update the
+ with another process that simultaneously attempted to update the
index. We used to explain what went wrong with an error message,
but the new code silently failed. The error message has been
resurrected.
diff --git a/Documentation/RelNotes/2.13.2.txt b/Documentation/RelNotes/2.13.2.txt
index c8ba0fa16f..8c2b20071e 100644
--- a/Documentation/RelNotes/2.13.2.txt
+++ b/Documentation/RelNotes/2.13.2.txt
@@ -34,4 +34,21 @@ Fixes since v2.13.1
* "git pull --rebase --autostash" didn't auto-stash when the local history
fast-forwards to the upstream.
+ * "git describe --contains" penalized light-weight tags so much that
+ they were almost never considered. Instead, give them about the
+ same chance to be considered as an annotated tag that is the same
+ age as the underlying commit would.
+
+ * The result from "git diff" that compares two blobs, e.g. "git diff
+ $commit1:$path $commit2:$path", used to be shown with the full
+ object name as given on the command line, but it is more natural to
+ use the $path in the output and use it to look up .gitattributes.
+
+ * A flaky test has been corrected.
+
+ * Help contributors that visit us at GitHub.
+
+ * "git stash push <pathspec>" did not work from a subdirectory at all.
+ Bugfix for a topic in v2.13
+
Also contains various documentation updates and code clean-ups.
diff --git a/Documentation/RelNotes/2.14.0.txt b/Documentation/RelNotes/2.14.0.txt
index a71615a6b4..55c54a76be 100644
--- a/Documentation/RelNotes/2.14.0.txt
+++ b/Documentation/RelNotes/2.14.0.txt
@@ -38,26 +38,23 @@ UI, Workflows & Features
* "git archive --format=zip" learned to use zip64 extension when
necessary to go beyond the 4GB limit.
- (merge 867e40ff3a rs/large-zip later to maint).
* "git reset" learned "--recurse-submodules" option.
* "git diff --submodule=diff" now recurses into nested submodules.
- (merge 5a5221427c jk/diff-submodule-diff-inline later to maint).
* "git repack" learned to accept the --threads=<n> option and pass it
to pack-objects.
* "git send-email" learned to run sendemail-validate hook to inspect
and reject a message before sending it out.
- (merge 177409e589 jt/send-email-validate-hook later to maint).
* There is no good reason why "git fetch $there $sha1" should fail
when the $sha1 names an object at the tip of an advertised ref,
even when the other side hasn't enabled allowTipSHA1InWant.
* The recently introduced "[includeIf "gitdir:$dir"] path=..."
- mechansim has further been taught to take symlinks into account.
+ mechanism has further been taught to take symlinks into account.
The directory "$dir" specified in "gitdir:$dir" may be a symlink to
a real location, not something that $(getcwd) may return. In such
a case, a realpath of "$dir" is compared with the real path of the
@@ -81,11 +78,28 @@ UI, Workflows & Features
required disambiguation more often. The command line parser
learned to say "it's a pathspec" a bit more often when the syntax
looks like so.
- (merge 2cb47ab695 jk/pathspec-magic-disambiguation later to maint).
* Update "perl-compatible regular expression" support to enable JIT
and also allow linking with the newer PCRE v2 library.
+ * "filter-branch" learned a pseudo filter "--setup" that can be used
+ to define common functions/variables that can be used by other
+ filters.
+
+ * Using "git add d/i/r" when d/i/r is the top of the working tree of
+ a separate repository would create a gitlink in the index, which
+ would appear as a not-quite-initialized submodule to others. We
+ learned to give warnings when this happens.
+
+ * "git status" learned to optionally give how many stash entries the
+ user has in its output.
+
+ * "git status" has long shown essentially the same message as "git
+ commit"; the message it gives while preparing for the root commit,
+ i.e. "Initial commit", was hard to understand for some new users.
+ Now it says "No commits yet" to stress more on the current status
+ (rather than the commit the user is preparing for, which is more in
+ line with the focus of "git commit").
Performance, Internal Implementation, Development Support etc.
@@ -95,7 +109,6 @@ Performance, Internal Implementation, Development Support etc.
* Code to update the cache-tree has been tightened so that we won't
accidentally write out any 0{40} entry in the tree object.
- (merge a96d3cc3f6 jk/no-null-sha1-in-cache-tree later to maint).
* Attempt to allow us notice "fishy" situation where we fail to
remove the temporary directory used during the test.
@@ -118,14 +131,11 @@ Performance, Internal Implementation, Development Support etc.
* Simplify parse_pathspec() codepath and stop it from looking at the
default in-core index.
- (merge 08de9151a8 bw/pathspec-sans-the-index later to maint).
* Add perf-test for wildmatch.
- (merge 62ca75a6b9 ab/perf-wildmatch later to maint).
* Code from "conversion using external process" codepath has been
extracted to a separate sub-process.[ch] module.
- (merge 4f2a2e9f0e bp/sub-process-convert-filter later to maint).
* When "git checkout", "git merge", etc. manipulates the in-core
index, various pieces of information in the index extensions are
@@ -136,7 +146,6 @@ Performance, Internal Implementation, Development Support etc.
cache is properly invalidated).
* The internal implementation of "git grep" has seen some clean-up.
- (merge 8df4c2953f ab/grep-preparatory-cleanup later to maint).
* Update the C style recommendation for notes for translators, as
recent versions of gettext tools can work with our style of
@@ -168,6 +177,31 @@ Performance, Internal Implementation, Development Support etc.
which then may cause Git operations to fail. Single out "the index
being locked" case and forcibly drop the lock from the copy.
+ * Three instances of the same helper function have been consolidated
+ to one.
+
+ * "fast-import" uses a default pack chain depth that is consistent
+ with other parts of the system.
+
+ * A new test to show the interaction between the pattern [^a-z]
+ (which matches '/') and a slash in a path has been added. The
+ pattern should not match the slash with "pathmatch", but should
+ with "wildmatch".
+
+ * The 'diff-highlight' program (in contrib/) has been restructured
+ for easier reuse by an external project 'diff-so-fancy'.
+ (merge 0c977dbc81 jk/diff-highlight-module later to maint).
+
+ * A common pattern to free a piece of memory and assign NULL to the
+ pointer that used to point at it has been replaced with a new
+ FREE_AND_NULL() macro.
+
+ * Traditionally, the default die() routine had a code to prevent it
+ from getting called multiple times, which interacted badly when a
+ threaded program used it (one downside is that the real error may
+ be hidden and instead the only error message given to the user may
+ end up being "die recursion detected", which is not very useful).
+
Also contains various documentation updates and code clean-ups.
@@ -216,11 +250,6 @@ notes for details).
* "git checkout --recurse-submodules" did not quite work with a
submodule that itself has submodules.
- * Plug some leaks and updates internal API used to implement the
- split index feature to make it easier to avoid such a leak in the
- future.
- (merge de950c5773 nd/split-index-unshare later to maint).
-
* "pack-objects" can stream a slice of an existing packfile out when
the pack bitmap can tell that the reachable objects are all needed
in the output, without inspecting individual objects. This
@@ -282,7 +311,6 @@ notes for details).
they were almost never considered. Instead, give them about the
same chance to be considered as an annotated tag that is the same
age as the underlying commit would.
- (merge ef1e74065c jc/name-rev-lw-tag later to maint).
* The "run-command" API implementation has been made more robust
against dead-locking in a threaded environment.
@@ -308,7 +336,6 @@ notes for details).
$commit1:$path $commit2:$path", used to be shown with the full
object name as given on the command line, but it is more natural to
use the $path in the output and use it to look up .gitattributes.
- (merge 30d005c020 jk/diff-blob later to maint).
* The "collision detecting" SHA-1 implementation shipped with 2.13
was quite broken on some big-endian platforms and/or platforms that
@@ -329,7 +356,6 @@ notes for details).
fast-forwards to the upstream.
* A flaky test has been corrected.
- (merge 7c2115aa07 jk/pack-idx-corruption-safety later to maint).
* "git $cmd -h" for builtin commands calls the implementation of the
command (i.e. cmd_$cmd() function) without doing any repository
@@ -337,6 +363,60 @@ notes for details).
potty needs to be prepared to show the help text without barfing.
(merge d691551192 jk/consistent-h later to maint).
+ * Help contributors that visit us at GitHub.
+
+ * "git stash push <pathspec>" did not work from a subdirectory at all.
+ Bugfix for a topic in v2.13
+
+ * As there is no portable way to pass timezone information to
+ strftime, some output format from "git log" and friends are
+ impossible to produce. Teach our own strbuf_addftime to replace %z
+ and %Z with caller-supplied values to help working around this.
+ (merge 6eced3ec5e rs/strbuf-addftime-zZ later to maint).
+
+ * "git mergetool" learned to work around a wrapper MacOS X adds
+ around underlying meld.
+ (merge 0af85f84bd da/mergetools-meld-output-opt-on-macos later to maint).
+
+ * An example in documentation that does not work in multi worktree
+ configuration has been corrected.
+ (merge 773a88914f ah/doc-gitattributes-empty-index later to maint).
+
+ * The pretty-format specifiers like '%h', '%t', etc. had an
+ optimization that no longer works correctly. In preparation/hope
+ of getting it correctly implemented, first discard the optimization
+ that is broken.
+ (merge fe9e2aefd4 rs/pretty-add-again later to maint).
+
+ * The code to pick up and execute command alias definition from the
+ configuration used to switch to the top of the working tree and
+ then come back when the expanded alias was executed, which was
+ unnecessarilyl complex. Attempt to simplify the logic by using the
+ early-config mechanism that does not chdir around.
+ (merge a9bcf6586d js/alias-early-config later to maint).
+
+ * Fix configuration codepath to pay proper attention to commondir
+ that is used in multi-worktree situation, and isolate config API
+ into its own header file.
+ (merge dc8441fdb4 bw/config-h later to maint).
+
+ * "git add -p" were updated in 2.12 timeframe to cope with custom
+ core.commentchar but the implementation was buggy and a
+ metacharacter like $ and * did not work.
+ (merge d85d7ecb80 jk/add-p-commentchar-fix later to maint).
+
+ * A recent regression in "git rebase -i" has been fixed and tests
+ that would have caught it and others have been added.
+ (merge adf16c08cb pw/rebase-i-regression-fix-tests later to maint).
+
+ * An unaligned 32-bit access in pack-bitmap code ahs been corrected.
+ (merge da41c942b3 jc/pack-bitmap-unaligned later to maint).
+
+ * Tighten error checks for invalid "git apply" input.
+ (merge d70e9c5c8c rs/apply-validate-input later to maint).
+
* Other minor doc, test and build updates and code cleanups.
- (merge 8ba74bfd7c jc/diff-tree-stale-comment later to maint).
- (merge 68602c01fd sb/submodule-rm-absorb later to maint).
+ (merge 68241cb9dd sb/t4005-modernize later to maint).
+ (merge 4fced24712 ks/t7508-indent-fix later to maint).
+ (merge 968b1fe263 mb/reword-autocomplete-message later to maint).
+ (merge 8592c95cdf ah/doc-pretty-color-auto-prefix later to maint).
diff --git a/Documentation/config.txt b/Documentation/config.txt
index f6278a5ae6..06898a7498 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -348,6 +348,9 @@ advice.*::
rmHints::
In case of failure in the output of linkgit:git-rm[1],
show directions on how to proceed from the current state.
+ addEmbeddedRepo::
+ Advice on what to do when you've accidentally added one
+ git repo inside of another.
--
core.fileMode::
@@ -683,7 +686,8 @@ core.packedGitLimit::
bytes at once to complete an operation it will unmap existing
regions to reclaim virtual address space within the process.
+
-Default is 256 MiB on 32 bit platforms and 8 GiB on 64 bit platforms.
+Default is 256 MiB on 32 bit platforms and 32 TiB (effectively
+unlimited) on 64 bit platforms.
This should be reasonable for all users/operating systems, except on
the largest projects. You probably do not need to adjust this value.
+
@@ -2620,7 +2624,7 @@ rebase.autoSquash::
If set to true enable `--autosquash` option by default.
rebase.autoStash::
- When set to true, automatically create a temporary stash
+ When set to true, automatically create a temporary stash entry
before the operation begins, and apply it after the operation
ends. This means that you can run rebase on a dirty worktree.
However, use with care: the final stash application after a
@@ -2992,6 +2996,11 @@ status.displayCommentPrefix::
behavior of linkgit:git-status[1] in Git 1.8.4 and previous.
Defaults to false.
+status.showStash::
+ If set to true, linkgit:git-status[1] will display the number of
+ entries currently stashed away.
+ Defaults to false.
+
status.showUntrackedFiles::
By default, linkgit:git-status[1] and linkgit:git-commit[1] show
files which are not currently tracked by Git. Directories which
@@ -3029,12 +3038,12 @@ status.submoduleSummary::
stash.showPatch::
If this is set to true, the `git stash show` command without an
- option will show the stash in patch form. Defaults to false.
+ option will show the stash entry in patch form. Defaults to false.
See description of 'show' command in linkgit:git-stash[1].
stash.showStat::
If this is set to true, the `git stash show` command without an
- option will show diffstat of the stash. Defaults to true.
+ option will show diffstat of the stash entry. Defaults to true.
See description of 'show' command in linkgit:git-stash[1].
submodule.<name>.url::
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 7ed63dce0b..f4169fb1ec 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -165,6 +165,13 @@ for "git add --no-all <pathspec>...", i.e. ignored removed files.
be ignored, no matter if they are already present in the work
tree or not.
+--no-warn-embedded-repo::
+ By default, `git add` will warn when adding an embedded
+ repository to the index without using `git submodule add` to
+ create an entry in `.gitmodules`. This option will suppress the
+ warning (e.g., if you are manually performing operations on
+ submodules).
+
--chmod=(+|-)x::
Override the executable bit of the added files. The executable
bit is only changed in the index, the files on disk are left
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 2b762654bf..3d3d219e58 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -121,7 +121,7 @@ Performance and Compression Tuning
--depth=<n>::
Maximum delta depth, for blob and tree deltification.
- Default is 10.
+ Default is 50.
--export-pack-edges=<file>::
After creating a packfile, print a line of data to
diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt
index 7b695dbb72..9e5169aa64 100644
--- a/Documentation/git-filter-branch.txt
+++ b/Documentation/git-filter-branch.txt
@@ -8,11 +8,11 @@ git-filter-branch - Rewrite branches
SYNOPSIS
--------
[verse]
-'git filter-branch' [--env-filter <command>] [--tree-filter <command>]
- [--index-filter <command>] [--parent-filter <command>]
- [--msg-filter <command>] [--commit-filter <command>]
- [--tag-name-filter <command>] [--subdirectory-filter <directory>]
- [--prune-empty]
+'git filter-branch' [--setup <command>] [--env-filter <command>]
+ [--tree-filter <command>] [--index-filter <command>]
+ [--parent-filter <command>] [--msg-filter <command>]
+ [--commit-filter <command>] [--tag-name-filter <command>]
+ [--subdirectory-filter <directory>] [--prune-empty]
[--original <namespace>] [-d <directory>] [-f | --force]
[--] [<rev-list options>...]
@@ -82,6 +82,13 @@ multiple commits.
OPTIONS
-------
+--setup <command>::
+ This is not a real filter executed for each commit but a one
+ time setup just before the loop. Therefore no commit-specific
+ variables are defined yet. Functions or variables defined here
+ can be used or modified in the following filter steps except
+ the commit filter, for technical reasons.
+
--env-filter <command>::
This filter may be used if you only need to modify the environment
in which the commit will be performed. Specifically, you might
diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt
index e414185f5a..9db5e08f4a 100644
--- a/Documentation/git-pull.txt
+++ b/Documentation/git-pull.txt
@@ -131,7 +131,7 @@ unless you have read linkgit:git-rebase[1] carefully.
--autostash::
--no-autostash::
Before starting rebase, stash local modifications away (see
- linkgit:git-stash[1]) if needed, and apply the stash when
+ linkgit:git-stash[1]) if needed, and apply the stash entry when
done. `--no-autostash` is useful to override the `rebase.autoStash`
configuration variable (see linkgit:git-config[1]).
+
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 53f4e14444..a5afd602d8 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -446,7 +446,7 @@ used to override and disable this setting.
--autostash::
--no-autostash::
- Automatically create a temporary stash before the operation
+ Automatically create a temporary stash entry before the operation
begins, and apply it after the operation ends. This means
that you can run rebase on a dirty worktree. However, use
with care: the final stash application after a successful
diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt
index 8a21198d65..1d697d9962 100644
--- a/Documentation/git-reset.txt
+++ b/Documentation/git-reset.txt
@@ -115,7 +115,7 @@ $ git pull git://info.example.com/ nitfol <4>
in these files are in good order. You do not want to see them
when you run "git diff", because you plan to work on other files
and changes with these files are distracting.
-<2> Somebody asks you to pull, and the changes sounds worthy of merging.
+<2> Somebody asks you to pull, and the changes sound worthy of merging.
<3> However, you already dirtied the index (i.e. your index does
not match the HEAD commit). But you know the pull you are going
to make does not affect frotz.c or filfre.c, so you revert the
@@ -294,7 +294,7 @@ $ git reset --keep start <3>
Split a commit apart into a sequence of commits::
+
-Suppose that you have created lots of logically separate changes and commited
+Suppose that you have created lots of logically separate changes and committed
them together. Then, later you decide that it might be better to have each
logical chunk associated with its own commit. You can use git reset to rewind
history without changing the contents of your local files, and then successively
diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index 70191d06b6..00f95fee1f 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -51,18 +51,18 @@ OPTIONS
save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]::
push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-m|--message <message>] [--] [<pathspec>...]::
- Save your local modifications to a new 'stash' and roll them
+ Save your local modifications to a new 'stash entry' and roll them
back to HEAD (in the working tree and in the index).
The <message> part is optional and gives
the description along with the stashed state.
+
For quickly making a snapshot, you can omit "push". In this mode,
non-option arguments are not allowed to prevent a misspelled
-subcommand from making an unwanted stash. The two exceptions to this
+subcommand from making an unwanted stash entry. The two exceptions to this
are `stash -p` which acts as alias for `stash push -p` and pathspecs,
which are allowed after a double hyphen `--` for disambiguation.
+
-When pathspec is given to 'git stash push', the new stash records the
+When pathspec is given to 'git stash push', the new stash entry records the
modified states only for the files that match the pathspec. The index
entries and working tree files are then rolled back to the state in
HEAD only for these files, too, leaving files that do not match the
@@ -89,10 +89,10 @@ The `--patch` option implies `--keep-index`. You can use
list [<options>]::
- List the stashes that you currently have. Each 'stash' is listed
- with its name (e.g. `stash@{0}` is the latest stash, `stash@{1}` is
+ List the stash entries that you currently have. Each 'stash entry' is
+ listed with its name (e.g. `stash@{0}` is the latest entry, `stash@{1}` is
the one before, etc.), the name of the branch that was current when the
- stash was made, and a short description of the commit the stash was
+ entry was made, and a short description of the commit the entry was
based on.
+
----------------------------------------------------------------
@@ -105,11 +105,12 @@ command to control what is shown and how. See linkgit:git-log[1].
show [<stash>]::
- Show the changes recorded in the stash as a diff between the
- stashed state and its original parent. When no `<stash>` is given,
- shows the latest one. By default, the command shows the diffstat, but
- it will accept any format known to 'git diff' (e.g., `git stash show
- -p stash@{1}` to view the second most recent stash in patch form).
+ Show the changes recorded in the stash entry as a diff between the
+ stashed contents and the commit back when the stash entry was first
+ created. When no `<stash>` is given, it shows the latest one.
+ By default, the command shows the diffstat, but it will accept any
+ format known to 'git diff' (e.g., `git stash show -p stash@{1}`
+ to view the second most recent entry in patch form).
You can use stash.showStat and/or stash.showPatch config variables
to change the default behavior.
@@ -149,26 +150,27 @@ branch <branchname> [<stash>]::
+
This is useful if the branch on which you ran `git stash save` has
changed enough that `git stash apply` fails due to conflicts. Since
-the stash is applied on top of the commit that was HEAD at the time
-`git stash` was run, it restores the originally stashed state with
-no conflicts.
+the stash entry is applied on top of the commit that was HEAD at the
+time `git stash` was run, it restores the originally stashed state
+with no conflicts.
clear::
- Remove all the stashed states. Note that those states will then
+ Remove all the stash entries. Note that those entries will then
be subject to pruning, and may be impossible to recover (see
'Examples' below for a possible strategy).
drop [-q|--quiet] [<stash>]::
- Remove a single stashed state from the stash list. When no `<stash>`
- is given, it removes the latest one. i.e. `stash@{0}`, otherwise
- `<stash>` must be a valid stash log reference of the form
- `stash@{<revision>}`.
+ Remove a single stash entry from the list of stash entries.
+ When no `<stash>` is given, it removes the latest one.
+ i.e. `stash@{0}`, otherwise `<stash>` must be a valid stash
+ log reference of the form `stash@{<revision>}`.
create::
- Create a stash (which is a regular commit object) and return its
- object name, without storing it anywhere in the ref namespace.
+ Create a stash entry (which is a regular commit object) and
+ return its object name, without storing it anywhere in the ref
+ namespace.
This is intended to be useful for scripts. It is probably not
the command you want to use; see "save" above.
@@ -182,10 +184,10 @@ store::
DISCUSSION
----------
-A stash is represented as a commit whose tree records the state of the
-working directory, and its first parent is the commit at `HEAD` when
-the stash was created. The tree of the second parent records the
-state of the index when the stash is made, and it is made a child of
+A stash entry is represented as a commit whose tree records the state
+of the working directory, and its first parent is the commit at `HEAD`
+when the entry was created. The tree of the second parent records the
+state of the index when the entry is made, and it is made a child of
the `HEAD` commit. The ancestry graph looks like this:
.----W
@@ -269,12 +271,12 @@ $ edit/build/test remaining parts
$ git commit foo -m 'Remaining parts'
----------------------------------------------------------------
-Recovering stashes that were cleared/dropped erroneously::
+Recovering stash entries that were cleared/dropped erroneously::
-If you mistakenly drop or clear stashes, they cannot be recovered
+If you mistakenly drop or clear stash entries, they cannot be recovered
through the normal safety mechanisms. However, you can try the
-following incantation to get a list of stashes that are still in your
-repository, but not reachable any more:
+following incantation to get a list of stash entries that are still in
+your repository, but not reachable any more:
+
----------------------------------------------------------------
git fsck --unreachable |
diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt
index d70abc6afe..d47f198f15 100644
--- a/Documentation/git-status.txt
+++ b/Documentation/git-status.txt
@@ -32,6 +32,9 @@ OPTIONS
--branch::
Show the branch and tracking info even in short-format.
+--show-stash::
+ Show the number of entries currently stashed away.
+
--porcelain[=<version>]::
Give the output in an easy-to-parse format for scripts.
This is similar to the short output, but will remain stable
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 74bc6200d5..b9a56d4c6e 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -63,14 +63,6 @@ add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--dep
to the changeset to be committed next to the current
project: the current project is termed the "superproject".
+
-This requires at least one argument: <repository>. The optional
-argument <path> is the relative location for the cloned submodule
-to exist in the superproject. If <path> is not given, the
-"humanish" part of the source repository is used ("repo" for
-"/path/to/repo.git" and "foo" for "host.xz:foo/.git").
-The <path> is also used as the submodule's logical name in its
-configuration entries unless `--name` is used to specify a logical name.
-+
<repository> is the URL of the new submodule's origin repository.
This may be either an absolute URL, or (if it begins with ./
or ../), the location relative to the superproject's default remote
@@ -87,21 +79,22 @@ If the superproject doesn't have a default remote configured
the superproject is its own authoritative upstream and the current
working directory is used instead.
+
-<path> is the relative location for the cloned submodule to
-exist in the superproject. If <path> does not exist, then the
-submodule is created by cloning from the named URL. If <path> does
-exist and is already a valid Git repository, then this is added
-to the changeset without cloning. This second form is provided
-to ease creating a new submodule from scratch, and presumes
-the user will later push the submodule to the given URL.
+The optional argument <path> is the relative location for the cloned
+submodule to exist in the superproject. If <path> is not given, the
+canonical part of the source repository is used ("repo" for
+"/path/to/repo.git" and "foo" for "host.xz:foo/.git"). If <path>
+exists and is already a valid Git repository, then it is staged
+for commit without cloning. The <path> is also used as the submodule's
+logical name in its configuration entries unless `--name` is used
+to specify a logical name.
+
-In either case, the given URL is recorded into .gitmodules for
-use by subsequent users cloning the superproject. If the URL is
-given relative to the superproject's repository, the presumption
-is the superproject and submodule repositories will be kept
-together in the same relative location, and only the
-superproject's URL needs to be provided: git-submodule will correctly
-locate the submodule using the relative URL in .gitmodules.
+The given URL is recorded into `.gitmodules` for use by subsequent users
+cloning the superproject. If the URL is given relative to the
+superproject's repository, the presumption is the superproject and
+submodule repositories will be kept together in the same relative
+location, and only the superproject's URL needs to be provided.
+git-submodule will correctly locate the submodule using the relative
+URL in `.gitmodules`.
status [--cached] [--recursive] [--] [<path>...]::
Show the status of the submodules. This will print the SHA-1 of the
@@ -123,7 +116,7 @@ too (and can also report changes to a submodule's work tree).
init [--] [<path>...]::
Initialize the submodules recorded in the index (which were
added and committed elsewhere) by setting `submodule.$name.url`
- in .git/config. It uses the same setting from .gitmodules as
+ in .git/config. It uses the same setting from `.gitmodules` as
a template. If the URL is relative, it will be resolved using
the default remote. If there is no default remote, the current
repository will be assumed to be upstream.
@@ -141,7 +134,7 @@ you can also just use `git submodule update --init` without
the explicit 'init' step if you do not intend to customize
any submodule locations.
+
-See the add subcommand for the defintion of default remote.
+See the add subcommand for the definition of default remote.
deinit [-f|--force] (--all|[--] <path>...)::
Unregister the given submodules, i.e. remove the whole
@@ -197,7 +190,7 @@ configuration variable:
none;; the submodule is not updated.
If the submodule is not yet initialized, and you just want to use the
-setting as stored in .gitmodules, you can automatically initialize the
+setting as stored in `.gitmodules`, you can automatically initialize the
submodule with the `--init` option.
If `--recursive` is specified, this command will recurse into the
@@ -220,7 +213,7 @@ foreach [--recursive] <command>::
Evaluates an arbitrary shell command in each checked out submodule.
The command has access to the variables $name, $path, $sha1 and
$toplevel:
- $name is the name of the relevant submodule section in .gitmodules,
+ $name is the name of the relevant submodule section in `.gitmodules`,
$path is the name of the submodule directory relative to the
superproject, $sha1 is the commit as recorded in the superproject,
and $toplevel is the absolute path to the top-level of the superproject.
@@ -242,7 +235,7 @@ git submodule foreach 'echo $path `git rev-parse HEAD`'
sync [--recursive] [--] [<path>...]::
Synchronizes submodules' remote URL configuration setting
- to the value specified in .gitmodules. It will only affect those
+ to the value specified in `.gitmodules`. It will only affect those
submodules which already have a URL entry in .git/config (that is the
case when they are initialized or freshly added). This is useful when
submodule URLs change upstream and you need to update your local
@@ -413,7 +406,7 @@ for linkgit:git-clone[1]'s `--reference` and `--shared` options carefully.
--[no-]recommend-shallow::
This option is only valid for the update command.
The initial clone of a submodule will use the recommended
- `submodule.<name>.shallow` as provided by the .gitmodules file
+ `submodule.<name>.shallow` as provided by the `.gitmodules` file
by default. To ignore the suggestions use `--no-recommend-shallow`.
-j <n>::
@@ -429,7 +422,7 @@ for linkgit:git-clone[1]'s `--reference` and `--shared` options carefully.
FILES
-----
-When initializing submodules, a .gitmodules file in the top-level directory
+When initializing submodules, a `.gitmodules` file in the top-level directory
of the containing repository is used to find the url of each submodule.
This file should be formatted in the same way as `$GIT_DIR/config`. The key
to each submodule url is "submodule.$name.url". See linkgit:gitmodules[5]
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index 4736483865..2a2d7e2a4d 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -229,7 +229,7 @@ From a clean working directory:
-------------------------------------------------
$ echo "* text=auto" >.gitattributes
-$ rm .git/index # Remove the index to re-scan the working directory
+$ git read-tree --empty # Clean index, force re-scan of working directory
$ git add .
$ git status # Show files that will be normalized
$ git commit -m "Introduce end-of-line normalization"
diff --git a/Documentation/gitcli.txt b/Documentation/gitcli.txt
index dfe7d83727..9f13266a68 100644
--- a/Documentation/gitcli.txt
+++ b/Documentation/gitcli.txt
@@ -194,7 +194,7 @@ different things.
* The `--index` option is used to ask a command that
usually works on files in the working tree to *also*
affect the index. For example, `git stash apply` usually
- merges changes recorded in a stash to the working tree,
+ merges changes recorded in a stash entry to the working tree,
but with the `--index` option, it also merges changes to
the index as well.
diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt
index 6e991c2469..b71b943b12 100644
--- a/Documentation/glossary-content.txt
+++ b/Documentation/glossary-content.txt
@@ -570,6 +570,10 @@ The most notable example is `HEAD`.
is created by giving the `--depth` option to linkgit:git-clone[1], and
its history can be later deepened with linkgit:git-fetch[1].
+[[def_stash]]stash entry::
+ An <<def_object,object>> used to temporarily store the contents of a
+ <<def_dirty,dirty>> working directory and the index for future reuse.
+
[[def_submodule]]submodule::
A <<def_repository,repository>> that holds the history of a
separate project inside another repository (the latter of
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index 38040e95b5..4d6dac5770 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -174,11 +174,12 @@ endif::git-rev-list[]
- '%Creset': reset color
- '%C(...)': color specification, as described under Values in the
"CONFIGURATION FILE" section of linkgit:git-config[1];
- adding `auto,` at the beginning will emit color only when colors are
- enabled for log output (by `color.diff`, `color.ui`, or `--color`, and
- respecting the `auto` settings of the former if we are going to a
- terminal). `auto` alone (i.e. `%C(auto)`) will turn on auto coloring
- on the next placeholders until the color is switched again.
+ adding `auto,` at the beginning (e.g. `%C(auto,red)`) will emit
+ color only when colors are enabled for log output (by `color.diff`,
+ `color.ui`, or `--color`, and respecting the `auto` settings of the
+ former if we are going to a terminal). `auto` alone (i.e.
+ `%C(auto)`) will turn on auto coloring on the next placeholders
+ until the color is switched again.
- '%m': left (`<`), right (`>`) or boundary (`-`) mark
- '%n': newline
- '%%': a raw '%'
@@ -213,8 +214,8 @@ If you add a `+` (plus sign) after '%' of a placeholder, a line-feed
is inserted immediately before the expansion if and only if the
placeholder expands to a non-empty string.
-If you add a `-` (minus sign) after '%' of a placeholder, line-feeds that
-immediately precede the expansion are deleted if and only if the
+If you add a `-` (minus sign) after '%' of a placeholder, all consecutive
+line-feeds immediately preceding the expansion are deleted if and only if the
placeholder expands to an empty string.
If you add a ` ` (space) after '%' of a placeholder, a space
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index 9c44eae55d..a6cf9eb380 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -769,7 +769,8 @@ timezone value.
1970). As with `--raw`, this is always in UTC and therefore `-local`
has no effect.
+
-`--date=format:...` feeds the format `...` to your system `strftime`.
+`--date=format:...` feeds the format `...` to your system `strftime`,
+except for %z and %Z, which are handled internally.
Use `--date=format:%c` to show the date in your system locale's
preferred format. See the `strftime` manual for a complete list of
format placeholders. When using `-local`, the correct syntax is
diff --git a/Makefile b/Makefile
index 32e4efc710..9c9c42f8f9 100644
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,8 @@ all::
# have been written to the final string if enough space had been available.
#
# Define FREAD_READS_DIRECTORIES if you are on a system which succeeds
-# when attempting to read from an fopen'ed directory.
+# when attempting to read from an fopen'ed directory (or even to fopen
+# it at all).
#
# Define NO_OPENSSL environment variable if you do not have OpenSSL.
# This also implies BLK_SHA1.
diff --git a/abspath.c b/abspath.c
index 7f1cfe9792..708aff8d42 100644
--- a/abspath.c
+++ b/abspath.c
@@ -183,7 +183,7 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
/*
* use the symlink as the remaining components that
- * need to be resloved
+ * need to be resolved
*/
strbuf_swap(&symlink, &remaining);
}
diff --git a/advice.c b/advice.c
index 3fa04fca0b..d81e1cb742 100644
--- a/advice.c
+++ b/advice.c
@@ -16,6 +16,7 @@ int advice_detached_head = 1;
int advice_set_upstream_failure = 1;
int advice_object_name_warning = 1;
int advice_rm_hints = 1;
+int advice_add_embedded_repo = 1;
static struct {
const char *name;
@@ -36,6 +37,7 @@ static struct {
{ "setupstreamfailure", &advice_set_upstream_failure },
{ "objectnamewarning", &advice_object_name_warning },
{ "rmhints", &advice_rm_hints },
+ { "addembeddedrepo", &advice_add_embedded_repo },
/* make this an alias for backward compatibility */
{ "pushnonfastforward", &advice_push_update_rejected }
diff --git a/advice.h b/advice.h
index b341a55ce7..c84a44531c 100644
--- a/advice.h
+++ b/advice.h
@@ -18,6 +18,7 @@ extern int advice_detached_head;
extern int advice_set_upstream_failure;
extern int advice_object_name_warning;
extern int advice_rm_hints;
+extern int advice_add_embedded_repo;
int git_default_advice_config(const char *var, const char *value);
__attribute__((format (printf, 1, 2)))
diff --git a/alias.c b/alias.c
index de8e6a3f49..39f622e414 100644
--- a/alias.c
+++ b/alias.c
@@ -62,8 +62,7 @@ int split_cmdline(char *cmdline, const char ***argv)
src++;
c = cmdline[src];
if (!c) {
- free(*argv);
- *argv = NULL;
+ FREE_AND_NULL(*argv);
return -SPLIT_CMDLINE_BAD_ENDING;
}
}
@@ -75,8 +74,7 @@ int split_cmdline(char *cmdline, const char ***argv)
cmdline[dst] = 0;
if (quoted) {
- free(*argv);
- *argv = NULL;
+ FREE_AND_NULL(*argv);
return -SPLIT_CMDLINE_UNCLOSED_QUOTE;
}
diff --git a/apply.c b/apply.c
index 65063785c1..c442b89328 100644
--- a/apply.c
+++ b/apply.c
@@ -211,6 +211,7 @@ struct patch {
unsigned ws_rule;
int lines_added, lines_deleted;
int score;
+ int extension_linenr; /* first line specifying delete/new/rename/copy */
unsigned int is_toplevel_relative:1;
unsigned int inaccurate_eof:1;
unsigned int is_binary:1;
@@ -763,17 +764,6 @@ static char *find_name_traditional(struct apply_state *state,
return find_name_common(state, line, def, p_value, line + len, 0);
}
-static int count_slashes(const char *cp)
-{
- int cnt = 0;
- char ch;
-
- while ((ch = *cp++))
- if (ch == '/')
- cnt++;
- return cnt;
-}
-
/*
* Given the string after "--- " or "+++ ", guess the appropriate
* p_value for the given patch.
@@ -1012,20 +1002,27 @@ static int gitdiff_newname(struct apply_state *state,
DIFF_NEW_NAME);
}
+static int parse_mode_line(const char *line, int linenr, unsigned int *mode)
+{
+ char *end;
+ *mode = strtoul(line, &end, 8);
+ if (end == line || !isspace(*end))
+ return error(_("invalid mode on line %d: %s"), linenr, line);
+ return 0;
+}
+
static int gitdiff_oldmode(struct apply_state *state,
const char *line,
struct patch *patch)
{
- patch->old_mode = strtoul(line, NULL, 8);
- return 0;
+ return parse_mode_line(line, state->linenr, &patch->old_mode);
}
static int gitdiff_newmode(struct apply_state *state,
const char *line,
struct patch *patch)
{
- patch->new_mode = strtoul(line, NULL, 8);
- return 0;
+ return parse_mode_line(line, state->linenr, &patch->new_mode);
}
static int gitdiff_delete(struct apply_state *state,
@@ -1139,7 +1136,7 @@ static int gitdiff_index(struct apply_state *state,
memcpy(patch->new_sha1_prefix, line, len);
patch->new_sha1_prefix[len] = 0;
if (*ptr == ' ')
- patch->old_mode = strtoul(ptr+1, NULL, 8);
+ return gitdiff_oldmode(state, ptr + 1, patch);
return 0;
}
@@ -1323,6 +1320,18 @@ static char *git_header_name(struct apply_state *state,
}
}
+static int check_header_line(struct apply_state *state, struct patch *patch)
+{
+ int extensions = (patch->is_delete == 1) + (patch->is_new == 1) +
+ (patch->is_rename == 1) + (patch->is_copy == 1);
+ if (extensions > 1)
+ return error(_("inconsistent header lines %d and %d"),
+ patch->extension_linenr, state->linenr);
+ if (extensions && !patch->extension_linenr)
+ patch->extension_linenr = state->linenr;
+ return 0;
+}
+
/* Verify that we recognize the lines following a git header */
static int parse_git_header(struct apply_state *state,
const char *line,
@@ -1389,6 +1398,8 @@ static int parse_git_header(struct apply_state *state,
res = p->fn(state, line + oplen, patch);
if (res < 0)
return -1;
+ if (check_header_line(state, patch))
+ return -1;
if (res > 0)
return offset;
break;
@@ -1586,7 +1597,8 @@ static int find_header(struct apply_state *state,
patch->old_name = xstrdup(patch->def_name);
patch->new_name = xstrdup(patch->def_name);
}
- if (!patch->is_delete && !patch->new_name) {
+ if ((!patch->new_name && !patch->is_delete) ||
+ (!patch->old_name && !patch->is_new)) {
error(_("git diff header lacks filename information "
"(line %d)"), state->linenr);
return -128;
@@ -3706,8 +3718,7 @@ static int check_preimage(struct apply_state *state,
is_new:
patch->is_new = 1;
patch->is_delete = 0;
- free(patch->old_name);
- patch->old_name = NULL;
+ FREE_AND_NULL(patch->old_name);
return 0;
}
diff --git a/attr.c b/attr.c
index 6e4b247acd..37454999d2 100644
--- a/attr.c
+++ b/attr.c
@@ -639,13 +639,11 @@ void attr_check_reset(struct attr_check *check)
void attr_check_clear(struct attr_check *check)
{
- free(check->items);
- check->items = NULL;
+ FREE_AND_NULL(check->items);
check->alloc = 0;
check->nr = 0;
- free(check->all_attrs);
- check->all_attrs = NULL;
+ FREE_AND_NULL(check->all_attrs);
check->all_attrs_nr = 0;
drop_attr_stack(&check->stack);
diff --git a/blame.c b/blame.c
index 6d57ab9715..91e26e93e8 100644
--- a/blame.c
+++ b/blame.c
@@ -314,8 +314,7 @@ static void fill_origin_blob(struct diff_options *opt,
static void drop_origin_blob(struct blame_origin *o)
{
if (o->file.ptr) {
- free(o->file.ptr);
- o->file.ptr = NULL;
+ FREE_AND_NULL(o->file.ptr);
}
}
diff --git a/branch.c b/branch.c
index a8a548ccf2..36541d05cd 100644
--- a/branch.c
+++ b/branch.c
@@ -25,8 +25,7 @@ static int find_tracked_branch(struct remote *remote, void *priv)
} else {
free(tracking->spec.src);
if (tracking->src) {
- free(tracking->src);
- tracking->src = NULL;
+ FREE_AND_NULL(tracking->src);
}
}
tracking->spec.src = NULL;
diff --git a/builtin/add.c b/builtin/add.c
index f2415e99f3..e888fb8c5f 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -250,6 +250,7 @@ N_("The following paths are ignored by one of your .gitignore files:\n");
static int verbose, show_only, ignored_too, refresh_only;
static int ignore_add_errors, intent_to_add, ignore_missing;
+static int warn_on_embedded_repo = 1;
#define ADDREMOVE_DEFAULT 1
static int addremove = ADDREMOVE_DEFAULT;
@@ -283,6 +284,8 @@ static struct option builtin_add_options[] = {
OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
OPT_STRING( 0 , "chmod", &chmod_arg, N_("(+/-)x"), N_("override the executable bit of the listed files")),
+ OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo,
+ N_("warn when adding an embedded repository")),
OPT_END(),
};
@@ -296,6 +299,45 @@ static int add_config(const char *var, const char *value, void *cb)
return git_default_config(var, value, cb);
}
+static const char embedded_advice[] = N_(
+"You've added another git repository inside your current repository.\n"
+"Clones of the outer repository will not contain the contents of\n"
+"the embedded repository and will not know how to obtain it.\n"
+"If you meant to add a submodule, use:\n"
+"\n"
+" git submodule add <url> %s\n"
+"\n"
+"If you added this path by mistake, you can remove it from the\n"
+"index with:\n"
+"\n"
+" git rm --cached %s\n"
+"\n"
+"See \"git help submodule\" for more information."
+);
+
+static void check_embedded_repo(const char *path)
+{
+ struct strbuf name = STRBUF_INIT;
+
+ if (!warn_on_embedded_repo)
+ return;
+ if (!ends_with(path, "/"))
+ return;
+
+ /* Drop trailing slash for aesthetics */
+ strbuf_addstr(&name, path);
+ strbuf_strip_suffix(&name, "/");
+
+ warning(_("adding embedded git repository: %s"), name.buf);
+ if (advice_add_embedded_repo) {
+ advise(embedded_advice, name.buf, name.buf);
+ /* there may be multiple entries; advise only once */
+ advice_add_embedded_repo = 0;
+ }
+
+ strbuf_release(&name);
+}
+
static int add_files(struct dir_struct *dir, int flags)
{
int i, exit_status = 0;
@@ -308,12 +350,14 @@ static int add_files(struct dir_struct *dir, int flags)
exit_status = 1;
}
- for (i = 0; i < dir->nr; i++)
+ for (i = 0; i < dir->nr; i++) {
+ check_embedded_repo(dir->entries[i]->name);
if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
if (!ignore_add_errors)
die(_("adding files failed"));
exit_status = 1;
}
+ }
return exit_status;
}
diff --git a/builtin/am.c b/builtin/am.c
index 7c7b916d23..c973bd96dc 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -484,8 +484,7 @@ static int run_applypatch_msg_hook(struct am_state *state)
ret = run_hook_le(NULL, "applypatch-msg", am_path(state, "final-commit"), NULL);
if (!ret) {
- free(state->msg);
- state->msg = NULL;
+ FREE_AND_NULL(state->msg);
if (read_commit_msg(state) < 0)
die(_("'%s' was deleted by the applypatch-msg hook"),
am_path(state, "final-commit"));
@@ -1074,17 +1073,10 @@ static void am_next(struct am_state *state)
{
struct object_id head;
- free(state->author_name);
- state->author_name = NULL;
-
- free(state->author_email);
- state->author_email = NULL;
-
- free(state->author_date);
- state->author_date = NULL;
-
- free(state->msg);
- state->msg = NULL;
+ FREE_AND_NULL(state->author_name);
+ FREE_AND_NULL(state->author_email);
+ FREE_AND_NULL(state->author_date);
+ FREE_AND_NULL(state->msg);
state->msg_len = 0;
unlink(am_path(state, "author-script"));
diff --git a/builtin/clean.c b/builtin/clean.c
index ed954134d2..057fc97fe4 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -838,8 +838,7 @@ static void interactive_main_loop(void)
int ret;
ret = menus[*chosen].fn();
if (ret != MENU_RETURN_NO_LOOP) {
- free(chosen);
- chosen = NULL;
+ FREE_AND_NULL(chosen);
if (!del_list.nr) {
clean_print_color(CLEAN_COLOR_ERROR);
printf_ln(_("No more files to clean, exiting."));
@@ -852,8 +851,7 @@ static void interactive_main_loop(void)
quit_cmd();
}
- free(chosen);
- chosen = NULL;
+ FREE_AND_NULL(chosen);
break;
}
}
diff --git a/builtin/commit.c b/builtin/commit.c
index 021070e693..03b97c6449 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1297,6 +1297,10 @@ static int git_status_config(const char *k, const char *v, void *cb)
status_deferred_config.show_branch = git_config_bool(k, v);
return 0;
}
+ if (!strcmp(k, "status.showstash")) {
+ s->show_stash = git_config_bool(k, v);
+ return 0;
+ }
if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) {
s->use_color = git_config_colorbool(k, v);
return 0;
@@ -1345,6 +1349,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)
N_("show status concisely"), STATUS_FORMAT_SHORT),
OPT_BOOL('b', "branch", &s.show_branch,
N_("show branch information")),
+ OPT_BOOL(0, "show-stash", &s.show_stash,
+ N_("show stash information")),
{ OPTION_CALLBACK, 0, "porcelain", &status_format,
N_("version"), N_("machine-readable output"),
PARSE_OPT_OPTARG, opt_parse_porcelain },
@@ -1654,6 +1660,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
usage_with_options(builtin_commit_usage, builtin_commit_options);
status_init_config(&s, git_commit_config);
+ s.commit_template = 1;
status_format = STATUS_FORMAT_NONE; /* Ignore status.short */
s.colopts = 0;
diff --git a/builtin/config.c b/builtin/config.c
index 82db29fae7..70ff231e9c 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -215,8 +215,7 @@ static int get_value(const char *key_, const char *regex_)
key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
if (regcomp(key_regexp, key, REG_EXTENDED)) {
error("invalid key pattern: %s", key_);
- free(key_regexp);
- key_regexp = NULL;
+ FREE_AND_NULL(key_regexp);
ret = CONFIG_INVALID_PATTERN;
goto free_strings;
}
@@ -236,8 +235,7 @@ static int get_value(const char *key_, const char *regex_)
regexp = (regex_t*)xmalloc(sizeof(regex_t));
if (regcomp(regexp, regex_, REG_EXTENDED)) {
error("invalid pattern: %s", regex_);
- free(regexp);
- regexp = NULL;
+ FREE_AND_NULL(regexp);
ret = CONFIG_INVALID_PATTERN;
goto free_strings;
}
diff --git a/builtin/grep.c b/builtin/grep.c
index e3ba1d98e3..fa351c49f4 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -648,7 +648,7 @@ static int grep_submodule(struct grep_opt *opt, const struct object_id *oid,
return 0;
if (!is_submodule_populated_gently(path, NULL)) {
/*
- * If searching history, check for the presense of the
+ * If searching history, check for the presence of the
* submodule's gitdir before skipping the submodule.
*/
if (oid) {
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index edc1a91d89..ad4de35178 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -389,8 +389,7 @@ static struct base_data *alloc_base_data(void)
static void free_base_data(struct base_data *c)
{
if (c->data) {
- free(c->data);
- c->data = NULL;
+ FREE_AND_NULL(c->data);
get_thread_data()->base_cache_used -= c->size;
}
}
@@ -606,8 +605,7 @@ static void *unpack_data(struct object_entry *obj,
git_inflate_end(&stream);
free(inbuf);
if (consume) {
- free(data);
- data = NULL;
+ FREE_AND_NULL(data);
}
return data;
}
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index d5e96ed2d0..f4a8441fe9 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -265,8 +265,7 @@ static unsigned long write_no_reuse_object(struct sha1file *f, struct object_ent
* make sure no cached delta data remains from a
* previous attempt before a pack split occurred.
*/
- free(entry->delta_data);
- entry->delta_data = NULL;
+ FREE_AND_NULL(entry->delta_data);
entry->z_delta_size = 0;
} else if (entry->delta_data) {
size = entry->delta_size;
@@ -1376,12 +1375,10 @@ static void cleanup_preferred_base(void)
if (!pbase_tree_cache[i])
continue;
free(pbase_tree_cache[i]->tree_data);
- free(pbase_tree_cache[i]);
- pbase_tree_cache[i] = NULL;
+ FREE_AND_NULL(pbase_tree_cache[i]);
}
- free(done_pbase_paths);
- done_pbase_paths = NULL;
+ FREE_AND_NULL(done_pbase_paths);
done_pbase_paths_num = done_pbase_paths_alloc = 0;
}
@@ -1971,8 +1968,7 @@ static unsigned long free_unpacked(struct unpacked *n)
n->index = NULL;
if (n->data) {
freed_mem += n->entry->size;
- free(n->data);
- n->data = NULL;
+ FREE_AND_NULL(n->data);
}
n->entry = NULL;
n->depth = 0;
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index e4cf1b5bb2..527f69e283 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -6,6 +6,7 @@
#include "color.h"
#include "argv-array.h"
#include "parse-options.h"
+#include "dir.h"
static const char* show_branch_usage[] = {
N_("git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]\n"
@@ -422,14 +423,6 @@ static int append_tag_ref(const char *refname, const struct object_id *oid,
static const char *match_ref_pattern = NULL;
static int match_ref_slash = 0;
-static int count_slash(const char *s)
-{
- int cnt = 0;
- while (*s)
- if (*s++ == '/')
- cnt++;
- return cnt;
-}
static int append_matching_ref(const char *refname, const struct object_id *oid,
int flag, void *cb_data)
@@ -439,7 +432,7 @@ static int append_matching_ref(const char *refname, const struct object_id *oid,
* refs/tags/v0.99.9a and friends.
*/
const char *tail;
- int slash = count_slash(refname);
+ int slash = count_slashes(refname);
for (tail = refname; *tail && match_ref_slash < slash; )
if (*tail++ == '/')
slash--;
@@ -530,7 +523,7 @@ static void append_one_rev(const char *av)
int saved_matches = ref_name_cnt;
match_ref_pattern = av;
- match_ref_slash = count_slash(av);
+ match_ref_slash = count_slashes(av);
for_each_ref(append_matching_ref, NULL);
if (saved_matches == ref_name_cnt &&
ref_name_cnt < MAX_REVS)
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 193f8b9d57..689a29fac1 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -113,8 +113,7 @@ static void *get_data(unsigned long size)
break;
if (ret != Z_OK) {
error("inflate returned %d", ret);
- free(buf);
- buf = NULL;
+ FREE_AND_NULL(buf);
if (!recover)
exit(1);
has_errors = 1;
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 0c5476ee9d..c98e2ce5f5 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -300,10 +300,8 @@ static int add_worktree(const char *path, const char *refname,
}
is_junk = 0;
- free(junk_work_tree);
- free(junk_git_dir);
- junk_work_tree = NULL;
- junk_git_dir = NULL;
+ FREE_AND_NULL(junk_work_tree);
+ FREE_AND_NULL(junk_git_dir);
done:
if (ret || !opts->keep_locked) {
diff --git a/commit-slab.h b/commit-slab.h
index 42d16dcded..333d81e370 100644
--- a/commit-slab.h
+++ b/commit-slab.h
@@ -82,8 +82,7 @@ static MAYBE_UNUSED void clear_ ##slabname(struct slabname *s) \
for (i = 0; i < s->slab_count; i++) \
free(s->slab[i]); \
s->slab_count = 0; \
- free(s->slab); \
- s->slab = NULL; \
+ FREE_AND_NULL(s->slab); \
} \
\
static MAYBE_UNUSED elemtype *slabname## _at_peek(struct slabname *s, \
diff --git a/commit.c b/commit.c
index 99846d9bf4..cbfd689939 100644
--- a/commit.c
+++ b/commit.c
@@ -287,8 +287,7 @@ void free_commit_buffer(struct commit *commit)
{
struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit);
if (v) {
- free(v->buffer);
- v->buffer = NULL;
+ FREE_AND_NULL(v->buffer);
v->size = 0;
}
}
diff --git a/compat/regex/regexec.c b/compat/regex/regexec.c
index eb5e1d4439..0a745d9c3b 100644
--- a/compat/regex/regexec.c
+++ b/compat/regex/regexec.c
@@ -4102,7 +4102,7 @@ extend_buffers (re_match_context_t *mctx)
if (BE (INT_MAX / 2 / sizeof (re_dfastate_t *) <= pstr->bufs_len, 0))
return REG_ESPACE;
- /* Double the lengthes of the buffers. */
+ /* Double the lengths of the buffers. */
ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
if (BE (ret != REG_NOERROR, 0))
return ret;
diff --git a/config.c b/config.c
index be1c640a4c..4638b0696a 100644
--- a/config.c
+++ b/config.c
@@ -388,8 +388,7 @@ static int git_config_parse_key_1(const char *key, char **store_key, int *basele
out_free_ret_1:
if (store_key) {
- free(*store_key);
- *store_key = NULL;
+ FREE_AND_NULL(*store_key);
}
return -CONFIG_INVALID_KEY;
}
diff --git a/configure.ac b/configure.ac
index 11d083fbe0..2f55237e65 100644
--- a/configure.ac
+++ b/configure.ac
@@ -922,9 +922,9 @@ AC_CACHE_CHECK([whether system succeeds to read fopen'ed directory],
[
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
- [[char c;
+ [[
FILE *f = fopen(".", "r");
- return f && fread(&c, 1, 1, f)]])],
+ return f)]])],
[ac_cv_fread_reads_directories=no],
[ac_cv_fread_reads_directories=yes])
])
diff --git a/contrib/coccinelle/free.cocci b/contrib/coccinelle/free.cocci
index c03ba737e5..f2d97e755b 100644
--- a/contrib/coccinelle/free.cocci
+++ b/contrib/coccinelle/free.cocci
@@ -9,3 +9,18 @@ expression E;
@@
- if (!E)
free(E);
+
+@@
+type T;
+T *ptr;
+@@
+- free(ptr);
+- ptr = NULL;
++ FREE_AND_NULL(ptr);
+
+@@
+expression E;
+@@
+- free(E);
+- E = NULL;
++ FREE_AND_NULL(E);
diff --git a/contrib/diff-highlight/.gitignore b/contrib/diff-highlight/.gitignore
new file mode 100644
index 0000000000..c07454824e
--- /dev/null
+++ b/contrib/diff-highlight/.gitignore
@@ -0,0 +1,2 @@
+shebang.perl
+diff-highlight
diff --git a/contrib/diff-highlight/diff-highlight b/contrib/diff-highlight/DiffHighlight.pm
index 81bd8040e3..663992e530 100755..100644
--- a/contrib/diff-highlight/diff-highlight
+++ b/contrib/diff-highlight/DiffHighlight.pm
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+package DiffHighlight;
use 5.008;
use warnings FATAL => 'all';
@@ -29,13 +29,14 @@ my @removed;
my @added;
my $in_hunk;
-# Some scripts may not realize that SIGPIPE is being ignored when launching the
-# pager--for instance scripts written in Python.
-$SIG{PIPE} = 'DEFAULT';
+our $line_cb = sub { print @_ };
+our $flush_cb = sub { local $| = 1 };
+
+sub handle_line {
+ local $_ = shift;
-while (<>) {
if (!$in_hunk) {
- print;
+ $line_cb->($_);
$in_hunk = /^$GRAPH*$COLOR*\@\@ /;
}
elsif (/^$GRAPH*$COLOR*-/) {
@@ -49,7 +50,7 @@ while (<>) {
@removed = ();
@added = ();
- print;
+ $line_cb->($_);
$in_hunk = /^$GRAPH*$COLOR*[\@ ]/;
}
@@ -62,15 +63,22 @@ while (<>) {
# place to flush. Flushing on a blank line is a heuristic that
# happens to match git-log output.
if (!length) {
- local $| = 1;
+ $flush_cb->();
}
}
-# Flush any queued hunk (this can happen when there is no trailing context in
-# the final diff of the input).
-show_hunk(\@removed, \@added);
+sub flush {
+ # Flush any queued hunk (this can happen when there is no trailing
+ # context in the final diff of the input).
+ show_hunk(\@removed, \@added);
+}
-exit 0;
+sub highlight_stdin {
+ while (<STDIN>) {
+ handle_line($_);
+ }
+ flush();
+}
# Ideally we would feed the default as a human-readable color to
# git-config as the fallback value. But diff-highlight does
@@ -88,7 +96,7 @@ sub show_hunk {
# If one side is empty, then there is nothing to compare or highlight.
if (!@$a || !@$b) {
- print @$a, @$b;
+ $line_cb->(@$a, @$b);
return;
}
@@ -97,17 +105,17 @@ sub show_hunk {
# stupid, and only handle multi-line hunks that remove and add the same
# number of lines.
if (@$a != @$b) {
- print @$a, @$b;
+ $line_cb->(@$a, @$b);
return;
}
my @queue;
for (my $i = 0; $i < @$a; $i++) {
my ($rm, $add) = highlight_pair($a->[$i], $b->[$i]);
- print $rm;
+ $line_cb->($rm);
push @queue, $add;
}
- print @queue;
+ $line_cb->(@queue);
}
sub highlight_pair {
diff --git a/contrib/diff-highlight/Makefile b/contrib/diff-highlight/Makefile
index 9018724524..fbf5c58249 100644
--- a/contrib/diff-highlight/Makefile
+++ b/contrib/diff-highlight/Makefile
@@ -1,5 +1,20 @@
-# nothing to build
-all:
+all: diff-highlight
-test:
+PERL_PATH = /usr/bin/perl
+-include ../../config.mak
+
+PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
+
+diff-highlight: shebang.perl DiffHighlight.pm diff-highlight.perl
+ cat $^ >$@+
+ chmod +x $@+
+ mv $@+ $@
+
+shebang.perl: FORCE
+ @echo '#!$(PERL_PATH_SQ)' >$@+
+ @cmp $@+ $@ >/dev/null 2>/dev/null || mv $@+ $@
+
+test: all
$(MAKE) -C t
+
+.PHONY: FORCE
diff --git a/contrib/diff-highlight/README b/contrib/diff-highlight/README
index 836b97a730..d4c2343175 100644
--- a/contrib/diff-highlight/README
+++ b/contrib/diff-highlight/README
@@ -99,6 +99,36 @@ newHighlight = "black #aaffaa"
---------------------------------------------
+Using diff-highlight as a module
+--------------------------------
+
+If you want to pre- or post- process the highlighted lines as part of
+another perl script, you can use the DiffHighlight module. You can
+either "require" it or just cat the module together with your script (to
+avoid run-time dependencies).
+
+Your script may set up one or more of the following variables:
+
+ - $DiffHighlight::line_cb - this should point to a function which is
+ called whenever DiffHighlight has lines (which may contain
+ highlights) to output. The default function prints each line to
+ stdout. Note that the function may be called with multiple lines.
+
+ - $DiffHighlight::flush_cb - this should point to a function which
+ flushes the output (because DiffHighlight believes it has completed
+ processing a logical chunk of input). The default function flushes
+ stdout.
+
+The script may then feed lines, one at a time, to DiffHighlight::handle_line().
+When lines are done processing, they will be fed to $line_cb. Note that
+DiffHighlight may queue up many input lines (to analyze a whole hunk)
+before calling $line_cb. After providing all lines, call
+DiffHighlight::flush() to flush any unprocessed lines.
+
+If you just want to process stdin, DiffHighlight::highlight_stdin()
+is a convenience helper which will loop and flush for you.
+
+
Bugs
----
diff --git a/contrib/diff-highlight/diff-highlight.perl b/contrib/diff-highlight/diff-highlight.perl
new file mode 100644
index 0000000000..9b3e9c1f4d
--- /dev/null
+++ b/contrib/diff-highlight/diff-highlight.perl
@@ -0,0 +1,8 @@
+package main;
+
+# Some scripts may not realize that SIGPIPE is being ignored when launching the
+# pager--for instance scripts written in Python.
+$SIG{PIPE} = 'DEFAULT';
+
+DiffHighlight::highlight_stdin();
+exit 0;
diff --git a/contrib/hooks/multimail/git_multimail.py b/contrib/hooks/multimail/git_multimail.py
index c7f86403cf..73fdda6b14 100755
--- a/contrib/hooks/multimail/git_multimail.py
+++ b/contrib/hooks/multimail/git_multimail.py
@@ -2964,7 +2964,7 @@ class StaticRecipientsEnvironmentMixin(Environment):
class CLIRecipientsEnvironmentMixin(Environment):
- """Mixin storing recipients information comming from the
+ """Mixin storing recipients information coming from the
command-line."""
def __init__(self, cli_recipients=None, **kw):
diff --git a/contrib/mw-to-git/git-remote-mediawiki.perl b/contrib/mw-to-git/git-remote-mediawiki.perl
index 41e74fba1e..e7f857c1a2 100755
--- a/contrib/mw-to-git/git-remote-mediawiki.perl
+++ b/contrib/mw-to-git/git-remote-mediawiki.perl
@@ -857,7 +857,7 @@ sub mw_import_revids {
my $n = 0;
my $n_actual = 0;
- my $last_timestamp = 0; # Placeholer in case $rev->timestamp is undefined
+ my $last_timestamp = 0; # Placeholder in case $rev->timestamp is undefined
foreach my $pagerevid (@{$revision_ids}) {
# Count page even if we skip it, since we display
diff --git a/contrib/mw-to-git/t/README b/contrib/mw-to-git/t/README
index 03f6ee5d72..2ee34be7e4 100644
--- a/contrib/mw-to-git/t/README
+++ b/contrib/mw-to-git/t/README
@@ -121,4 +121,4 @@ How to write a new test
Please, follow the standards given by git. See git/t/README.
New file should be named as t936[0-9]-*.sh.
-Be sure to reset your wiki regulary with the function `wiki_reset`.
+Be sure to reset your wiki regularly with the function `wiki_reset`.
diff --git a/credential.c b/credential.c
index 67a523353b..9747f47b18 100644
--- a/credential.c
+++ b/credential.c
@@ -94,8 +94,7 @@ static void credential_apply_config(struct credential *c)
c->configured = 1;
if (!c->use_http_path && proto_is_http(c->protocol)) {
- free(c->path);
- c->path = NULL;
+ FREE_AND_NULL(c->path);
}
}
@@ -315,10 +314,8 @@ void credential_reject(struct credential *c)
for (i = 0; i < c->helpers.nr; i++)
credential_do(c, c->helpers.items[i].string, "erase");
- free(c->username);
- c->username = NULL;
- free(c->password);
- c->password = NULL;
+ FREE_AND_NULL(c->username);
+ FREE_AND_NULL(c->password);
c->approved = 0;
}
diff --git a/date.c b/date.c
index 63fa99685e..1fd6d66375 100644
--- a/date.c
+++ b/date.c
@@ -70,6 +70,12 @@ static struct tm *time_to_tm(timestamp_t time, int tz)
return gmtime(&t);
}
+static struct tm *time_to_tm_local(timestamp_t time)
+{
+ time_t t = time;
+ return localtime(&t);
+}
+
/*
* What value of "tz" was in effect back then at "time" in the
* local timezone?
@@ -214,7 +220,10 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)
return timebuf.buf;
}
- tm = time_to_tm(time, tz);
+ if (mode->local)
+ tm = time_to_tm_local(time);
+ else
+ tm = time_to_tm(time, tz);
if (!tm) {
tm = time_to_tm(0, 0);
tz = 0;
@@ -246,7 +255,8 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)
month_names[tm->tm_mon], tm->tm_year + 1900,
tm->tm_hour, tm->tm_min, tm->tm_sec, tz);
else if (mode->type == DATE_STRFTIME)
- strbuf_addftime(&timebuf, mode->strftime_fmt, tm);
+ strbuf_addftime(&timebuf, mode->strftime_fmt, tm, tz,
+ mode->local ? NULL : "");
else
strbuf_addf(&timebuf, "%.3s %.3s %d %02d:%02d:%02d %d%c%+05d",
weekday_names[tm->tm_wday],
diff --git a/diff-lib.c b/diff-lib.c
index 0c0e20f7c0..2a52b07954 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -179,8 +179,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
free(dpath);
continue;
}
- free(dpath);
- dpath = NULL;
+ FREE_AND_NULL(dpath);
/*
* Show the diff for the 'ce' if we found the one
diff --git a/diff.c b/diff.c
index 41295d4ea9..00b4c86698 100644
--- a/diff.c
+++ b/diff.c
@@ -1219,8 +1219,7 @@ static void free_diff_words_data(struct emit_callback *ecbdata)
regfree(ecbdata->diff_words->word_regex);
free(ecbdata->diff_words->word_regex);
}
- free(ecbdata->diff_words);
- ecbdata->diff_words = NULL;
+ FREE_AND_NULL(ecbdata->diff_words);
}
}
@@ -2952,8 +2951,7 @@ void diff_free_filespec_blob(struct diff_filespec *s)
void diff_free_filespec_data(struct diff_filespec *s)
{
diff_free_filespec_blob(s);
- free(s->cnt_data);
- s->cnt_data = NULL;
+ FREE_AND_NULL(s->cnt_data);
}
static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 03d1e8d40b..1e4678b7d7 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -667,11 +667,9 @@ void diffcore_rename(struct diff_options *options)
for (i = 0; i < rename_dst_nr; i++)
free_filespec(rename_dst[i].two);
- free(rename_dst);
- rename_dst = NULL;
+ FREE_AND_NULL(rename_dst);
rename_dst_nr = rename_dst_alloc = 0;
- free(rename_src);
- rename_src = NULL;
+ FREE_AND_NULL(rename_src);
rename_src_nr = rename_src_alloc = 0;
return;
}
diff --git a/dir.c b/dir.c
index 34445374ba..332f9d8095 100644
--- a/dir.c
+++ b/dir.c
@@ -53,6 +53,15 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
static int get_dtype(struct dirent *de, struct index_state *istate,
const char *path, int len);
+int count_slashes(const char *s)
+{
+ int cnt = 0;
+ while (*s)
+ if (*s++ == '/')
+ cnt++;
+ return cnt;
+}
+
int fspathcmp(const char *a, const char *b)
{
return ignore_case ? strcasecmp(a, b) : strcmp(a, b);
@@ -2118,8 +2127,7 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
for (i = j = 0; j < dir->nr; j++) {
if (i &&
check_dir_entry_contains(dir->entries[i - 1], dir->entries[j])) {
- free(dir->entries[j]);
- dir->entries[j] = NULL;
+ FREE_AND_NULL(dir->entries[j]);
} else {
dir->entries[i++] = dir->entries[j];
}
@@ -2145,8 +2153,7 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
dir->untracked->dir_invalidated))
istate->cache_changed |= UNTRACKED_CHANGED;
if (dir->untracked != istate->untracked) {
- free(dir->untracked);
- dir->untracked = NULL;
+ FREE_AND_NULL(dir->untracked);
}
}
return dir->nr;
@@ -2489,8 +2496,7 @@ void write_untracked_extension(struct strbuf *out, struct untracked_cache *untra
strbuf_addbuf(out, &untracked->ident);
strbuf_add(out, ouc, ouc_size(len));
- free(ouc);
- ouc = NULL;
+ FREE_AND_NULL(ouc);
if (!untracked->root) {
varint_len = encode_varint(0, varbuf);
diff --git a/dir.h b/dir.h
index a89c13e27a..e3717055d1 100644
--- a/dir.h
+++ b/dir.h
@@ -197,6 +197,9 @@ struct dir_struct {
unsigned unmanaged_exclude_files;
};
+/*Count the number of slashes for string s*/
+extern int count_slashes(const char *s);
+
/*
* The ordering of these constants is significant, with
* higher-numbered match types signifying "closer" (i.e. more
diff --git a/fast-import.c b/fast-import.c
index 94a1b06149..a959161b46 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -281,7 +281,7 @@ struct recent_command {
};
/* Configured limits on output */
-static unsigned long max_depth = 10;
+static unsigned long max_depth = 50;
static off_t max_packsize;
static int unpack_limit = 100;
static int force_update;
@@ -1064,8 +1064,7 @@ discard_pack:
close(pack_data->pack_fd);
unlink_or_warn(pack_data->pack_name);
}
- free(pack_data);
- pack_data = NULL;
+ FREE_AND_NULL(pack_data);
running = 0;
/* We can't carry a delta across packfiles. */
@@ -1150,8 +1149,7 @@ static int store_object(
/* We cannot carry a delta into the new pack. */
if (delta) {
- free(delta);
- delta = NULL;
+ FREE_AND_NULL(delta);
git_deflate_init(&s, pack_compression_level);
s.next_in = (void *)dat->buf;
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 79d675b5b0..0e8543c865 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -1081,7 +1081,7 @@ EOF2
open $fh, '<', $hunkfile
or die sprintf(__("failed to open hunk edit file for reading: %s"), $!);
- my @newtext = grep { !/^$comment_line_char/ } <$fh>;
+ my @newtext = grep { !/^\Q$comment_line_char\E/ } <$fh>;
close $fh;
unlink $hunkfile;
@@ -1136,6 +1136,7 @@ sub prompt_yesno {
while (1) {
print colored $prompt_color, $prompt;
my $line = prompt_single_character;
+ return undef unless defined $line;
return 0 if $line =~ /^n/i;
return 1 if $line =~ /^y/i;
}
diff --git a/git-compat-util.h b/git-compat-util.h
index 51ba4e6b3b..047172d173 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -808,6 +808,12 @@ extern char *xgetcwd(void);
extern FILE *fopen_for_writing(const char *path);
extern FILE *fopen_or_warn(const char *path, const char *mode);
+/*
+ * FREE_AND_NULL(ptr) is like free(ptr) followed by ptr = NULL. Note
+ * that ptr is used twice, so don't pass e.g. ptr++.
+ */
+#define FREE_AND_NULL(p) do { free(p); (p) = NULL; } while (0)
+
#define ALLOC_ARRAY(x, alloc) (x) = xmalloc(st_mult(sizeof(*(x)), (alloc)))
#define REALLOC_ARRAY(x, alloc) (x) = xrealloc((x), st_mult(sizeof(*(x)), (alloc)))
diff --git a/git-filter-branch.sh b/git-filter-branch.sh
index aafaf708da..3a74602ef3 100755
--- a/git-filter-branch.sh
+++ b/git-filter-branch.sh
@@ -81,12 +81,13 @@ set_ident () {
finish_ident COMMITTER
}
-USAGE="[--env-filter <command>] [--tree-filter <command>]
- [--index-filter <command>] [--parent-filter <command>]
- [--msg-filter <command>] [--commit-filter <command>]
- [--tag-name-filter <command>] [--subdirectory-filter <directory>]
- [--original <namespace>] [-d <directory>] [-f | --force]
- [<rev-list options>...]"
+USAGE="[--setup <command>] [--env-filter <command>]
+ [--tree-filter <command>] [--index-filter <command>]
+ [--parent-filter <command>] [--msg-filter <command>]
+ [--commit-filter <command>] [--tag-name-filter <command>]
+ [--subdirectory-filter <directory>] [--original <namespace>]
+ [-d <directory>] [-f | --force]
+ [--] [<rev-list options>...]"
OPTIONS_SPEC=
. git-sh-setup
@@ -96,6 +97,7 @@ if [ "$(is_bare_repository)" = false ]; then
fi
tempdir=.git-rewrite
+filter_setup=
filter_env=
filter_tree=
filter_index=
@@ -148,6 +150,9 @@ do
-d)
tempdir="$OPTARG"
;;
+ --setup)
+ filter_setup="$OPTARG"
+ ;;
--env-filter)
filter_env="$OPTARG"
;;
@@ -317,6 +322,9 @@ else
need_index=
fi
+eval "$filter_setup" < /dev/null ||
+ die "filter setup failed: $filter_setup"
+
while read commit parents; do
git_filter_branch__commit_count=$(($git_filter_branch__commit_count+1))
diff --git a/git-rebase.sh b/git-rebase.sh
index db1deed846..2cf73b88e8 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -166,14 +166,14 @@ apply_autostash () {
stash_sha1=$(cat "$state_dir/autostash")
if git stash apply $stash_sha1 2>&1 >/dev/null
then
- echo "$(gettext 'Applied autostash.')"
+ echo "$(gettext 'Applied autostash.')" >&2
else
git stash store -m "autostash" -q $stash_sha1 ||
die "$(eval_gettext "Cannot store \$stash_sha1")"
gettext 'Applying autostash resulted in conflicts.
Your changes are safe in the stash.
You can run "git stash pop" or "git stash drop" at any time.
-'
+' >&2
fi
fi
}
diff --git a/git-stash.sh b/git-stash.sh
index 2fb651b2b8..9b6c2da7b4 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -19,6 +19,7 @@ OPTIONS_SPEC=
START_DIR=$(pwd)
. git-sh-setup
require_work_tree
+prefix=$(git rev-parse --show-prefix) || exit 1
cd_to_toplevel
TMP="$GIT_DIR/.git-stash.$$"
@@ -273,6 +274,8 @@ push_stash () {
shift
done
+ eval "set $(git rev-parse --sq --prefix "$prefix" -- "$@")"
+
if test -n "$patch_mode" && test -n "$untracked"
then
die "$(gettext "Can't use --patch and --include-untracked or --all at the same time")"
@@ -481,7 +484,7 @@ parse_flags_and_rev()
case $# in
0)
- have_stash || die "$(gettext "No stash found.")"
+ have_stash || die "$(gettext "No stash entries found.")"
set -- ${ref_stash}@{0}
;;
1)
@@ -573,7 +576,7 @@ apply_stash () {
GIT_INDEX_FILE="$TMPindex" git-read-tree "$u_tree" &&
GIT_INDEX_FILE="$TMPindex" git checkout-index --all &&
rm -f "$TMPindex" ||
- die "$(gettext "Could not restore untracked files from stash")"
+ die "$(gettext "Could not restore untracked files from stash entry")"
fi
eval "
@@ -627,7 +630,7 @@ pop_stash() {
drop_stash "$@"
else
status=$?
- say "$(gettext "The stash is kept in case you need it again.")"
+ say "$(gettext "The stash entry is kept in case you need it again.")"
exit $status
fi
}
diff --git a/git-submodule.sh b/git-submodule.sh
index c0d0e9a4c6..e131760eec 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -213,7 +213,8 @@ cmd_add()
die "$(eval_gettext "'\$sm_path' already exists in the index and is not a submodule")"
fi
- if test -z "$force" && ! git add --dry-run --ignore-missing "$sm_path" > /dev/null 2>&1
+ if test -z "$force" &&
+ ! git add --dry-run --ignore-missing --no-warn-embedded-repo "$sm_path" > /dev/null 2>&1
then
eval_gettextln "The following path is ignored by one of your .gitignore files:
\$sm_path
@@ -267,7 +268,7 @@ or you are unsure what this means choose another name with the '--name' option."
fi
git config submodule."$sm_name".url "$realrepo"
- git add $force "$sm_path" ||
+ git add --no-warn-embedded-repo $force "$sm_path" ||
die "$(eval_gettext "Failed to add submodule '\$sm_path'")"
git config -f .gitmodules submodule."$sm_name".path "$sm_path" &&
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index d8209c7a02..3d4a8ee27c 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -3125,7 +3125,7 @@ sub git_get_projects_list {
return @list;
}
-# written with help of Tree::Trie module (Perl Artistic License, GPL compatibile)
+# written with help of Tree::Trie module (Perl Artistic License, GPL compatible)
# as side effects it sets 'forks' field to list of forks for forked projects
sub filter_forks_from_projects_list {
my $projects = shift;
@@ -4376,7 +4376,7 @@ sub git_print_page_nav {
"</div>\n";
}
-# returns a submenu for the nagivation of the refs views (tags, heads,
+# returns a submenu for the navigation of the refs views (tags, heads,
# remotes) with the current view disabled and the remotes view only
# available if the feature is enabled
sub format_ref_views {
diff --git a/gpg-interface.c b/gpg-interface.c
index 8ab32df457..d936f3a32f 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -14,16 +14,11 @@ static const char *gpg_program = "gpg";
void signature_check_clear(struct signature_check *sigc)
{
- free(sigc->payload);
- free(sigc->gpg_output);
- free(sigc->gpg_status);
- free(sigc->signer);
- free(sigc->key);
- sigc->payload = NULL;
- sigc->gpg_output = NULL;
- sigc->gpg_status = NULL;
- sigc->signer = NULL;
- sigc->key = NULL;
+ FREE_AND_NULL(sigc->payload);
+ FREE_AND_NULL(sigc->gpg_output);
+ FREE_AND_NULL(sigc->gpg_status);
+ FREE_AND_NULL(sigc->signer);
+ FREE_AND_NULL(sigc->key);
}
static struct {
diff --git a/grep.c b/grep.c
index 30d317a122..98733db623 100644
--- a/grep.c
+++ b/grep.c
@@ -509,7 +509,7 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
if (!p->pcre2_jit_stack)
die("Couldn't allocate PCRE2 JIT stack");
p->pcre2_match_context = pcre2_match_context_create(NULL);
- if (!p->pcre2_jit_stack)
+ if (!p->pcre2_match_context)
die("Couldn't allocate PCRE2 match context");
pcre2_jit_stack_assign(p->pcre2_match_context, NULL, p->pcre2_jit_stack);
} else if (p->pcre2_jit_on != 0) {
@@ -1940,12 +1940,9 @@ void grep_source_init(struct grep_source *gs, enum grep_source_type type,
void grep_source_clear(struct grep_source *gs)
{
- free(gs->name);
- gs->name = NULL;
- free(gs->path);
- gs->path = NULL;
- free(gs->identifier);
- gs->identifier = NULL;
+ FREE_AND_NULL(gs->name);
+ FREE_AND_NULL(gs->path);
+ FREE_AND_NULL(gs->identifier);
grep_source_clear_data(gs);
}
@@ -1955,8 +1952,7 @@ void grep_source_clear_data(struct grep_source *gs)
case GREP_SOURCE_FILE:
case GREP_SOURCE_OID:
case GREP_SOURCE_SUBMODULE:
- free(gs->buf);
- gs->buf = NULL;
+ FREE_AND_NULL(gs->buf);
gs->size = 0;
break;
case GREP_SOURCE_BUF:
diff --git a/help.c b/help.c
index 8ba0777410..88a3aeaeb9 100644
--- a/help.c
+++ b/help.c
@@ -269,9 +269,8 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
for (i = 0; i < old->cnt; i++)
cmds->names[cmds->cnt++] = old->names[i];
- free(old->names);
+ FREE_AND_NULL(old->names);
old->cnt = 0;
- old->names = NULL;
}
/* An empirically derived magic number */
@@ -357,12 +356,18 @@ const char *help_unknown_cmd(const char *cmd)
clean_cmdnames(&main_cmds);
fprintf_ln(stderr,
_("WARNING: You called a Git command named '%s', "
- "which does not exist.\n"
- "Continuing under the assumption that you meant '%s'"),
- cmd, assumed);
- if (autocorrect > 0) {
- fprintf_ln(stderr, _("in %0.1f seconds automatically..."),
- (float)autocorrect/10.0);
+ "which does not exist."),
+ cmd);
+ if (autocorrect < 0)
+ fprintf_ln(stderr,
+ _("Continuing under the assumption that "
+ "you meant '%s'."),
+ assumed);
+ else {
+ fprintf_ln(stderr,
+ _("Continuing in %0.1f seconds, "
+ "assuming that you meant '%s'."),
+ (float)autocorrect/10.0, assumed);
sleep_millisec(autocorrect * 100);
}
return assumed;
diff --git a/http-push.c b/http-push.c
index 67c4d4b472..c91f40a610 100644
--- a/http-push.c
+++ b/http-push.c
@@ -291,8 +291,7 @@ static void start_mkcol(struct transfer_request *request)
request->state = RUN_MKCOL;
} else {
request->state = ABORTED;
- free(request->url);
- request->url = NULL;
+ FREE_AND_NULL(request->url);
}
}
#endif
@@ -409,8 +408,7 @@ static void start_put(struct transfer_request *request)
request->state = RUN_PUT;
} else {
request->state = ABORTED;
- free(request->url);
- request->url = NULL;
+ FREE_AND_NULL(request->url);
}
}
@@ -432,8 +430,7 @@ static void start_move(struct transfer_request *request)
request->state = RUN_MOVE;
} else {
request->state = ABORTED;
- free(request->url);
- request->url = NULL;
+ FREE_AND_NULL(request->url);
}
}
@@ -526,8 +523,7 @@ static void finish_request(struct transfer_request *request)
/* URL is reused for MOVE after PUT */
if (request->state != RUN_PUT) {
- free(request->url);
- request->url = NULL;
+ FREE_AND_NULL(request->url);
}
if (request->state == RUN_MKCOL) {
@@ -803,8 +799,7 @@ xml_start_tag(void *userData, const char *name, const char **atts)
}
xsnprintf(ctx->name + old_namelen, ctx->len - old_namelen, ".%s", c);
- free(ctx->cdata);
- ctx->cdata = NULL;
+ FREE_AND_NULL(ctx->cdata);
ctx->userFunc(ctx, 0);
}
@@ -932,8 +927,7 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
free(lock->token);
free(lock->owner);
free(url);
- free(lock);
- lock = NULL;
+ FREE_AND_NULL(lock);
} else {
lock->url = url;
lock->start_time = time(NULL);
@@ -1105,8 +1099,7 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
ls->dentry_flags |= IS_DIR;
}
} else if (!strcmp(ctx->name, DAV_PROPFIND_RESP)) {
- free(ls->dentry_name);
- ls->dentry_name = NULL;
+ FREE_AND_NULL(ls->dentry_name);
ls->dentry_flags = 0;
}
}
@@ -1547,8 +1540,7 @@ static void fetch_symref(const char *path, char **symref, struct object_id *oid)
curl_errorstr);
free(url);
- free(*symref);
- *symref = NULL;
+ FREE_AND_NULL(*symref);
oidclr(oid);
if (buffer.len == 0)
diff --git a/http.c b/http.c
index 013bb0cc65..c6c010f881 100644
--- a/http.c
+++ b/http.c
@@ -1027,8 +1027,7 @@ void http_cleanup(void)
if (proxy_auth.password) {
memset(proxy_auth.password, 0, strlen(proxy_auth.password));
- free(proxy_auth.password);
- proxy_auth.password = NULL;
+ FREE_AND_NULL(proxy_auth.password);
}
free((void *)curl_proxyuserpwd);
@@ -1039,13 +1038,11 @@ void http_cleanup(void)
if (cert_auth.password != NULL) {
memset(cert_auth.password, 0, strlen(cert_auth.password));
- free(cert_auth.password);
- cert_auth.password = NULL;
+ FREE_AND_NULL(cert_auth.password);
}
ssl_cert_password_required = 0;
- free(cached_accept_language);
- cached_accept_language = NULL;
+ FREE_AND_NULL(cached_accept_language);
}
struct active_request_slot *get_active_slot(void)
@@ -1897,8 +1894,7 @@ static char *fetch_pack_index(unsigned char *sha1, const char *base_url)
if (http_get_file(url, tmp, NULL) != HTTP_OK) {
error("Unable to get pack index %s", url);
- free(tmp);
- tmp = NULL;
+ FREE_AND_NULL(tmp);
}
free(url);
@@ -2329,8 +2325,7 @@ void release_http_object_request(struct http_object_request *freq)
freq->localfile = -1;
}
if (freq->url != NULL) {
- free(freq->url);
- freq->url = NULL;
+ FREE_AND_NULL(freq->url);
}
if (freq->slot != NULL) {
freq->slot->callback_func = NULL;
diff --git a/imap-send.c b/imap-send.c
index 59e9b12d29..351e84aea1 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -777,8 +777,7 @@ static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)
offsetof(struct imap_cmd, next));
if (cmdp->cb.data) {
n = socket_write(&imap->buf.sock, cmdp->cb.data, cmdp->cb.dlen);
- free(cmdp->cb.data);
- cmdp->cb.data = NULL;
+ FREE_AND_NULL(cmdp->cb.data);
if (n != (int)cmdp->cb.dlen)
return RESP_BAD;
} else if (cmdp->cb.cont) {
diff --git a/line-log.c b/line-log.c
index 2588ce0767..ab0709f9ae 100644
--- a/line-log.c
+++ b/line-log.c
@@ -34,9 +34,8 @@ void range_set_init(struct range_set *rs, size_t prealloc)
void range_set_release(struct range_set *rs)
{
- free(rs->ranges);
+ FREE_AND_NULL(rs->ranges);
rs->alloc = rs->nr = 0;
- rs->ranges = NULL;
}
/* dst must be uninitialized! */
@@ -610,8 +609,7 @@ parse_lines(struct commit *commit, const char *prefix, struct string_list *args)
line_log_data_insert(&ranges, full_name, begin, end);
free_filespec(spec);
- free(ends);
- ends = NULL;
+ FREE_AND_NULL(ends);
}
for (p = ranges; p; p = p->next)
diff --git a/ll-merge.c b/ll-merge.c
index b9576efe97..9fb855a900 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -210,8 +210,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
result->size = st.st_size;
result->ptr = xmallocz(result->size);
if (read_in_full(fd, result->ptr, result->size) != result->size) {
- free(result->ptr);
- result->ptr = NULL;
+ FREE_AND_NULL(result->ptr);
result->size = 0;
}
close_bad:
diff --git a/mailinfo.c b/mailinfo.c
index f59162453e..bd574cb752 100644
--- a/mailinfo.c
+++ b/mailinfo.c
@@ -58,17 +58,17 @@ static void parse_bogus_from(struct mailinfo *mi, const struct strbuf *line)
static const char *unquote_comment(struct strbuf *outbuf, const char *in)
{
int c;
- int take_next_litterally = 0;
+ int take_next_literally = 0;
strbuf_addch(outbuf, '(');
while ((c = *in++) != 0) {
- if (take_next_litterally == 1) {
- take_next_litterally = 0;
+ if (take_next_literally == 1) {
+ take_next_literally = 0;
} else {
switch (c) {
case '\\':
- take_next_litterally = 1;
+ take_next_literally = 1;
continue;
case '(':
in = unquote_comment(outbuf, in);
@@ -88,15 +88,15 @@ static const char *unquote_comment(struct strbuf *outbuf, const char *in)
static const char *unquote_quoted_string(struct strbuf *outbuf, const char *in)
{
int c;
- int take_next_litterally = 0;
+ int take_next_literally = 0;
while ((c = *in++) != 0) {
- if (take_next_litterally == 1) {
- take_next_litterally = 0;
+ if (take_next_literally == 1) {
+ take_next_literally = 0;
} else {
switch (c) {
case '\\':
- take_next_litterally = 1;
+ take_next_literally = 1;
continue;
case '"':
return in;
@@ -920,8 +920,7 @@ again:
/* we hit an end boundary */
/* pop the current boundary off the stack */
strbuf_release(*(mi->content_top));
- free(*(mi->content_top));
- *(mi->content_top) = NULL;
+ FREE_AND_NULL(*(mi->content_top));
/* technically won't happen as is_multipart_boundary()
will fail first. But just in case..
diff --git a/mergetools/meld b/mergetools/meld
index bc178e8882..7a08470f88 100644
--- a/mergetools/meld
+++ b/mergetools/meld
@@ -10,7 +10,7 @@ merge_cmd () {
if test "$meld_has_output_option" = true
then
- "$merge_tool_path" --output "$MERGED" \
+ "$merge_tool_path" --output="$MERGED" \
"$LOCAL" "$BASE" "$REMOTE"
else
"$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"
diff --git a/object.c b/object.c
index 06ba3a11d8..f818777412 100644
--- a/object.c
+++ b/object.c
@@ -377,8 +377,7 @@ void object_array_clear(struct object_array *array)
int i;
for (i = 0; i < array->nr; i++)
object_array_release_entry(&array->objects[i]);
- free(array->objects);
- array->objects = NULL;
+ FREE_AND_NULL(array->objects);
array->nr = array->alloc = 0;
}
diff --git a/pack-bitmap.c b/pack-bitmap.c
index a3ac3dccd4..327634cd71 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -627,7 +627,7 @@ static void show_objects_for_type(
sha1 = nth_packed_object_sha1(bitmap_git.pack, entry->nr);
if (bitmap_git.hashes)
- hash = ntohl(bitmap_git.hashes[entry->nr]);
+ hash = get_be32(bitmap_git.hashes + entry->nr);
show_reach(sha1, object_type, 0, hash, bitmap_git.pack, entry->offset);
}
diff --git a/pathspec.c b/pathspec.c
index ecc5331c23..e2a23ebc96 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -606,7 +606,7 @@ void parse_pathspec(struct pathspec *pathspec,
/*
* If everything is an exclude pattern, add one positive pattern
- * that matches everyting. We allocated an extra one for this.
+ * that matches everything. We allocated an extra one for this.
*/
if (nr_exclude == n) {
int plen = (!(flags & PATHSPEC_PREFER_CWD)) ? 0 : prefixlen;
@@ -663,7 +663,6 @@ void clear_pathspec(struct pathspec *pathspec)
attr_check_free(pathspec->items[i].attr_check);
}
- free(pathspec->items);
- pathspec->items = NULL;
+ FREE_AND_NULL(pathspec->items);
pathspec->nr = 0;
}
diff --git a/perl/Git/I18N.pm b/perl/Git/I18N.pm
index c41425c8d0..836a5c2382 100644
--- a/perl/Git/I18N.pm
+++ b/perl/Git/I18N.pm
@@ -74,7 +74,7 @@ Git::I18N - Perl interface to Git's Gettext localizations
printf __("The following error occurred: %s\n"), $error;
- printf __n("commited %d file\n", "commited %d files\n", $files), $files;
+ printf __n("committed %d file\n", "committed %d files\n", $files), $files;
=head1 DESCRIPTION
diff --git a/pretty.c b/pretty.c
index 9c9f81b5b0..e4b561c582 100644
--- a/pretty.c
+++ b/pretty.c
@@ -784,29 +784,9 @@ struct format_commit_context {
size_t body_off;
/* The following ones are relative to the result struct strbuf. */
- struct chunk abbrev_commit_hash;
- struct chunk abbrev_tree_hash;
- struct chunk abbrev_parent_hashes;
size_t wrap_start;
};
-static int add_again(struct strbuf *sb, struct chunk *chunk)
-{
- if (chunk->len) {
- strbuf_adddup(sb, chunk->off, chunk->len);
- return 1;
- }
-
- /*
- * We haven't seen this chunk before. Our caller is surely
- * going to add it the hard way now. Remember the most likely
- * start of the to-be-added chunk: the current end of the
- * struct strbuf.
- */
- chunk->off = sb->len;
- return 0;
-}
-
static void parse_commit_header(struct format_commit_context *context)
{
const char *msg = context->message;
@@ -1148,24 +1128,16 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
return 1;
case 'h': /* abbreviated commit hash */
strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
- if (add_again(sb, &c->abbrev_commit_hash)) {
- strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
- return 1;
- }
strbuf_add_unique_abbrev(sb, commit->object.oid.hash,
c->pretty_ctx->abbrev);
strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
- c->abbrev_commit_hash.len = sb->len - c->abbrev_commit_hash.off;
return 1;
case 'T': /* tree hash */
strbuf_addstr(sb, oid_to_hex(&commit->tree->object.oid));
return 1;
case 't': /* abbreviated tree hash */
- if (add_again(sb, &c->abbrev_tree_hash))
- return 1;
strbuf_add_unique_abbrev(sb, commit->tree->object.oid.hash,
c->pretty_ctx->abbrev);
- c->abbrev_tree_hash.len = sb->len - c->abbrev_tree_hash.off;
return 1;
case 'P': /* parent hashes */
for (p = commit->parents; p; p = p->next) {
@@ -1175,16 +1147,12 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
}
return 1;
case 'p': /* abbreviated parent hashes */
- if (add_again(sb, &c->abbrev_parent_hashes))
- return 1;
for (p = commit->parents; p; p = p->next) {
if (p != commit->parents)
strbuf_addch(sb, ' ');
strbuf_add_unique_abbrev(sb, p->item->object.oid.hash,
c->pretty_ctx->abbrev);
}
- c->abbrev_parent_hashes.len = sb->len -
- c->abbrev_parent_hashes.off;
return 1;
case 'm': /* left/right/bottom */
strbuf_addstr(sb, get_revision_mark(NULL, commit));
diff --git a/prio-queue.c b/prio-queue.c
index fc3860fdcb..126d096727 100644
--- a/prio-queue.c
+++ b/prio-queue.c
@@ -27,10 +27,9 @@ void prio_queue_reverse(struct prio_queue *queue)
void clear_prio_queue(struct prio_queue *queue)
{
- free(queue->array);
+ FREE_AND_NULL(queue->array);
queue->nr = 0;
queue->alloc = 0;
- queue->array = NULL;
queue->insertion_ctr = 0;
}
diff --git a/read-cache.c b/read-cache.c
index c8c766dab0..3c4354ee21 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1878,9 +1878,15 @@ int discard_index(struct index_state *istate)
{
int i;
- unshare_split_index(istate, 1);
- for (i = 0; i < istate->cache_nr; i++)
+ for (i = 0; i < istate->cache_nr; i++) {
+ if (istate->cache[i]->index &&
+ istate->split_index &&
+ istate->split_index->base &&
+ istate->cache[i]->index <= istate->split_index->base->cache_nr &&
+ istate->cache[i] == istate->split_index->base->cache[istate->cache[i]->index - 1])
+ continue;
free(istate->cache[i]);
+ }
resolve_undo_clear_index(istate);
istate->cache_nr = 0;
istate->cache_changed = 0;
@@ -1889,8 +1895,7 @@ int discard_index(struct index_state *istate)
free_name_hash(istate);
cache_tree_free(&(istate->cache_tree));
istate->initialized = 0;
- free(istate->cache);
- istate->cache = NULL;
+ FREE_AND_NULL(istate->cache);
istate->cache_alloc = 0;
discard_split_index(istate);
free_untracked_cache(istate->untracked);
@@ -2604,8 +2609,7 @@ void *read_blob_data_from_index(const struct index_state *istate,
void stat_validity_clear(struct stat_validity *sv)
{
- free(sv->sd);
- sv->sd = NULL;
+ FREE_AND_NULL(sv->sd);
}
int stat_validity_check(struct stat_validity *sv, const char *path)
diff --git a/ref-filter.c b/ref-filter.c
index ab32bc9c31..72e6cb8ecc 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1891,8 +1891,7 @@ void ref_array_clear(struct ref_array *array)
for (i = 0; i < array->nr; i++)
free_array_item(array->items[i]);
- free(array->items);
- array->items = NULL;
+ FREE_AND_NULL(array->items);
array->nr = array->alloc = 0;
}
diff --git a/refs.c b/refs.c
index 84112c88ee..88658ba769 100644
--- a/refs.c
+++ b/refs.c
@@ -1342,6 +1342,18 @@ int for_each_ref_in_submodule(const char *submodule, const char *prefix,
prefix, fn, cb_data);
}
+int for_each_fullref_in_submodule(const char *submodule, const char *prefix,
+ each_ref_fn fn, void *cb_data,
+ unsigned int broken)
+{
+ unsigned int flag = 0;
+
+ if (broken)
+ flag = DO_FOR_EACH_INCLUDE_BROKEN;
+ return do_for_each_ref(get_submodule_ref_store(submodule),
+ prefix, fn, 0, flag, cb_data);
+}
+
int for_each_replace_ref(each_ref_fn fn, void *cb_data)
{
return do_for_each_ref(get_main_ref_store(),
diff --git a/refs.h b/refs.h
index 4be14c4b3c..6daa78eb50 100644
--- a/refs.h
+++ b/refs.h
@@ -303,7 +303,10 @@ int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data);
int for_each_ref_submodule(const char *submodule,
each_ref_fn fn, void *cb_data);
int for_each_ref_in_submodule(const char *submodule, const char *prefix,
- each_ref_fn fn, void *cb_data);
+ each_ref_fn fn, void *cb_data);
+int for_each_fullref_in_submodule(const char *submodule, const char *prefix,
+ each_ref_fn fn, void *cb_data,
+ unsigned int broken);
int for_each_tag_ref_submodule(const char *submodule,
each_ref_fn fn, void *cb_data);
int for_each_branch_ref_submodule(const char *submodule,
@@ -571,7 +574,7 @@ int ref_transaction_verify(struct ref_transaction *transaction,
#define TRANSACTION_GENERIC_ERROR -2
/*
- * Perform the preparatory stages of commiting `transaction`. Acquire
+ * Perform the preparatory stages of committing `transaction`. Acquire
* any needed locks, check preconditions, etc.; basically, do as much
* as possible to ensure that the transaction will be able to go
* through, stopping just short of making any irrevocable or
@@ -583,7 +586,7 @@ int ref_transaction_verify(struct ref_transaction *transaction,
* On failure, abort the transaction, write an error message to `err`,
* and return one of the `TRANSACTION_*` constants.
*
- * Callers who don't need such fine-grained control over commiting
+ * Callers who don't need such fine-grained control over committing
* reference transactions should just call `ref_transaction_commit()`.
*/
int ref_transaction_prepare(struct ref_transaction *transaction,
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 621a4086c3..0404f2c233 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -371,6 +371,18 @@ static void files_ref_path(struct files_ref_store *refs,
}
/*
+ * Check that the packed refs cache (if any) still reflects the
+ * contents of the file. If not, clear the cache.
+ */
+static void validate_packed_ref_cache(struct files_ref_store *refs)
+{
+ if (refs->packed &&
+ !stat_validity_check(&refs->packed->validity,
+ files_packed_refs_path(refs)))
+ clear_packed_ref_cache(refs);
+}
+
+/*
* Get the packed_ref_cache for the specified files_ref_store,
* creating and populating it if it hasn't been read before or if the
* file has been changed (according to its `validity` field) since it
@@ -382,10 +394,8 @@ static struct packed_ref_cache *get_packed_ref_cache(struct files_ref_store *ref
{
const char *packed_refs_file = files_packed_refs_path(refs);
- if (refs->packed &&
- !is_lock_file_locked(&refs->packed_refs_lock) &&
- !stat_validity_check(&refs->packed->validity, packed_refs_file))
- clear_packed_ref_cache(refs);
+ if (!is_lock_file_locked(&refs->packed_refs_lock))
+ validate_packed_ref_cache(refs);
if (!refs->packed)
refs->packed = read_packed_refs(packed_refs_file);
@@ -1312,13 +1322,17 @@ static int lock_packed_refs(struct files_ref_store *refs, int flags)
&refs->packed_refs_lock, files_packed_refs_path(refs),
flags, timeout_value) < 0)
return -1;
+
/*
- * Get the current packed-refs while holding the lock. It is
- * important that we call `get_packed_ref_cache()` before
- * setting `packed_ref_cache->lock`, because otherwise the
- * former will see that the file is locked and assume that the
- * cache can't be stale.
+ * Now that we hold the `packed-refs` lock, make sure that our
+ * cache matches the current version of the file. Normally
+ * `get_packed_ref_cache()` does that for us, but that
+ * function assumes that when the file is locked, any existing
+ * cache is still valid. We've just locked the file, but it
+ * might have changed the moment *before* we locked it.
*/
+ validate_packed_ref_cache(refs);
+
packed_ref_cache = get_packed_ref_cache(refs);
/* Increment the reference count to prevent it from being freed: */
acquire_packed_ref_cache(packed_ref_cache);
@@ -2945,8 +2959,7 @@ static int files_transaction_prepare(struct ref_store *ref_store,
head_oid.hash, &head_type);
if (head_ref && !(head_type & REF_ISSYMREF)) {
- free(head_ref);
- head_ref = NULL;
+ FREE_AND_NULL(head_ref);
}
/*
diff --git a/refs/ref-cache.c b/refs/ref-cache.c
index af2fcb2c12..76bb723c86 100644
--- a/refs/ref-cache.c
+++ b/refs/ref-cache.c
@@ -82,9 +82,8 @@ static void clear_ref_dir(struct ref_dir *dir)
int i;
for (i = 0; i < dir->nr; i++)
free_ref_entry(dir->entries[i]);
- free(dir->entries);
+ FREE_AND_NULL(dir->entries);
dir->sorted = dir->nr = dir->alloc = 0;
- dir->entries = NULL;
}
struct ref_entry *create_dir_entry(struct ref_cache *cache,
diff --git a/remote-testsvn.c b/remote-testsvn.c
index e034ea00d4..0ff4a31262 100644
--- a/remote-testsvn.c
+++ b/remote-testsvn.c
@@ -66,8 +66,7 @@ static char *read_ref_note(const struct object_id *oid)
else if (!msglen || type != OBJ_BLOB) {
error("Note contains unusable content. "
"Is something else using this notes tree? %s", notes_ref);
- free(msg);
- msg = NULL;
+ FREE_AND_NULL(msg);
}
free_notes(NULL);
return msg;
diff --git a/rerere.c b/rerere.c
index 829b3b0f08..70634d456c 100644
--- a/rerere.c
+++ b/rerere.c
@@ -40,9 +40,8 @@ static void free_rerere_dirs(void)
free(rerere_dir[i]->status);
free(rerere_dir[i]);
}
- free(rerere_dir);
+ FREE_AND_NULL(rerere_dir);
rerere_dir_nr = rerere_dir_alloc = 0;
- rerere_dir = NULL;
}
static void free_rerere_id(struct string_list_item *item)
diff --git a/revision.c b/revision.c
index 12eb332350..e181ad1b70 100644
--- a/revision.c
+++ b/revision.c
@@ -1725,8 +1725,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
revs->max_count = atoi(argv[1]);
revs->no_walk = 0;
return 2;
- } else if (starts_with(arg, "-n")) {
- revs->max_count = atoi(arg + 2);
+ } else if (skip_prefix(arg, "-n", &optarg)) {
+ revs->max_count = atoi(optarg);
revs->no_walk = 0;
} else if ((argcount = parse_long_opt("max-age", argv, &optarg))) {
revs->max_age = atoi(optarg);
@@ -1785,16 +1785,13 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
} else if (!strcmp(arg, "--author-date-order")) {
revs->sort_order = REV_SORT_BY_AUTHOR_DATE;
revs->topo_order = 1;
- } else if (starts_with(arg, "--early-output")) {
- int count = 100;
- switch (arg[14]) {
- case '=':
- count = atoi(arg+15);
- /* Fallthrough */
- case 0:
- revs->topo_order = 1;
- revs->early_output = count;
- }
+ } else if (!strcmp(arg, "--early-output")) {
+ revs->early_output = 100;
+ revs->topo_order = 1;
+ } else if (skip_prefix(arg, "--early-output=", &optarg)) {
+ if (strtoul_ui(optarg, 10, &revs->early_output) < 0)
+ die("'%s': not a non-negative integer", optarg);
+ revs->topo_order = 1;
} else if (!strcmp(arg, "--parents")) {
revs->rewrite_parents = 1;
revs->print_parents = 1;
@@ -1810,13 +1807,13 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
revs->min_parents = 2;
} else if (!strcmp(arg, "--no-merges")) {
revs->max_parents = 1;
- } else if (starts_with(arg, "--min-parents=")) {
- revs->min_parents = atoi(arg+14);
- } else if (starts_with(arg, "--no-min-parents")) {
+ } else if (skip_prefix(arg, "--min-parents=", &optarg)) {
+ revs->min_parents = atoi(optarg);
+ } else if (!strcmp(arg, "--no-min-parents")) {
revs->min_parents = 0;
- } else if (starts_with(arg, "--max-parents=")) {
- revs->max_parents = atoi(arg+14);
- } else if (starts_with(arg, "--no-max-parents")) {
+ } else if (skip_prefix(arg, "--max-parents=", &optarg)) {
+ revs->max_parents = atoi(optarg);
+ } else if (!strcmp(arg, "--no-max-parents")) {
revs->max_parents = -1;
} else if (!strcmp(arg, "--boundary")) {
revs->boundary = 1;
@@ -1897,14 +1894,15 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
revs->verbose_header = 1;
revs->pretty_given = 1;
get_commit_format(NULL, revs);
- } else if (starts_with(arg, "--pretty=") || starts_with(arg, "--format=")) {
+ } else if (skip_prefix(arg, "--pretty=", &optarg) ||
+ skip_prefix(arg, "--format=", &optarg)) {
/*
* Detached form ("--pretty X" as opposed to "--pretty=X")
* not allowed, since the argument is optional.
*/
revs->verbose_header = 1;
revs->pretty_given = 1;
- get_commit_format(arg+9, revs);
+ get_commit_format(optarg, revs);
} else if (!strcmp(arg, "--expand-tabs")) {
revs->expand_tabs_in_log = 8;
} else if (!strcmp(arg, "--no-expand-tabs")) {
@@ -1922,26 +1920,23 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
revs->show_signature = 1;
} else if (!strcmp(arg, "--no-show-signature")) {
revs->show_signature = 0;
- } else if (!strcmp(arg, "--show-linear-break") ||
- starts_with(arg, "--show-linear-break=")) {
- if (starts_with(arg, "--show-linear-break="))
- revs->break_bar = xstrdup(arg + 20);
- else
- revs->break_bar = " ..........";
+ } else if (!strcmp(arg, "--show-linear-break")) {
+ revs->break_bar = " ..........";
revs->track_linear = 1;
revs->track_first_time = 1;
- } else if (starts_with(arg, "--show-notes=") ||
- starts_with(arg, "--notes=")) {
+ } else if (skip_prefix(arg, "--show-linear-break=", &optarg)) {
+ revs->break_bar = xstrdup(optarg);
+ revs->track_linear = 1;
+ revs->track_first_time = 1;
+ } else if (skip_prefix(arg, "--show-notes=", &optarg) ||
+ skip_prefix(arg, "--notes=", &optarg)) {
struct strbuf buf = STRBUF_INIT;
revs->show_notes = 1;
revs->show_notes_given = 1;
- if (starts_with(arg, "--show-notes")) {
- if (revs->notes_opt.use_default_notes < 0)
- revs->notes_opt.use_default_notes = 1;
- strbuf_addstr(&buf, arg+13);
- }
- else
- strbuf_addstr(&buf, arg+8);
+ if (starts_with(arg, "--show-notes=") &&
+ revs->notes_opt.use_default_notes < 0)
+ revs->notes_opt.use_default_notes = 1;
+ strbuf_addstr(&buf, optarg);
expand_notes_ref(&buf);
string_list_append(&revs->notes_opt.extra_notes_refs,
strbuf_detach(&buf, NULL));
@@ -1978,8 +1973,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
revs->abbrev = 0;
} else if (!strcmp(arg, "--abbrev")) {
revs->abbrev = DEFAULT_ABBREV;
- } else if (starts_with(arg, "--abbrev=")) {
- revs->abbrev = strtoul(arg + 9, NULL, 10);
+ } else if (skip_prefix(arg, "--abbrev=", &optarg)) {
+ revs->abbrev = strtoul(optarg, NULL, 10);
if (revs->abbrev < MINIMUM_ABBREV)
revs->abbrev = MINIMUM_ABBREV;
else if (revs->abbrev > 40)
@@ -2080,7 +2075,7 @@ static int for_each_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_d
struct strbuf bisect_refs = STRBUF_INIT;
int status;
strbuf_addf(&bisect_refs, "refs/bisect/%s", term);
- status = for_each_ref_in_submodule(submodule, bisect_refs.buf, fn, cb_data);
+ status = for_each_fullref_in_submodule(submodule, bisect_refs.buf, fn, cb_data, 0);
strbuf_release(&bisect_refs);
return status;
}
@@ -2140,20 +2135,20 @@ static int handle_revision_pseudo_opt(const char *submodule,
} else if ((argcount = parse_long_opt("exclude", argv, &optarg))) {
add_ref_exclusion(&revs->ref_excludes, optarg);
return argcount;
- } else if (starts_with(arg, "--branches=")) {
+ } else if (skip_prefix(arg, "--branches=", &optarg)) {
struct all_refs_cb cb;
init_all_refs_cb(&cb, revs, *flags);
- for_each_glob_ref_in(handle_one_ref, arg + 11, "refs/heads/", &cb);
+ for_each_glob_ref_in(handle_one_ref, optarg, "refs/heads/", &cb);
clear_ref_exclusion(&revs->ref_excludes);
- } else if (starts_with(arg, "--tags=")) {
+ } else if (skip_prefix(arg, "--tags=", &optarg)) {
struct all_refs_cb cb;
init_all_refs_cb(&cb, revs, *flags);
- for_each_glob_ref_in(handle_one_ref, arg + 7, "refs/tags/", &cb);
+ for_each_glob_ref_in(handle_one_ref, optarg, "refs/tags/", &cb);
clear_ref_exclusion(&revs->ref_excludes);
- } else if (starts_with(arg, "--remotes=")) {
+ } else if (skip_prefix(arg, "--remotes=", &optarg)) {
struct all_refs_cb cb;
init_all_refs_cb(&cb, revs, *flags);
- for_each_glob_ref_in(handle_one_ref, arg + 10, "refs/remotes/", &cb);
+ for_each_glob_ref_in(handle_one_ref, optarg, "refs/remotes/", &cb);
clear_ref_exclusion(&revs->ref_excludes);
} else if (!strcmp(arg, "--reflog")) {
add_reflogs_to_pending(revs, *flags);
@@ -2163,14 +2158,14 @@ static int handle_revision_pseudo_opt(const char *submodule,
*flags ^= UNINTERESTING | BOTTOM;
} else if (!strcmp(arg, "--no-walk")) {
revs->no_walk = REVISION_WALK_NO_WALK_SORTED;
- } else if (starts_with(arg, "--no-walk=")) {
+ } else if (skip_prefix(arg, "--no-walk=", &optarg)) {
/*
* Detached form ("--no-walk X" as opposed to "--no-walk=X")
* not allowed, since the argument is optional.
*/
- if (!strcmp(arg + 10, "sorted"))
+ if (!strcmp(optarg, "sorted"))
revs->no_walk = REVISION_WALK_NO_WALK_SORTED;
- else if (!strcmp(arg + 10, "unsorted"))
+ else if (!strcmp(optarg, "unsorted"))
revs->no_walk = REVISION_WALK_NO_WALK_UNSORTED;
else
return error("invalid argument to --no-walk");
diff --git a/revision.h b/revision.h
index a91dd3d5d9..f96e7f7f49 100644
--- a/revision.h
+++ b/revision.h
@@ -74,8 +74,9 @@ struct rev_info {
/* topo-sort */
enum rev_sort_order sort_order;
- unsigned int early_output:1,
- ignore_missing:1,
+ unsigned int early_output;
+
+ unsigned int ignore_missing:1,
ignore_missing_links:1;
/* Traversal flags */
diff --git a/send-pack.c b/send-pack.c
index ed3cee3211..11d6f3d983 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -133,7 +133,7 @@ static int pack_objects(int fd, struct ref *refs, struct oid_array *extra, struc
* For a normal non-zero exit, we assume pack-objects wrote
* something useful to stderr. For death by signal, though,
* we should mention it to the user. The exception is SIGPIPE
- * (141), because that's a normal occurence if the remote end
+ * (141), because that's a normal occurrence if the remote end
* hangs up (and we'll report that by trying to read the unpack
* status).
*/
diff --git a/sequencer.c b/sequencer.c
index 224afe79b9..3010faf863 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1212,8 +1212,7 @@ struct todo_list {
static void todo_list_release(struct todo_list *todo_list)
{
strbuf_release(&todo_list->buf);
- free(todo_list->items);
- todo_list->items = NULL;
+ FREE_AND_NULL(todo_list->items);
todo_list->nr = todo_list->alloc = 0;
}
@@ -1923,7 +1922,7 @@ static int apply_autostash(struct replay_opts *opts)
argv_array_push(&child.args, "apply");
argv_array_push(&child.args, stash_sha1.buf);
if (!run_command(&child))
- printf(_("Applied autostash.\n"));
+ fprintf(stderr, _("Applied autostash.\n"));
else {
struct child_process store = CHILD_PROCESS_INIT;
@@ -1937,10 +1936,11 @@ static int apply_autostash(struct replay_opts *opts)
if (run_command(&store))
ret = error(_("cannot store %s"), stash_sha1.buf);
else
- printf(_("Applying autostash resulted in conflicts.\n"
- "Your changes are safe in the stash.\n"
- "You can run \"git stash pop\" or"
- " \"git stash drop\" at any time.\n"));
+ fprintf(stderr,
+ _("Applying autostash resulted in conflicts.\n"
+ "Your changes are safe in the stash.\n"
+ "You can run \"git stash pop\" or"
+ " \"git stash drop\" at any time.\n"));
}
strbuf_release(&stash_sha1);
diff --git a/sha1-array.c b/sha1-array.c
index 7d646ab5b8..838b3bf847 100644
--- a/sha1-array.c
+++ b/sha1-array.c
@@ -35,8 +35,7 @@ int oid_array_lookup(struct oid_array *array, const struct object_id *oid)
void oid_array_clear(struct oid_array *array)
{
- free(array->oid);
- array->oid = NULL;
+ FREE_AND_NULL(array->oid);
array->nr = 0;
array->alloc = 0;
array->sorted = 0;
diff --git a/sha1_file.c b/sha1_file.c
index a900b28042..fb1fd809dc 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -611,8 +611,7 @@ char *compute_alternate_path(const char *path, struct strbuf *err)
out:
if (seen_error) {
- free(ref_git);
- ref_git = NULL;
+ FREE_AND_NULL(ref_git);
}
return ref_git;
diff --git a/sha1dc/sha1.c b/sha1dc/sha1.c
index facea1bb56..3a1735e5ca 100644
--- a/sha1dc/sha1.c
+++ b/sha1dc/sha1.c
@@ -918,7 +918,7 @@ static void sha1recompress_fast_ ## t (uint32_t ihvin[5], uint32_t ihvout[5], co
#ifdef _MSC_VER
#pragma warning(push)
-#pragma warning(disable: 4127) /* Complier complains about the checks in the above macro being constant. */
+#pragma warning(disable: 4127) /* Compiler complains about the checks in the above macro being constant. */
#endif
#ifdef DOSTORESTATE0
diff --git a/split-index.c b/split-index.c
index 49bd197f71..83e39ec8d7 100644
--- a/split-index.c
+++ b/split-index.c
@@ -73,17 +73,10 @@ void move_cache_to_base_index(struct index_state *istate)
int i;
/*
- * If "si" is shared with another index_state (e.g. by
- * unpack-trees code), we will need to duplicate split_index
- * struct. It's not happening now though, luckily.
+ * do not delete old si->base, its index entries may be shared
+ * with istate->cache[]. Accept a bit of leaking here because
+ * this code is only used by short-lived update-index.
*/
- assert(si->refcount <= 1);
-
- unshare_split_index(istate, 0);
- if (si->base) {
- discard_index(si->base);
- free(si->base);
- }
si->base = xcalloc(1, sizeof(*si->base));
si->base->version = istate->version;
/* zero timestamp disables racy test in ce_write_index() */
@@ -174,10 +167,9 @@ void merge_base_index(struct index_state *istate)
ewah_free(si->delete_bitmap);
ewah_free(si->replace_bitmap);
- free(si->saved_cache);
+ FREE_AND_NULL(si->saved_cache);
si->delete_bitmap = NULL;
si->replace_bitmap = NULL;
- si->saved_cache = NULL;
si->saved_cache_nr = 0;
}
@@ -282,41 +274,11 @@ void finish_writing_split_index(struct index_state *istate)
istate->cache_nr = si->saved_cache_nr;
}
-void unshare_split_index(struct index_state *istate, int discard)
-{
- struct split_index *si = istate->split_index;
- int i;
-
- if (!si || !si->base)
- return;
-
- for (i = 0; i < istate->cache_nr; i++) {
- struct cache_entry *ce = istate->cache[i];
- struct cache_entry *new = NULL;
-
- if (!ce->index ||
- ce->index > si->base->cache_nr ||
- ce != si->base->cache[ce->index - 1])
- continue;
-
- if (!discard) {
- int len = ce_namelen(ce);
- new = xcalloc(1, cache_entry_size(len));
- copy_cache_entry(new, ce);
- memcpy(new->name, ce->name, len);
- new->index = 0;
- }
- istate->cache[i] = new;
- }
-}
-
-
void discard_split_index(struct index_state *istate)
{
struct split_index *si = istate->split_index;
if (!si)
return;
- unshare_split_index(istate, 0);
istate->split_index = NULL;
si->refcount--;
if (si->refcount)
@@ -365,8 +327,14 @@ void add_split_index(struct index_state *istate)
void remove_split_index(struct index_state *istate)
{
- if (!istate->split_index)
- return;
- discard_split_index(istate);
- istate->cache_changed |= SOMETHING_CHANGED;
+ if (istate->split_index) {
+ /*
+ * can't discard_split_index(&the_index); because that
+ * will destroy split_index->base->cache[], which may
+ * be shared with the_index.cache[]. So yeah we're
+ * leaking a bit here.
+ */
+ istate->split_index = NULL;
+ istate->cache_changed |= SOMETHING_CHANGED;
+ }
}
diff --git a/split-index.h b/split-index.h
index 65c0f09b2b..df91c1bda8 100644
--- a/split-index.h
+++ b/split-index.h
@@ -33,6 +33,5 @@ void finish_writing_split_index(struct index_state *istate);
void discard_split_index(struct index_state *istate);
void add_split_index(struct index_state *istate);
void remove_split_index(struct index_state *istate);
-void unshare_split_index(struct index_state *istate, int discard);
#endif
diff --git a/strbuf.c b/strbuf.c
index 00457940cf..c4e91a6656 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -204,13 +204,6 @@ void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2)
strbuf_setlen(sb, sb->len + sb2->len);
}
-void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len)
-{
- strbuf_grow(sb, len);
- memcpy(sb->buf + sb->len, sb->buf + pos, len);
- strbuf_setlen(sb, sb->len + len);
-}
-
void strbuf_addchars(struct strbuf *sb, int c, size_t n)
{
strbuf_grow(sb, n);
@@ -785,14 +778,48 @@ char *xstrfmt(const char *fmt, ...)
return ret;
}
-void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm)
+void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm,
+ int tz_offset, const char *tz_name)
{
+ struct strbuf munged_fmt = STRBUF_INIT;
size_t hint = 128;
size_t len;
if (!*fmt)
return;
+ /*
+ * There is no portable way to pass timezone information to
+ * strftime, so we handle %z and %Z here.
+ */
+ for (;;) {
+ const char *percent = strchrnul(fmt, '%');
+ strbuf_add(&munged_fmt, fmt, percent - fmt);
+ if (!*percent)
+ break;
+ fmt = percent + 1;
+ switch (*fmt) {
+ case '%':
+ strbuf_addstr(&munged_fmt, "%%");
+ fmt++;
+ break;
+ case 'z':
+ strbuf_addf(&munged_fmt, "%+05d", tz_offset);
+ fmt++;
+ break;
+ case 'Z':
+ if (tz_name) {
+ strbuf_addstr(&munged_fmt, tz_name);
+ fmt++;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ strbuf_addch(&munged_fmt, '%');
+ }
+ }
+ fmt = munged_fmt.buf;
+
strbuf_grow(sb, hint);
len = strftime(sb->buf + sb->len, sb->alloc - sb->len, fmt, tm);
@@ -804,17 +831,16 @@ void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm)
* output contains at least one character, and then drop the extra
* character before returning.
*/
- struct strbuf munged_fmt = STRBUF_INIT;
- strbuf_addf(&munged_fmt, "%s ", fmt);
+ strbuf_addch(&munged_fmt, ' ');
while (!len) {
hint *= 2;
strbuf_grow(sb, hint);
len = strftime(sb->buf + sb->len, sb->alloc - sb->len,
munged_fmt.buf, tm);
}
- strbuf_release(&munged_fmt);
len--; /* drop munged space */
}
+ strbuf_release(&munged_fmt);
strbuf_setlen(sb, sb->len + len);
}
diff --git a/strbuf.h b/strbuf.h
index 80047b1bb7..3646a6291b 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -264,12 +264,6 @@ static inline void strbuf_addstr(struct strbuf *sb, const char *s)
extern void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2);
/**
- * Copy part of the buffer from a given position till a given length to the
- * end of the buffer.
- */
-extern void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len);
-
-/**
* This function can be used to expand a format string containing
* placeholders. To that end, it parses the string and calls the specified
* function for every percent sign found.
@@ -340,8 +334,14 @@ extern void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap);
/**
* Add the time specified by `tm`, as formatted by `strftime`.
- */
-extern void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm);
+ * `tz_name` is used to expand %Z internally unless it's NULL.
+ * `tz_offset` is in decimal hhmm format, e.g. -600 means six hours west
+ * of Greenwich, and it's used to expand %z internally. However, tokens
+ * with modifiers (e.g. %Ez) are passed to `strftime`.
+ */
+extern void strbuf_addftime(struct strbuf *sb, const char *fmt,
+ const struct tm *tm, int tz_offset,
+ const char *tz_name);
/**
* Read a given size of data from a FILE* pointer to the buffer.
diff --git a/submodule.c b/submodule.c
index b23c253118..da2b484879 100644
--- a/submodule.c
+++ b/submodule.c
@@ -857,9 +857,9 @@ static int submodule_has_commits(const char *path, struct oid_array *commits)
int has_commit = 1;
/*
- * Perform a cheap, but incorrect check for the existance of 'commits'.
+ * Perform a cheap, but incorrect check for the existence of 'commits'.
* This is done by adding the submodule's object store to the in-core
- * object store, and then querying for each commit's existance. If we
+ * object store, and then querying for each commit's existence. If we
* do not have the commit object anywhere, there is no chance we have
* it in the object store of the correct submodule and have it
* reachable from a ref, so we can fail early without spawning rev-list
diff --git a/t/helper/test-strcmp-offset.c b/t/helper/test-strcmp-offset.c
index 4a45a54e92..e159c9a127 100644
--- a/t/helper/test-strcmp-offset.c
+++ b/t/helper/test-strcmp-offset.c
@@ -11,7 +11,7 @@ int cmd_main(int argc, const char **argv)
result = strcmp_offset(argv[1], argv[2], &offset);
/*
- * Because differnt CRTs behave differently, only rely on signs
+ * Because different CRTs behave differently, only rely on signs
* of the result values.
*/
result = (result < 0 ? -1 :
diff --git a/t/t0006-date.sh b/t/t0006-date.sh
index 42d4ea61ef..7ac9466d50 100755
--- a/t/t0006-date.sh
+++ b/t/t0006-date.sh
@@ -31,9 +31,11 @@ check_show () {
format=$1
time=$2
expect=$3
- test_expect_success $4 "show date ($format:$time)" '
+ prereqs=$4
+ zone=$5
+ test_expect_success $prereqs "show date ($format:$time)" '
echo "$time -> $expect" >expect &&
- test-date show:$format "$time" >actual &&
+ TZ=${zone:-$TZ} test-date show:"$format" "$time" >actual &&
test_cmp expect actual
'
}
@@ -51,6 +53,16 @@ check_show iso-local "$TIME" '2016-06-15 14:13:20 +0000'
check_show raw-local "$TIME" '1466000000 +0000'
check_show unix-local "$TIME" '1466000000'
+check_show 'format:%z' "$TIME" '+0200'
+check_show 'format-local:%z' "$TIME" '+0000'
+check_show 'format:%Z' "$TIME" ''
+check_show 'format-local:%Z' "$TIME" 'UTC'
+check_show 'format:%%z' "$TIME" '%z'
+check_show 'format-local:%%z' "$TIME" '%z'
+
+check_show 'format:%Y-%m-%d %H:%M:%S' "$TIME" '2016-06-15 16:13:20'
+check_show 'format-local:%Y-%m-%d %H:%M:%S' "$TIME" '2016-06-15 09:13:20' '' EST5
+
# arbitrary time absurdly far in the future
FUTURE="5758122296 -0400"
check_show iso "$FUTURE" "2152-06-19 18:24:56 -0400" TIME_IS_64BIT,TIME_T_IS_64BIT
diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh
index 84a9028c43..1bdf38e80d 100755
--- a/t/t2203-add-intent.sh
+++ b/t/t2203-add-intent.sh
@@ -129,10 +129,10 @@ test_expect_success 'cache-tree does skip dir that becomes empty' '
)
'
-test_expect_success 'commit: ita entries ignored in empty intial commit check' '
- git init empty-intial-commit &&
+test_expect_success 'commit: ita entries ignored in empty initial commit check' '
+ git init empty-initial-commit &&
(
- cd empty-intial-commit &&
+ cd empty-initial-commit &&
: >one &&
git add -N one &&
test_must_fail git commit -m nothing-new-here
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 7ca69f4bed..163a14a1c2 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -82,6 +82,7 @@ match 1 0 'foo/bar' 'foo/**/bar'
match 1 0 'foo/bar' 'foo/**/**/bar'
match 0 0 'foo/bar' 'foo?bar'
match 0 0 'foo/bar' 'foo[/]bar'
+match 0 0 'foo/bar' 'foo[^a-z]bar'
match 0 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
match 1 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
match 1 0 'foo' '**/foo'
@@ -225,6 +226,7 @@ pathmatch 0 foo/bba/arr 'foo/*z'
pathmatch 0 foo/bba/arr 'foo/**z'
pathmatch 1 foo/bar 'foo?bar'
pathmatch 1 foo/bar 'foo[/]bar'
+pathmatch 1 foo/bar 'foo[^a-z]bar'
pathmatch 0 foo '*/*/*'
pathmatch 0 foo/bar '*/*/*'
pathmatch 1 foo/bba/arr '*/*/*'
@@ -233,7 +235,7 @@ pathmatch 1 abcXdefXghi '*X*i'
pathmatch 1 ab/cXd/efXg/hi '*/*X*/*/*i'
pathmatch 1 ab/cXd/efXg/hi '*Xg*i'
-# Case-sensitivy features
+# Case-sensitivity features
match 0 x 'a' '[A-Z]'
match 1 x 'A' '[A-Z]'
match 0 x 'A' '[a-z]'
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 10f8f026ff..48d152b9a9 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -100,6 +100,23 @@ test_expect_success 'git branch -m n/n n should work' '
git reflog exists refs/heads/n
'
+# The topmost entry in reflog for branch bbb is about branch creation.
+# Hence, we compare bbb@{1} (instead of bbb@{0}) with aaa@{0}.
+
+test_expect_success 'git branch -m bbb should rename checked out branch' '
+ test_when_finished git branch -D bbb &&
+ test_when_finished git checkout master &&
+ git checkout -b aaa &&
+ git commit --allow-empty -m "a new commit" &&
+ git rev-parse aaa@{0} >expect &&
+ git branch -m bbb &&
+ git rev-parse bbb@{1} >actual &&
+ test_cmp expect actual &&
+ git symbolic-ref HEAD >actual &&
+ echo refs/heads/bbb >expect &&
+ test_cmp expect actual
+'
+
test_expect_success 'git branch -m o/o o should fail when o/p exists' '
git branch o/o &&
git branch o/p &&
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 5bd0275930..37821d2454 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -169,6 +169,13 @@ test_expect_success 'reflog for the branch shows state before rebase' '
test $(git rev-parse branch1@{1}) = $(git rev-parse original-branch1)
'
+test_expect_success 'reflog for the branch shows correct finish message' '
+ printf "rebase -i (finish): refs/heads/branch1 onto %s\n" \
+ "$(git rev-parse branch2)" >expected &&
+ git log -g --pretty=%gs -1 refs/heads/branch1 >actual &&
+ test_cmp expected actual
+'
+
test_expect_success 'exchange two commits' '
set_fake_editor &&
FAKE_LINES="2 1" git rebase -i HEAD~2 &&
diff --git a/t/t3420-rebase-autostash.sh b/t/t3420-rebase-autostash.sh
index ab8a63e8d6..e243700660 100755
--- a/t/t3420-rebase-autostash.sh
+++ b/t/t3420-rebase-autostash.sh
@@ -33,7 +33,123 @@ test_expect_success setup '
git commit -m "related commit"
'
-testrebase() {
+create_expected_success_am () {
+ cat >expected <<-EOF
+ $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
+ HEAD is now at $(git rev-parse --short feature-branch) third commit
+ First, rewinding head to replay your work on top of it...
+ Applying: second commit
+ Applying: third commit
+ Applied autostash.
+ EOF
+}
+
+create_expected_success_interactive () {
+ q_to_cr >expected <<-EOF
+ $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
+ HEAD is now at $(git rev-parse --short feature-branch) third commit
+ Rebasing (1/2)QRebasing (2/2)QApplied autostash.
+ Successfully rebased and updated refs/heads/rebased-feature-branch.
+ EOF
+}
+
+create_expected_success_merge () {
+ cat >expected <<-EOF
+ $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
+ HEAD is now at $(git rev-parse --short feature-branch) third commit
+ First, rewinding head to replay your work on top of it...
+ Merging unrelated-onto-branch with HEAD~1
+ Merging:
+ $(git rev-parse --short unrelated-onto-branch) unrelated commit
+ $(git rev-parse --short feature-branch^) second commit
+ found 1 common ancestor:
+ $(git rev-parse --short feature-branch~2) initial commit
+ [detached HEAD $(git rev-parse --short rebased-feature-branch~1)] second commit
+ Author: A U Thor <author@example.com>
+ Date: Thu Apr 7 15:14:13 2005 -0700
+ 2 files changed, 2 insertions(+)
+ create mode 100644 file1
+ create mode 100644 file2
+ Committed: 0001 second commit
+ Merging unrelated-onto-branch with HEAD~0
+ Merging:
+ $(git rev-parse --short rebased-feature-branch~1) second commit
+ $(git rev-parse --short feature-branch) third commit
+ found 1 common ancestor:
+ $(git rev-parse --short feature-branch~1) second commit
+ [detached HEAD $(git rev-parse --short rebased-feature-branch)] third commit
+ Author: A U Thor <author@example.com>
+ Date: Thu Apr 7 15:15:13 2005 -0700
+ 1 file changed, 1 insertion(+)
+ create mode 100644 file3
+ Committed: 0002 third commit
+ All done.
+ Applied autostash.
+ EOF
+}
+
+create_expected_failure_am () {
+ cat >expected <<-EOF
+ $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
+ HEAD is now at $(git rev-parse --short feature-branch) third commit
+ First, rewinding head to replay your work on top of it...
+ Applying: second commit
+ Applying: third commit
+ Applying autostash resulted in conflicts.
+ Your changes are safe in the stash.
+ You can run "git stash pop" or "git stash drop" at any time.
+ EOF
+}
+
+create_expected_failure_interactive () {
+ q_to_cr >expected <<-EOF
+ $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
+ HEAD is now at $(git rev-parse --short feature-branch) third commit
+ Rebasing (1/2)QRebasing (2/2)QApplying autostash resulted in conflicts.
+ Your changes are safe in the stash.
+ You can run "git stash pop" or "git stash drop" at any time.
+ Successfully rebased and updated refs/heads/rebased-feature-branch.
+ EOF
+}
+
+create_expected_failure_merge () {
+ cat >expected <<-EOF
+ $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
+ HEAD is now at $(git rev-parse --short feature-branch) third commit
+ First, rewinding head to replay your work on top of it...
+ Merging unrelated-onto-branch with HEAD~1
+ Merging:
+ $(git rev-parse --short unrelated-onto-branch) unrelated commit
+ $(git rev-parse --short feature-branch^) second commit
+ found 1 common ancestor:
+ $(git rev-parse --short feature-branch~2) initial commit
+ [detached HEAD $(git rev-parse --short rebased-feature-branch~1)] second commit
+ Author: A U Thor <author@example.com>
+ Date: Thu Apr 7 15:14:13 2005 -0700
+ 2 files changed, 2 insertions(+)
+ create mode 100644 file1
+ create mode 100644 file2
+ Committed: 0001 second commit
+ Merging unrelated-onto-branch with HEAD~0
+ Merging:
+ $(git rev-parse --short rebased-feature-branch~1) second commit
+ $(git rev-parse --short feature-branch) third commit
+ found 1 common ancestor:
+ $(git rev-parse --short feature-branch~1) second commit
+ [detached HEAD $(git rev-parse --short rebased-feature-branch)] third commit
+ Author: A U Thor <author@example.com>
+ Date: Thu Apr 7 15:15:13 2005 -0700
+ 1 file changed, 1 insertion(+)
+ create mode 100644 file3
+ Committed: 0002 third commit
+ All done.
+ Applying autostash resulted in conflicts.
+ Your changes are safe in the stash.
+ You can run "git stash pop" or "git stash drop" at any time.
+ EOF
+}
+
+testrebase () {
type=$1
dotest=$2
@@ -51,14 +167,20 @@ testrebase() {
test_config rebase.autostash true &&
git reset --hard &&
git checkout -b rebased-feature-branch feature-branch &&
- test_when_finished git branch -D rebased-feature-branch &&
echo dirty >>file3 &&
- git rebase$type unrelated-onto-branch &&
+ git rebase$type unrelated-onto-branch >actual 2>&1 &&
grep unrelated file4 &&
grep dirty file3 &&
git checkout feature-branch
'
+ test_expect_success "rebase$type --autostash: check output" '
+ test_when_finished git branch -D rebased-feature-branch &&
+ suffix=${type#\ --} && suffix=${suffix:-am} &&
+ create_expected_success_$suffix &&
+ test_i18ncmp expected actual
+ '
+
test_expect_success "rebase$type: dirty index, non-conflicting rebase" '
test_config rebase.autostash true &&
git reset --hard &&
@@ -137,10 +259,9 @@ testrebase() {
test_config rebase.autostash true &&
git reset --hard &&
git checkout -b rebased-feature-branch feature-branch &&
- test_when_finished git branch -D rebased-feature-branch &&
echo dirty >file4 &&
git add file4 &&
- git rebase$type unrelated-onto-branch &&
+ git rebase$type unrelated-onto-branch >actual 2>&1 &&
test_path_is_missing $dotest &&
git reset --hard &&
grep unrelated file4 &&
@@ -149,6 +270,13 @@ testrebase() {
git stash pop &&
grep dirty file4
'
+
+ test_expect_success "rebase$type: check output with conflicting stash" '
+ test_when_finished git branch -D rebased-feature-branch &&
+ suffix=${type#\ --} && suffix=${suffix:-am} &&
+ create_expected_failure_$suffix &&
+ test_i18ncmp expected actual
+ '
}
test_expect_success "rebase: fast-forward rebase" '
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index 2ecb43a616..2f3e7cea64 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -477,4 +477,12 @@ test_expect_success 'add -p does not expand argument lists' '
! grep not-changed trace.out
'
+test_expect_success 'hunk-editing handles custom comment char' '
+ git reset --hard &&
+ echo change >>file &&
+ test_config core.commentChar "\$" &&
+ echo e | GIT_EDITOR=true git add -p &&
+ git diff --exit-code
+'
+
test_done
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 3b4bed5c9a..4046817d70 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -812,6 +812,22 @@ test_expect_success 'stash -- <pathspec> stashes and restores the file' '
test_path_is_file bar
'
+test_expect_success 'stash -- <pathspec> stashes in subdirectory' '
+ mkdir sub &&
+ >foo &&
+ >bar &&
+ git add foo bar &&
+ (
+ cd sub &&
+ git stash push -- ../foo
+ ) &&
+ test_path_is_file bar &&
+ test_path_is_missing foo &&
+ git stash pop &&
+ test_path_is_file foo &&
+ test_path_is_file bar
+'
+
test_expect_success 'stash with multiple pathspec arguments' '
>foo &&
>bar &&
diff --git a/t/t4005-diff-rename-2.sh b/t/t4005-diff-rename-2.sh
index 135addbfbd..f542d2929d 100755
--- a/t/t4005-diff-rename-2.sh
+++ b/t/t4005-diff-rename-2.sh
@@ -3,84 +3,75 @@
# Copyright (c) 2005 Junio C Hamano
#
-test_description='Same rename detection as t4003 but testing diff-raw.
+test_description='Same rename detection as t4003 but testing diff-raw.'
-'
. ./test-lib.sh
. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
-test_expect_success \
- 'prepare reference tree' \
- 'cat "$TEST_DIRECTORY"/diff-lib/COPYING >COPYING &&
- echo frotz >rezrov &&
- git update-index --add COPYING rezrov &&
- tree=$(git write-tree) &&
- echo $tree'
-
-test_expect_success \
- 'prepare work tree' \
- 'sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 &&
- sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 &&
- rm -f COPYING &&
- git update-index --add --remove COPYING COPYING.?'
+test_expect_success 'setup reference tree' '
+ cat "$TEST_DIRECTORY"/diff-lib/COPYING >COPYING &&
+ echo frotz >rezrov &&
+ git update-index --add COPYING rezrov &&
+ tree=$(git write-tree) &&
+ echo $tree &&
+ sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 &&
+ sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 &&
+ origoid=$(git hash-object COPYING) &&
+ oid1=$(git hash-object COPYING.1) &&
+ oid2=$(git hash-object COPYING.2)
+'
+################################################################
# tree has COPYING and rezrov. work tree has COPYING.1 and COPYING.2,
# both are slightly edited, and unchanged rezrov. We say COPYING.1
# and COPYING.2 are based on COPYING, and do not say anything about
# rezrov.
-git diff-index -C $tree >current
-
-cat >expected <<\EOF
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 COPYING COPYING.1
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 06c67961bbaed34a127f76d261f4c0bf73eda471 R1234 COPYING COPYING.2
-EOF
+test_expect_success 'validate output from rename/copy detection (#1)' '
+ rm -f COPYING &&
+ git update-index --add --remove COPYING COPYING.? &&
-test_expect_success \
- 'validate output from rename/copy detection (#1)' \
- 'compare_diff_raw current expected'
+ cat <<-EOF >expected &&
+ :100644 100644 $origoid $oid1 C1234 COPYING COPYING.1
+ :100644 100644 $origoid $oid2 R1234 COPYING COPYING.2
+ EOF
+ git diff-index -C $tree >current &&
+ compare_diff_raw expected current
+'
################################################################
-
-test_expect_success \
- 'prepare work tree again' \
- 'mv COPYING.2 COPYING &&
- git update-index --add --remove COPYING COPYING.1 COPYING.2'
-
# tree has COPYING and rezrov. work tree has COPYING and COPYING.1,
# both are slightly edited, and unchanged rezrov. We say COPYING.1
# is based on COPYING and COPYING is still there, and do not say anything
# about rezrov.
-git diff-index -C $tree >current
-cat >expected <<\EOF
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 06c67961bbaed34a127f76d261f4c0bf73eda471 M COPYING
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 COPYING COPYING.1
-EOF
+test_expect_success 'validate output from rename/copy detection (#2)' '
+ mv COPYING.2 COPYING &&
+ git update-index --add --remove COPYING COPYING.1 COPYING.2 &&
-test_expect_success \
- 'validate output from rename/copy detection (#2)' \
- 'compare_diff_raw current expected'
+ cat <<-EOF >expected &&
+ :100644 100644 $origoid $oid2 M COPYING
+ :100644 100644 $origoid $oid1 C1234 COPYING COPYING.1
+ EOF
+ git diff-index -C $tree >current &&
+ compare_diff_raw current expected
+'
################################################################
-
# tree has COPYING and rezrov. work tree has the same COPYING and
# copy-edited COPYING.1, and unchanged rezrov. We should not say
# anything about rezrov or COPYING, since the revised again diff-raw
# nows how to say Copy.
-test_expect_success \
- 'prepare work tree once again' \
- 'cat "$TEST_DIRECTORY"/diff-lib/COPYING >COPYING &&
- git update-index --add --remove COPYING COPYING.1'
-
-git diff-index -C --find-copies-harder $tree >current
-cat >expected <<\EOF
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 COPYING COPYING.1
-EOF
+test_expect_success 'validate output from rename/copy detection (#3)' '
+ cat "$TEST_DIRECTORY"/diff-lib/COPYING >COPYING &&
+ git update-index --add --remove COPYING COPYING.1 &&
-test_expect_success \
- 'validate output from rename/copy detection (#3)' \
- 'compare_diff_raw current expected'
+ cat <<-EOF >expected &&
+ :100644 100644 $origoid $oid1 C1234 COPYING COPYING.1
+ EOF
+ git diff-index -C --find-copies-harder $tree >current &&
+ compare_diff_raw current expected
+'
test_done
diff --git a/t/t4041-diff-submodule-option.sh b/t/t4041-diff-submodule-option.sh
index 2d9731b52d..058ee0829d 100755
--- a/t/t4041-diff-submodule-option.sh
+++ b/t/t4041-diff-submodule-option.sh
@@ -430,9 +430,11 @@ test_expect_success 'deleted submodule' '
test_cmp expected actual
'
-test_create_repo sm2 &&
-head7=$(add_file sm2 foo8 foo9) &&
-git add sm2
+test_expect_success 'create second submodule' '
+ test_create_repo sm2 &&
+ head7=$(add_file sm2 foo8 foo9) &&
+ git add sm2
+'
test_expect_success 'multiple submodules' '
git diff-index -p --submodule=log HEAD >actual &&
diff --git a/t/t4060-diff-submodule-option-diff-format.sh b/t/t4060-diff-submodule-option-diff-format.sh
index 33ec26d755..4b168d0ed7 100755
--- a/t/t4060-diff-submodule-option-diff-format.sh
+++ b/t/t4060-diff-submodule-option-diff-format.sh
@@ -643,9 +643,11 @@ test_expect_success 'deleted submodule' '
test_cmp expected actual
'
-test_create_repo sm2 &&
-head7=$(add_file sm2 foo8 foo9) &&
-git add sm2
+test_expect_success 'create second submodule' '
+ test_create_repo sm2 &&
+ head7=$(add_file sm2 foo8 foo9) &&
+ git add sm2
+'
test_expect_success 'multiple submodules' '
git diff-index -p --submodule=diff HEAD >actual &&
diff --git a/t/t4129-apply-samemode.sh b/t/t4129-apply-samemode.sh
index c268298eaf..5cdd76dfa7 100755
--- a/t/t4129-apply-samemode.sh
+++ b/t/t4129-apply-samemode.sh
@@ -13,7 +13,9 @@ test_expect_success setup '
echo modified >file &&
git diff --stat -p >patch-0.txt &&
chmod +x file &&
- git diff --stat -p >patch-1.txt
+ git diff --stat -p >patch-1.txt &&
+ sed "s/^\(new mode \).*/\1/" <patch-1.txt >patch-empty-mode.txt &&
+ sed "s/^\(new mode \).*/\1garbage/" <patch-1.txt >patch-bogus-mode.txt
'
test_expect_success FILEMODE 'same mode (no index)' '
@@ -59,4 +61,16 @@ test_expect_success FILEMODE 'mode update (index only)' '
git ls-files -s file | grep "^100755"
'
+test_expect_success FILEMODE 'empty mode is rejected' '
+ git reset --hard &&
+ test_must_fail git apply patch-empty-mode.txt 2>err &&
+ test_i18ngrep "invalid mode" err
+'
+
+test_expect_success FILEMODE 'bogus mode is rejected' '
+ git reset --hard &&
+ test_must_fail git apply patch-bogus-mode.txt 2>err &&
+ test_i18ngrep "invalid mode" err
+'
+
test_done
diff --git a/t/t4133-apply-filenames.sh b/t/t4133-apply-filenames.sh
index 2ecb4216b7..c5ed3b17c4 100755
--- a/t/t4133-apply-filenames.sh
+++ b/t/t4133-apply-filenames.sh
@@ -35,4 +35,28 @@ test_expect_success 'apply diff with inconsistent filenames in headers' '
test_i18ngrep "inconsistent old filename" err
'
+test_expect_success 'apply diff with new filename missing from headers' '
+ cat >missing_new_filename.diff <<-\EOF &&
+ diff --git a/f b/f
+ index 0000000..d00491f
+ --- a/f
+ @@ -0,0 +1 @@
+ +1
+ EOF
+ test_must_fail git apply missing_new_filename.diff 2>err &&
+ test_i18ngrep "lacks filename information" err
+'
+
+test_expect_success 'apply diff with old filename missing from headers' '
+ cat >missing_old_filename.diff <<-\EOF &&
+ diff --git a/f b/f
+ index d00491f..0000000
+ +++ b/f
+ @@ -1 +0,0 @@
+ -1
+ EOF
+ test_must_fail git apply missing_old_filename.diff 2>err &&
+ test_i18ngrep "lacks filename information" err
+'
+
test_done
diff --git a/t/t4136-apply-check.sh b/t/t4136-apply-check.sh
index 4b0a374b63..6d92872318 100755
--- a/t/t4136-apply-check.sh
+++ b/t/t4136-apply-check.sh
@@ -29,4 +29,22 @@ test_expect_success 'apply exits non-zero with no-op patch' '
test_must_fail git apply --check input
'
+test_expect_success 'invalid combination: create and copy' '
+ test_must_fail git apply --check - <<-\EOF
+ diff --git a/1 b/2
+ new file mode 100644
+ copy from 1
+ copy to 2
+ EOF
+'
+
+test_expect_success 'invalid combination: create and rename' '
+ test_must_fail git apply --check - <<-\EOF
+ diff --git a/1 b/2
+ new file mode 100644
+ rename from 1
+ rename to 2
+ EOF
+'
+
test_done
diff --git a/t/t4213-log-tabexpand.sh b/t/t4213-log-tabexpand.sh
index e01a8f6ac9..7f90f58c03 100755
--- a/t/t4213-log-tabexpand.sh
+++ b/t/t4213-log-tabexpand.sh
@@ -37,7 +37,7 @@ count_expand ()
# Prefix the output with the command line arguments, and
# replace SP with a dot both in the expecte and actual output
- # so that test_cmp would show the differene together with the
+ # so that test_cmp would show the difference together with the
# breakage in a way easier to consume by the debugging user.
{
echo "git show -s $*"
diff --git a/t/t5100-mailinfo.sh b/t/t5100-mailinfo.sh
index 7171f67539..9690dcad4f 100755
--- a/t/t5100-mailinfo.sh
+++ b/t/t5100-mailinfo.sh
@@ -171,4 +171,46 @@ test_expect_success 'mailinfo with mailinfo.scissors config' '
'
+test_expect_success 'mailinfo no options' '
+ subj="$(echo "Subject: [PATCH] [other] [PATCH] message" |
+ git mailinfo /dev/null /dev/null)" &&
+ test z"$subj" = z"Subject: message"
+'
+
+test_expect_success 'mailinfo -k' '
+ subj="$(echo "Subject: [PATCH] [other] [PATCH] message" |
+ git mailinfo -k /dev/null /dev/null)" &&
+ test z"$subj" = z"Subject: [PATCH] [other] [PATCH] message"
+'
+
+test_expect_success 'mailinfo -b no [PATCH]' '
+ subj="$(echo "Subject: [other] message" |
+ git mailinfo -b /dev/null /dev/null)" &&
+ test z"$subj" = z"Subject: [other] message"
+'
+
+test_expect_success 'mailinfo -b leading [PATCH]' '
+ subj="$(echo "Subject: [PATCH] [other] message" |
+ git mailinfo -b /dev/null /dev/null)" &&
+ test z"$subj" = z"Subject: [other] message"
+'
+
+test_expect_success 'mailinfo -b double [PATCH]' '
+ subj="$(echo "Subject: [PATCH] [PATCH] message" |
+ git mailinfo -b /dev/null /dev/null)" &&
+ test z"$subj" = z"Subject: message"
+'
+
+test_expect_failure 'mailinfo -b trailing [PATCH]' '
+ subj="$(echo "Subject: [other] [PATCH] message" |
+ git mailinfo -b /dev/null /dev/null)" &&
+ test z"$subj" = z"Subject: [other] message"
+'
+
+test_expect_failure 'mailinfo -b separated double [PATCH]' '
+ subj="$(echo "Subject: [PATCH] [other] [PATCH] message" |
+ git mailinfo -b /dev/null /dev/null)" &&
+ test z"$subj" = z"Subject: [other] message"
+'
+
test_done
diff --git a/t/t5614-clone-submodules-shallow.sh b/t/t5614-clone-submodules-shallow.sh
index a87d329656..e4e6ea4d52 100755
--- a/t/t5614-clone-submodules-shallow.sh
+++ b/t/t5614-clone-submodules-shallow.sh
@@ -71,7 +71,7 @@ test_expect_success 'clone follows shallow recommendation' '
test_when_finished "rm -rf super_clone" &&
git config -f .gitmodules submodule.sub.shallow true &&
git add .gitmodules &&
- git commit -m "recommed shallow for sub" &&
+ git commit -m "recommend shallow for sub" &&
git clone --recurse-submodules --no-local "file://$pwd/." super_clone &&
(
cd super_clone &&
@@ -105,7 +105,7 @@ test_expect_success 'clone follows non shallow recommendation' '
test_when_finished "rm -rf super_clone" &&
git config -f .gitmodules submodule.sub.shallow false &&
git add .gitmodules &&
- git commit -m "recommed non shallow for sub" &&
+ git commit -m "recommend non shallow for sub" &&
git clone --recurse-submodules --no-local "file://$pwd/." super_clone &&
(
cd super_clone &&
diff --git a/t/t6002-rev-list-bisect.sh b/t/t6002-rev-list-bisect.sh
index 3bf2759eae..534903bbd2 100755
--- a/t/t6002-rev-list-bisect.sh
+++ b/t/t6002-rev-list-bisect.sh
@@ -235,4 +235,18 @@ test_sequence "--bisect"
#
#
+
+test_expect_success '--bisect can default to good/bad refs' '
+ git update-ref refs/bisect/bad c3 &&
+ good=$(git rev-parse b1) &&
+ git update-ref refs/bisect/good-$good $good &&
+ good=$(git rev-parse c1) &&
+ git update-ref refs/bisect/good-$good $good &&
+
+ # the only thing between c3 and c1 is c2
+ git rev-parse c2 >expect &&
+ git rev-list --bisect >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index 16952e44fc..aa74eb8f0d 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -244,7 +244,7 @@ test_expect_success 'setup and absorb a submodule' '
test_cmp expect out
'
-test_expect_success 'describe chokes on severly broken submodules' '
+test_expect_success 'describe chokes on severely broken submodules' '
mv .git/modules/sub1/ .git/modules/sub_moved &&
test_must_fail git describe --dirty
'
diff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh
index 366746f0d4..4e4c455502 100755
--- a/t/t7401-submodule-summary.sh
+++ b/t/t7401-submodule-summary.sh
@@ -241,9 +241,11 @@ EOF
test_cmp expected actual
"
-test_create_repo sm2 &&
-head7=$(add_file sm2 foo8 foo9) &&
-git add sm2
+test_expect_success 'create second submodule' '
+ test_create_repo sm2 &&
+ head7=$(add_file sm2 foo8 foo9) &&
+ git add sm2
+'
test_expect_success 'multiple submodules' "
git submodule summary >actual &&
diff --git a/t/t7412-submodule-absorbgitdirs.sh b/t/t7412-submodule-absorbgitdirs.sh
index e2bbb449b6..ce74c12da2 100755
--- a/t/t7412-submodule-absorbgitdirs.sh
+++ b/t/t7412-submodule-absorbgitdirs.sh
@@ -33,7 +33,7 @@ test_expect_success 'absorb the git dir' '
test_cmp expect.2 actual.2
'
-test_expect_success 'absorbing does not fail for deinitalized submodules' '
+test_expect_success 'absorbing does not fail for deinitialized submodules' '
test_when_finished "git submodule update --init" &&
git submodule deinit --all &&
git submodule absorbgitdirs &&
diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh
index 9c785b07ec..c8e7e98331 100755
--- a/t/t7413-submodule-is-active.sh
+++ b/t/t7413-submodule-is-active.sh
@@ -2,7 +2,7 @@
test_description='Test submodule--helper is-active
-This test verifies that `git submodue--helper is-active` correclty identifies
+This test verifies that `git submodue--helper is-active` correctly identifies
submodules which are "active" and interesting to the user.
'
diff --git a/t/t7414-submodule-mistakes.sh b/t/t7414-submodule-mistakes.sh
new file mode 100755
index 0000000000..f2e7df59cf
--- /dev/null
+++ b/t/t7414-submodule-mistakes.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+test_description='handling of common mistakes people may make with submodules'
+. ./test-lib.sh
+
+test_expect_success 'create embedded repository' '
+ git init embed &&
+ test_commit -C embed one
+'
+
+test_expect_success 'git-add on embedded repository warns' '
+ test_when_finished "git rm --cached -f embed" &&
+ git add embed 2>stderr &&
+ test_i18ngrep warning stderr
+'
+
+test_expect_success '--no-warn-embedded-repo suppresses warning' '
+ test_when_finished "git rm --cached -f embed" &&
+ git add --no-warn-embedded-repo embed 2>stderr &&
+ test_i18ngrep ! warning stderr
+'
+
+test_expect_success 'no warning when updating entry' '
+ test_when_finished "git rm --cached -f embed" &&
+ git add embed &&
+ git -C embed commit --allow-empty -m two &&
+ git add embed 2>stderr &&
+ test_i18ngrep ! warning stderr
+'
+
+test_expect_success 'submodule add does not warn' '
+ test_when_finished "git rm -rf submodule .gitmodules" &&
+ git submodule add ./embed submodule 2>stderr &&
+ test_i18ngrep ! warning stderr
+'
+
+test_done
diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh
index 0b6da7ae1f..fa61b1a4ee 100755
--- a/t/t7501-commit.sh
+++ b/t/t7501-commit.sh
@@ -18,7 +18,7 @@ test_expect_success 'initial status' '
echo bongo bongo >file &&
git add file &&
git status >actual &&
- test_i18ngrep "Initial commit" actual
+ test_i18ngrep "No commits yet" actual
'
test_expect_success 'fail initial amend' '
diff --git a/t/t7508-status.sh b/t/t7508-status.sh
index 79427840a4..43d19a9b22 100755
--- a/t/t7508-status.sh
+++ b/t/t7508-status.sh
@@ -1603,9 +1603,71 @@ EOF
test_expect_success 'git commit -m will commit a staged but ignored submodule' '
git commit -uno -m message &&
git status -s --ignore-submodules=dirty >output &&
- test_i18ngrep ! "^M. sm" output &&
+ test_i18ngrep ! "^M. sm" output &&
git config --remove-section submodule.subname &&
git config -f .gitmodules --remove-section submodule.subname
'
+test_expect_success 'show stash info with "--show-stash"' '
+ git reset --hard &&
+ git stash clear &&
+ echo 1 >file &&
+ git add file &&
+ git stash &&
+ git status >expected_default &&
+ git status --show-stash >expected_with_stash &&
+ test_i18ngrep "^Your stash currently has 1 entry$" expected_with_stash
+'
+
+test_expect_success 'no stash info with "--show-stash --no-show-stash"' '
+ git status --show-stash --no-show-stash >expected_without_stash &&
+ test_cmp expected_default expected_without_stash
+'
+
+test_expect_success '"status.showStash=false" weaker than "--show-stash"' '
+ git -c status.showStash=false status --show-stash >actual &&
+ test_cmp expected_with_stash actual
+'
+
+test_expect_success '"status.showStash=true" weaker than "--no-show-stash"' '
+ git -c status.showStash=true status --no-show-stash >actual &&
+ test_cmp expected_without_stash actual
+'
+
+test_expect_success 'no additionnal info if no stash entries' '
+ git stash clear &&
+ git -c status.showStash=true status >actual &&
+ test_cmp expected_without_stash actual
+'
+
+test_expect_success '"No commits yet" should be noted in status output' '
+ git checkout --orphan empty-branch-1 &&
+ git status >output &&
+ test_i18ngrep "No commits yet" output
+'
+
+test_expect_success '"No commits yet" should not be noted in status output' '
+ git checkout --orphan empty-branch-2 &&
+ test_commit test-commit-1 &&
+ git status >output &&
+ test_i18ngrep ! "No commits yet" output
+'
+
+test_expect_success '"Initial commit" should be noted in commit template' '
+ git checkout --orphan empty-branch-3 &&
+ touch to_be_committed_1 &&
+ git add to_be_committed_1 &&
+ git commit --dry-run >output &&
+ test_i18ngrep "Initial commit" output
+'
+
+test_expect_success '"Initial commit" should not be noted in commit template' '
+ git checkout --orphan empty-branch-4 &&
+ test_commit test-commit-2 &&
+ touch to_be_committed_2 &&
+ git add to_be_committed_2 &&
+ git commit --dry-run >output &&
+ test_i18ngrep ! "Initial commit" output
+'
+
test_done
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 2e0ba3ebd8..67b8c50a5a 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -2822,7 +2822,7 @@ test_expect_success 'S: filemodify with garbage after sha1 must fail' '
#
# notemodify, three ways to say dataref
#
-test_expect_success 'S: notemodify with garabge after mark dataref must fail' '
+test_expect_success 'S: notemodify with garbage after mark dataref must fail' '
test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
commit refs/heads/S
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
diff --git a/transport-helper.c b/transport-helper.c
index 36408046eb..33cff38cc0 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -242,8 +242,7 @@ static int disconnect_helper(struct transport *transport)
close(data->helper->out);
fclose(data->out);
res = finish_command(data->helper);
- free(data->helper);
- data->helper = NULL;
+ FREE_AND_NULL(data->helper);
}
return res;
}
@@ -711,43 +710,35 @@ static int push_update_ref_status(struct strbuf *buf,
if (!strcmp(msg, "no match")) {
status = REF_STATUS_NONE;
- free(msg);
- msg = NULL;
+ FREE_AND_NULL(msg);
}
else if (!strcmp(msg, "up to date")) {
status = REF_STATUS_UPTODATE;
- free(msg);
- msg = NULL;
+ FREE_AND_NULL(msg);
}
else if (!strcmp(msg, "non-fast forward")) {
status = REF_STATUS_REJECT_NONFASTFORWARD;
- free(msg);
- msg = NULL;
+ FREE_AND_NULL(msg);
}
else if (!strcmp(msg, "already exists")) {
status = REF_STATUS_REJECT_ALREADY_EXISTS;
- free(msg);
- msg = NULL;
+ FREE_AND_NULL(msg);
}
else if (!strcmp(msg, "fetch first")) {
status = REF_STATUS_REJECT_FETCH_FIRST;
- free(msg);
- msg = NULL;
+ FREE_AND_NULL(msg);
}
else if (!strcmp(msg, "needs force")) {
status = REF_STATUS_REJECT_NEEDS_FORCE;
- free(msg);
- msg = NULL;
+ FREE_AND_NULL(msg);
}
else if (!strcmp(msg, "stale info")) {
status = REF_STATUS_REJECT_STALE;
- free(msg);
- msg = NULL;
+ FREE_AND_NULL(msg);
}
else if (!strcmp(msg, "forced update")) {
forced = 1;
- free(msg);
- msg = NULL;
+ FREE_AND_NULL(msg);
}
}
diff --git a/transport.c b/transport.c
index b9995306f2..d75ff0514d 100644
--- a/transport.c
+++ b/transport.c
@@ -1146,8 +1146,7 @@ void transport_unlock_pack(struct transport *transport)
{
if (transport->pack_lockfile) {
unlink_or_warn(transport->pack_lockfile);
- free(transport->pack_lockfile);
- transport->pack_lockfile = NULL;
+ FREE_AND_NULL(transport->pack_lockfile);
}
}
diff --git a/tree-diff.c b/tree-diff.c
index 467e381724..bd6d65a409 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -141,8 +141,7 @@ static struct combine_diff_path *path_appendnew(struct combine_diff_path *last,
/* if last->next is !NULL - it is a pre-allocated memory, we can reuse */
p = last->next;
if (p && (alloclen > (intptr_t)p->next)) {
- free(p);
- p = NULL;
+ FREE_AND_NULL(p);
}
if (!p) {
@@ -559,8 +558,7 @@ struct combine_diff_path *diff_tree_paths(
* (see path_appendnew() for details about why)
*/
if (p->next) {
- free(p->next);
- p->next = NULL;
+ FREE_AND_NULL(p->next);
}
return p;
diff --git a/tree.c b/tree.c
index dd69423d9a..b224115e0f 100644
--- a/tree.c
+++ b/tree.c
@@ -234,8 +234,7 @@ int parse_tree_gently(struct tree *item, int quiet_on_missing)
void free_tree_buffer(struct tree *tree)
{
- free(tree->buffer);
- tree->buffer = NULL;
+ FREE_AND_NULL(tree->buffer);
tree->size = 0;
tree->object.parsed = 0;
}
diff --git a/usage.c b/usage.c
index 2f87ca69a8..1ea7df9a20 100644
--- a/usage.c
+++ b/usage.c
@@ -44,7 +44,23 @@ static void warn_builtin(const char *warn, va_list params)
static int die_is_recursing_builtin(void)
{
static int dying;
- return dying++;
+ /*
+ * Just an arbitrary number X where "a < x < b" where "a" is
+ * "maximum number of pthreads we'll ever plausibly spawn" and
+ * "b" is "something less than Inf", since the point is to
+ * prevent infinite recursion.
+ */
+ static const int recursion_limit = 1024;
+
+ dying++;
+ if (dying > recursion_limit) {
+ return 1;
+ } else if (dying == 2) {
+ warning("die() called many times. Recursion error or racy threaded death!");
+ return 0;
+ } else {
+ return 0;
+ }
}
/* If we are in a dlopen()ed .so write to a global variable would segfault
diff --git a/wt-status.c b/wt-status.c
index bf651f16fa..8d2fb35b08 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -137,6 +137,7 @@ void wt_status_prepare(struct wt_status *s)
s->untracked.strdup_strings = 1;
s->ignored.strdup_strings = 1;
s->show_branch = -1; /* unspecified */
+ s->show_stash = 0;
s->display_comment_prefix = 0;
}
@@ -801,6 +802,27 @@ static void wt_longstatus_print_changed(struct wt_status *s)
wt_longstatus_print_trailer(s);
}
+static int stash_count_refs(struct object_id *ooid, struct object_id *noid,
+ const char *email, timestamp_t timestamp, int tz,
+ const char *message, void *cb_data)
+{
+ int *c = cb_data;
+ (*c)++;
+ return 0;
+}
+
+static void wt_longstatus_print_stash_summary(struct wt_status *s)
+{
+ int stash_count = 0;
+
+ for_each_reflog_ent("refs/stash", stash_count_refs, &stash_count);
+ if (stash_count > 0)
+ status_printf_ln(s, GIT_COLOR_NORMAL,
+ Q_("Your stash currently has %d entry",
+ "Your stash currently has %d entries", stash_count),
+ stash_count);
+}
+
static void wt_longstatus_print_submodule_summary(struct wt_status *s, int uncommitted)
{
struct child_process sm_summary = CHILD_PROCESS_INIT;
@@ -1579,7 +1601,10 @@ static void wt_longstatus_print(struct wt_status *s)
if (s->is_initial) {
status_printf_ln(s, color(WT_STATUS_HEADER, s), "%s", "");
- status_printf_ln(s, color(WT_STATUS_HEADER, s), _("Initial commit"));
+ status_printf_ln(s, color(WT_STATUS_HEADER, s),
+ s->commit_template
+ ? _("Initial commit")
+ : _("No commits yet"));
status_printf_ln(s, color(WT_STATUS_HEADER, s), "%s", "");
}
@@ -1642,6 +1667,8 @@ static void wt_longstatus_print(struct wt_status *s)
} else
printf(_("nothing to commit, working tree clean\n"));
}
+ if(s->show_stash)
+ wt_longstatus_print_stash_summary(s);
}
static void wt_shortstatus_unmerged(struct string_list_item *it,
@@ -1749,7 +1776,7 @@ static void wt_shortstatus_print_tracking(struct wt_status *s)
#define LABEL(string) (s->no_gettext ? (string) : _(string))
if (s->is_initial)
- color_fprintf(s->fp, header_color, LABEL(N_("Initial commit on ")));
+ color_fprintf(s->fp, header_color, LABEL(N_("No commits yet on ")));
if (!strcmp(s->branch, "HEAD")) {
color_fprintf(s->fp, color(WT_STATUS_NOBRANCH, s), "%s",
diff --git a/wt-status.h b/wt-status.h
index 8a3864783b..64f4d33ea1 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -76,7 +76,9 @@ struct wt_status {
char color_palette[WT_STATUS_MAXSLOT][COLOR_MAXLEN];
unsigned colopts;
int null_termination;
+ int commit_template;
int show_branch;
+ int show_stash;
int hints;
enum wt_status_format status_format;