summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/CodingGuidelines11
-rw-r--r--Documentation/RelNotes/1.9.1.txt59
-rw-r--r--Documentation/RelNotes/2.0.0.txt160
-rw-r--r--Documentation/config.txt29
-rw-r--r--Documentation/git-am.txt13
-rw-r--r--Documentation/git-archive.txt5
-rw-r--r--Documentation/git-commit.txt8
-rw-r--r--Documentation/git-cvsimport.txt4
-rw-r--r--Documentation/git-filter-branch.txt4
-rw-r--r--Documentation/git-pack-objects.txt2
-rw-r--r--Documentation/git-repack.txt8
-rw-r--r--Documentation/git-request-pull.txt55
-rw-r--r--Documentation/git-rev-parse.txt34
-rw-r--r--Documentation/git-stash.txt2
-rw-r--r--Documentation/git-status.txt2
-rw-r--r--Documentation/git-submodule.txt15
-rw-r--r--Documentation/git-tag.txt6
-rw-r--r--Documentation/git-upload-archive.txt32
-rw-r--r--Documentation/git.txt8
-rw-r--r--Documentation/gitcore-tutorial.txt2
-rw-r--r--Documentation/gitcvs-migration.txt2
-rw-r--r--Documentation/gitignore.txt3
-rw-r--r--Documentation/gitk.txt10
-rw-r--r--Documentation/gitremote-helpers.txt4
-rw-r--r--Documentation/gitrepository-layout.txt4
-rw-r--r--Documentation/gitweb.txt2
-rw-r--r--Documentation/glossary-content.txt4
-rw-r--r--Documentation/merge-strategies.txt4
-rw-r--r--Documentation/technical/http-protocol.txt4
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--Makefile34
-rw-r--r--archive.c17
-rw-r--r--attr.c7
-rw-r--r--branch.c12
-rw-r--r--builtin/add.c21
-rw-r--r--builtin/apply.c2
-rw-r--r--builtin/branch.c2
-rw-r--r--builtin/cat-file.c15
-rw-r--r--builtin/check-attr.c3
-rw-r--r--builtin/checkout.c8
-rw-r--r--builtin/clean.c20
-rw-r--r--builtin/clone.c4
-rw-r--r--builtin/commit.c49
-rw-r--r--builtin/config.c104
-rw-r--r--builtin/describe.c2
-rw-r--r--builtin/for-each-ref.c2
-rw-r--r--builtin/fsck.c8
-rw-r--r--builtin/gc.c2
-rw-r--r--builtin/index-pack.c6
-rw-r--r--builtin/ls-remote.c2
-rw-r--r--builtin/merge.c6
-rw-r--r--builtin/mktree.c5
-rw-r--r--builtin/mv.c12
-rw-r--r--builtin/name-rev.c2
-rw-r--r--builtin/notes.c6
-rw-r--r--builtin/pack-objects.c86
-rw-r--r--builtin/prune-packed.c2
-rw-r--r--builtin/prune.c4
-rw-r--r--builtin/receive-pack.c16
-rw-r--r--builtin/reflog.c2
-rw-r--r--builtin/repack.c13
-rw-r--r--builtin/replace.c4
-rw-r--r--builtin/reset.c7
-rw-r--r--builtin/rev-parse.c13
-rw-r--r--builtin/show-branch.c2
-rw-r--r--builtin/tag.c79
-rw-r--r--builtin/unpack-objects.c4
-rw-r--r--bulk-checkin.c8
-rw-r--r--bundle.c8
-rw-r--r--cache-tree.c30
-rw-r--r--cache.h107
-rw-r--r--commit.c46
-rw-r--r--commit.h5
-rw-r--r--compat/fnmatch/fnmatch.c494
-rw-r--r--compat/fnmatch/fnmatch.h84
-rwxr-xr-xcompat/vcbuild/scripts/clink.pl2
-rw-r--r--config.c60
-rw-r--r--config.mak.uname11
-rw-r--r--configure.ac30
-rw-r--r--connect.c2
-rw-r--r--contrib/completion/git-completion.bash19
-rwxr-xr-xcontrib/contacts/git-contacts2
-rwxr-xr-xcontrib/remote-helpers/git-remote-bzr31
-rwxr-xr-xcontrib/remote-helpers/test-bzr.sh22
-rwxr-xr-xcontrib/remote-helpers/test-hg.sh4
-rwxr-xr-xcontrib/subtree/git-subtree.sh1
-rw-r--r--date.c23
-rw-r--r--diff-no-index.c9
-rw-r--r--diff.c26
-rw-r--r--diffcore-order.c2
-rw-r--r--diffcore-rename.c14
-rw-r--r--diffcore.h2
-rw-r--r--dir.c36
-rw-r--r--entry.c64
-rw-r--r--environment.c4
-rw-r--r--fast-import.c33
-rw-r--r--fetch-pack.c11
-rw-r--r--fsck.c56
-rwxr-xr-xgit-add--interactive.perl3
-rwxr-xr-xgit-bisect.sh8
-rw-r--r--git-compat-util.h19
-rwxr-xr-xgit-difftool.perl18
-rw-r--r--git-rebase--interactive.sh2
-rwxr-xr-xgit-rebase.sh4
-rwxr-xr-xgit-remote-testgit.sh18
-rwxr-xr-xgit-request-pull.sh130
-rwxr-xr-xgit-stash.sh10
-rwxr-xr-xgit-submodule.sh2
-rw-r--r--git.c2
-rwxr-xr-xgitweb/gitweb.perl2
-rw-r--r--gitweb/static/gitweb.css5
-rw-r--r--grep.c9
-rw-r--r--help.c7
-rw-r--r--http.c26
-rw-r--r--http.h9
-rw-r--r--log-tree.c2
-rw-r--r--match-trees.c11
-rw-r--r--notes-utils.c2
-rw-r--r--object.c29
-rw-r--r--object.h7
-rw-r--r--pack-bitmap-write.c2
-rw-r--r--pack-write.c18
-rw-r--r--pack.h2
-rw-r--r--parse-options.c5
-rw-r--r--patch-ids.c5
-rw-r--r--pretty.c17
-rw-r--r--progress.c3
-rw-r--r--read-cache.c44
-rw-r--r--reflog-walk.c16
-rw-r--r--refs.c4
-rw-r--r--remote-curl.c5
-rw-r--r--remote-testsvn.c4
-rw-r--r--remote.c111
-rw-r--r--remote.h1
-rw-r--r--replace_object.c34
-rw-r--r--revision.c8
-rw-r--r--run-command.c44
-rw-r--r--run-command.h7
-rw-r--r--sh-i18n--envsubst.c12
-rw-r--r--sha1_file.c77
-rw-r--r--shallow.c69
-rw-r--r--strbuf.h18
-rw-r--r--streaming.c4
-rw-r--r--t/Makefile4
-rw-r--r--t/lib-terminal.sh37
-rwxr-xr-xt/t0001-init.sh211
-rwxr-xr-xt/t0003-attributes.sh62
-rwxr-xr-xt/t0008-ignores.sh31
-rwxr-xr-xt/t1020-subdirectory.sh2
-rwxr-xr-xt/t1300-repo-config.sh54
-rwxr-xr-xt/t1302-repo-version.sh2
-rwxr-xr-xt/t1305-config-include.sh32
-rwxr-xr-xt/t1450-fsck.sh14
-rwxr-xr-xt/t1502-rev-parse-parseopt.sh92
-rwxr-xr-xt/t1510-repo-setup.sh4
-rwxr-xr-xt/t1600-index.sh76
-rwxr-xr-xt/t2104-update-index-skip-worktree.sh2
-rwxr-xr-xt/t3070-wildmatch.sh13
-rwxr-xr-xt/t3200-branch.sh22
-rwxr-xr-xt/t3301-notes.sh49
-rwxr-xr-xt/t3400-rebase.sh17
-rwxr-xr-xt/t3404-rebase-interactive.sh69
-rwxr-xr-xt/t3413-rebase-hook.sh6
-rwxr-xr-xt/t4014-format-patch.sh14
-rwxr-xr-xt/t4018-diff-funcname.sh230
-rw-r--r--t/t4018/README18
-rw-r--r--t/t4018/cpp-c++-function4
-rw-r--r--t/t4018/cpp-class-constructor4
-rw-r--r--t/t4018/cpp-class-constructor-mem-init5
-rw-r--r--t/t4018/cpp-class-definition4
-rw-r--r--t/t4018/cpp-class-definition-derived5
-rw-r--r--t/t4018/cpp-class-destructor4
-rw-r--r--t/t4018/cpp-function-returning-global-type4
-rw-r--r--t/t4018/cpp-function-returning-nested5
-rw-r--r--t/t4018/cpp-function-returning-pointer4
-rw-r--r--t/t4018/cpp-function-returning-reference4
-rw-r--r--t/t4018/cpp-gnu-style-function5
-rw-r--r--t/t4018/cpp-namespace-definition4
-rw-r--r--t/t4018/cpp-operator-definition4
-rw-r--r--t/t4018/cpp-skip-access-specifiers8
-rw-r--r--t/t4018/cpp-skip-comment-block9
-rw-r--r--t/t4018/cpp-skip-labels8
-rw-r--r--t/t4018/cpp-struct-definition9
-rw-r--r--t/t4018/cpp-struct-single-line7
-rw-r--r--t/t4018/cpp-template-function-definition4
-rw-r--r--t/t4018/cpp-union-definition4
-rw-r--r--t/t4018/cpp-void-c-function4
-rw-r--r--t/t4018/custom1-pattern17
-rw-r--r--t/t4018/custom2-match-to-end-of-line8
-rw-r--r--t/t4018/custom3-alternation-in-pattern17
-rw-r--r--t/t4018/java-class-member-function8
-rw-r--r--t/t4018/perl-skip-end-of-heredoc8
-rw-r--r--t/t4018/perl-skip-forward-decl10
-rw-r--r--t/t4018/perl-skip-sub-in-pod18
-rw-r--r--t/t4018/perl-sub-definition4
-rw-r--r--t/t4018/perl-sub-definition-kr-brace4
-rwxr-xr-xt/t4020-diff-external.sh30
-rwxr-xr-xt/t4212-log-corrupt.sh45
-rwxr-xr-xt/t5000-tar-tree.sh9
-rwxr-xr-xt/t5150-request-pull.sh24
-rwxr-xr-xt/t5305-include-tag.sh4
-rwxr-xr-xt/t5310-pack-bitmaps.sh5
-rwxr-xr-xt/t5510-fetch.sh6
-rwxr-xr-xt/t5516-fetch-push.sh13
-rwxr-xr-xt/t5529-push-errors.sh48
-rwxr-xr-xt/t5537-fetch-shallow.sh41
-rwxr-xr-xt/t5602-clone-remote-exec.sh13
-rwxr-xr-xt/t5701-clone-local.sh6
-rwxr-xr-xt/t5801-remote-helpers.sh19
-rwxr-xr-xt/t6006-rev-list-format.sh9
-rwxr-xr-xt/t7001-mv.sh13
-rwxr-xr-xt/t7004-tag.sh43
-rwxr-xr-xt/t7006-pager.sh18
-rwxr-xr-xt/t7060-wtstatus.sh14
-rwxr-xr-xt/t7102-reset.sh11
-rwxr-xr-xt/t7300-clean.sh16
-rwxr-xr-xt/t7400-submodule-basic.sh5
-rwxr-xr-xt/t7501-commit.sh36
-rwxr-xr-xt/t7502-commit.sh16
-rwxr-xr-xt/t7505-prepare-commit-msg-hook.sh33
-rwxr-xr-xt/t7512-status-help.sh12
-rwxr-xr-xt/t7514-commit-patch.sh34
-rwxr-xr-xt/t7700-repack.sh18
-rwxr-xr-xt/t7800-difftool.sh14
-rwxr-xr-xt/t7810-grep.sh70
-rwxr-xr-xt/t9001-send-email.sh2
-rwxr-xr-xt/t9130-git-svn-authors-file.sh3
-rwxr-xr-xt/t9154-git-svn-fancy-glob.sh6
-rwxr-xr-xt/t9400-git-cvsserver-server.sh1
-rw-r--r--t/test-lib-functions.sh5
-rw-r--r--t/test-lib.sh11
-rw-r--r--test-wildmatch.c79
-rw-r--r--transport-helper.c25
-rw-r--r--transport.c8
-rw-r--r--unpack-trees.c2
-rw-r--r--upload-pack.c22
-rw-r--r--userdiff.c12
-rw-r--r--utf8.c6
-rw-r--r--versioncmp.c93
-rw-r--r--ws.c7
-rw-r--r--wt-status.c138
-rw-r--r--wt-status.h1
242 files changed, 3224 insertions, 2248 deletions
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines
index ef67b53f72..ed432a80ca 100644
--- a/Documentation/CodingGuidelines
+++ b/Documentation/CodingGuidelines
@@ -126,6 +126,17 @@ For C programs:
"char * string". This makes it easier to understand code
like "char *string, c;".
+ - Use whitespace around operators and keywords, but not inside
+ parentheses and not around functions. So:
+
+ while (condition)
+ func(bar + 1);
+
+ and not:
+
+ while( condition )
+ func (bar+1);
+
- We avoid using braces unnecessarily. I.e.
if (bla) {
diff --git a/Documentation/RelNotes/1.9.1.txt b/Documentation/RelNotes/1.9.1.txt
new file mode 100644
index 0000000000..5b0602053c
--- /dev/null
+++ b/Documentation/RelNotes/1.9.1.txt
@@ -0,0 +1,59 @@
+Git v1.9.1 Release Notes
+========================
+
+Fixes since v1.9.0
+------------------
+
+ * "git clean -d pathspec" did not use the given pathspec correctly
+ and ended up cleaning too much.
+
+ * "git difftool" misbehaved when the repository is bound to the
+ working tree with the ".git file" mechanism, where a textual file
+ ".git" tells us where it is.
+
+ * "git push" did not pay attention to branch.*.pushremote if it is
+ defined earlier than remote.pushdefault; the order of these two
+ variables in the configuration file should not matter, but it did
+ by mistake.
+
+ * Codepaths that parse timestamps in commit objects have been
+ tightened.
+
+ * "git diff --external-diff" incorrectly fed the submodule directory
+ in the working tree to the external diff driver when it knew it is
+ the same as one of the versions being compared.
+
+ * "git reset" needs to refresh the index when working in a working
+ tree (it can also be used to match the index to the HEAD in an
+ otherwise bare repository), but it failed to set up the working
+ tree properly, causing GIT_WORK_TREE to be ignored.
+
+ * "git check-attr" when working on a repository with a working tree
+ did not work well when the working tree was specified via the
+ --work-tree (and obviously with --git-dir) option.
+
+ * "merge-recursive" was broken in 1.7.7 era and stopped working in
+ an empty (temporary) working tree, when there are renames
+ involved. This has been corrected.
+
+ * "git rev-parse" was loose in rejecting command line arguments
+ that do not make sense, e.g. "--default" without the required
+ value for that option.
+
+ * include.path variable (or any variable that expects a path that
+ can use ~username expansion) in the configuration file is not a
+ boolean, but the code failed to check it.
+
+ * "git diff --quiet -- pathspec1 pathspec2" sometimes did not return
+ correct status value.
+
+ * Attempting to deepen a shallow repository by fetching over smart
+ HTTP transport failed in the protocol exchange, when no-done
+ extension was used. The fetching side waited for the list of
+ shallow boundary commits after the sending end stopped talking to
+ it.
+
+ * Allow "git cmd path/", when the 'path' is where a submodule is
+ bound to the top-level working tree, to match 'path', despite the
+ extra and unnecessary trailing slash (such a slash is often
+ given by command line completion).
diff --git a/Documentation/RelNotes/2.0.0.txt b/Documentation/RelNotes/2.0.0.txt
index acc7415505..98ec2103cd 100644
--- a/Documentation/RelNotes/2.0.0.txt
+++ b/Documentation/RelNotes/2.0.0.txt
@@ -39,14 +39,35 @@ The "-q" option to "git diff-files", which does *NOT* mean "quiet",
has been removed (it told Git to ignore deletion, which you can do
with "git diff-files --diff-filter=d").
+"git request-pull" lost a few "heuristics" that often led to mistakes.
+
Updates since v1.9 series
-------------------------
-Foreign interfaces, subsystems and ports.
+UI, Workflows & Features
+
+ * "git rebase" learned to interpret a lone "-" as "@{-1}", the
+ branch that we were previously on.
+ * "git commit --cleanup=<mode>" learned a new mode, scissors.
-UI, Workflows & Features
+ * "git tag --list" output can be sorted using "version sort" with
+ "--sort=version:refname".
+
+ * Discard the accumulated "heuristics" to guess from which branch the
+ result wants to be pulled from and make sure what the end user
+ specified is not second-guessed by "git request-pull", to avoid
+ mistakes. When you pushed out your 'master' branch to your public
+ repository as 'for-linus', use the new "master:for-linus" syntax to
+ denote the branch to be pulled.
+
+ * "git grep" learned to behave in a way similar to native grep when
+ "-h" (no header) and "-c" (count) options are given.
+
+ * transport-helper, fast-import and fast-export have been updated to
+ allow the ref mapping and ref deletion in a way similar to the
+ natively supported transports.
* The "simple" mode is the default for "git push".
@@ -63,7 +84,27 @@ UI, Workflows & Features
"quiet", has been removed (it told Git to ignore deletion, which
you can do with "git diff-files --diff-filter=d").
- * Many commands that creates commits, e.g. "pull", "rebase",
+ * Server operators can loosen the "tips of refs only" restriction for
+ the remote archive service with the uploadarchive.allowUnreachable
+ configuration option.
+
+ * The progress indicators from various time-consuming commands have
+ been marked for i18n/l10n.
+
+ * "git notes -C <blob>" diagnoses an attempt to use an object that
+ is not a blob as an error.
+
+ * "git config" learned to read from the standard input when "-" is
+ given as the value to its "--file" parameter (attempting an
+ operation to update the configuration in the standard input of
+ course is rejected).
+
+ * Trailing whitespaces in .gitignore files, unless they are quoted
+ for fnmatch(3), e.g. "path\ ", are warned and ignored. Strictly
+ speaking, this is a backward incompatible change, but very unlikely
+ to bite any sane user and adjusting should be obvious and easy.
+
+ * Many commands that create commits, e.g. "pull", "rebase",
learned to take the --gpg-sign option on the command line.
* "git commit" can be told to always GPG sign the resulting commit
@@ -85,6 +126,14 @@ UI, Workflows & Features
Performance, Internal Implementation, etc.
+ * We started using wildmatch() in place of fnmatch(3) a few releases
+ ago; complete the process and stop using fnmatch(3).
+
+ * Uses of curl's "multi" interface and "easy" interface do not mix
+ well when we attempt to reuse outgoing connections. Teach the RPC
+ over http code, used in the smart HTTP transport, not to use the
+ "easy" interface.
+
* The bitmap-index feature from JGit has been ported, which should
significantly improve performance when serving objects form a
repository that uses it.
@@ -97,7 +146,9 @@ Performance, Internal Implementation, etc.
suits your needs better when using the former.
-Also contains various documentation updates and code clean-ups.
+Also contains various documentation updates and code clean-ups. Many
+of them came from flurry of activities as GSoC candidate microproject
+exercises.
Fixes since v1.9 series
@@ -107,6 +158,107 @@ Unless otherwise noted, all the fixes since v1.9 in the maintenance
track are contained in this release (see the maintenance releases'
notes for details).
+ * "git repack" died when asked to (re)pack with the reachability
+ bitmap when a bitmap cannot be built; instead, just (re)pack
+ without producing a bitmap in such a case, with a warning.
+ (merge 373c67d jk/pack-bitmap later to maint).
+
+
+ * The progress output while repacking and transferring objects showed
+ an apparent large silence while writing the objects out of existing
+ packfiles, when the reachability bitmap was in use.
+ (merge 78d2214 jk/pack-bitmap-progress later to maint).
+
+
+ * A stray environment variable $prefix could have leaked into and
+ affected the behaviour of the "subtree" script (in contrib/).
+
+
+ * When it is not necessary to edit a commit log message (e.g. "git
+ commit -m" is given a message without specifying "-e"), we used to
+ disable the spawning of the editor by overriding GIT_EDITOR, but
+ this means all the uses of the editor, other than to edit the
+ commit log message, are also affected.
+ (merge b549be0 bp/commit-p-editor later to maint).
+
+
+ * "git mv" that moves a submodule forgot to adjust the array that
+ uses to keep track of which submodules were to be moved to update
+ its configuration.
+ (merge fb8a4e8 jk/mv-submodules-fix later to maint).
+
+ * Length limit for the pathname used when removing a path in a deep
+ subdirectory has been removed to avoid buffer overflows.
+ (merge 2f29e0c mh/remove-subtree-long-pathname-fix later to maint).
+
+ * The test helper lib-terminal always run an actual test_expect_*
+ when included, which screwed up with the use of skil-all that may
+ have to be done later.
+ (merge 7e27173 jk/lib-terminal-lazy later to maint).
+
+ * "git index-pack" used a wrong variable to name the keep-file in an
+ error message when the file cannot be written or closed.
+ (merge de983a0 nd/index-pack-error-message later to maint).
+
+ * "rebase -i" produced a broken insn sheet when the title of a commit
+ happened to contain '\n' (or ended with '\c') due to a careless use
+ of 'echo'.
+ (merge cb1aefd us/printf-not-echo later to maint).
+
+ * There were a few instances of 'git-foo' remaining in the
+ documentation that should have been spelled 'git foo'.
+ (merge 3c3e6f5 rr/doc-merge-strategies later to maint).
+
+ * Serving objects from a shallow repository needs to write a
+ new file to hold the temporary shallow boundaries but it was not
+ cleaned when we exit due to die() or a signal.
+ (merge 7839632 jk/shallow-update-fix later to maint).
+
+ * When "git stash pop" stops after failing to apply the stash
+ (e.g. due to conflicting changes), the stash is not dropped. State
+ that explicitly in the output to let the users know.
+ (merge 2d4c993 jc/stash-pop-not-popped later to maint).
+
+ * The labels in "git status" output that describe the nature of
+ conflicts (e.g. "both deleted") were limited to 20 bytes, which was
+ too short for some l10n (e.g. fr).
+ (merge c7cb333 jn/wt-status later to maint).
+
+ * "git clean -d pathspec" did not use the given pathspec correctly
+ and ended up cleaning too much.
+ (merge 1f2e108 jk/clean-d-pathspec later to maint).
+
+ * "git difftool" misbehaved when the repository is bound to the
+ working tree with the ".git file" mechanism, where a textual file
+ ".git" tells us where it is.
+ (merge fcfec8b da/difftool-git-files later to maint).
+
+ * "git push" did not pay attention to branch.*.pushremote if it is
+ defined earlier than remote.pushdefault; the order of these two
+ variables in the configuration file should not matter, but it did
+ by mistake.
+ (merge 98b406f jk/remote-pushremote-config-reading later to maint).
+
+ * Codepaths that parse timestamps in commit objects have been
+ tightened.
+ (merge 3f419d4 jk/commit-dates-parsing-fix later to maint).
+
+ * "git diff --external-diff" incorrectly fed the submodule directory
+ in the working tree to the external diff driver when it knew it is
+ the same as one of the versions being compared.
+ (merge aba4727 tr/diff-submodule-no-reuse-worktree later to maint).
+
+ * "git reset" needs to refresh the index when working in a working
+ tree (it can also be used to match the index to the HEAD in an
+ otherwise bare repository), but it failed to set up the working
+ tree properly, causing GIT_WORK_TREE to be ignored.
+ (merge b7756d4 nd/reset-setup-worktree later to maint).
+
+ * "git check-attr" when working on a repository with a working tree
+ did not work well when the working tree was specified via the
+ --work-tree (and obviously with --git-dir) option.
+ (merge cdbf623 jc/check-attr-honor-working-tree later to maint).
+
* "merge-recursive" was broken in 1.7.7 era and stopped working in
an empty (temporary) working tree, when there are renames
involved. This has been corrected.
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 73904bce55..c415aadbbc 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -131,8 +131,13 @@ Variables
Note that this list is non-comprehensive and not necessarily complete.
For command-specific variables, you will find a more detailed description
-in the appropriate manual page. You will find a description of non-core
-porcelain configuration variables in the respective porcelain documentation.
+in the appropriate manual page.
+
+Other git-related tools may and do use their own variables. When
+inventing new variables for use in your own tool, make sure their
+names do not conflict with those that are used by Git itself and
+other popular tools, and describe them in your documentation.
+
advice.*::
These variables control various optional help messages designed to
@@ -1607,6 +1612,10 @@ imap::
The configuration variables in the 'imap' section are described
in linkgit:git-imap-send[1].
+index.version::
+ Specify the version with which new index files should be
+ initialized. This does not affect existing repositories.
+
init.templatedir::
Specify the directory from which templates will be copied.
(See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].)
@@ -1639,7 +1648,7 @@ interactive.singlekey::
linkgit:git-add[1], linkgit:git-checkout[1], linkgit:git-commit[1],
linkgit:git-reset[1], and linkgit:git-stash[1]. Note that this
setting is silently ignored if portable keystroke input
- is not available.
+ is not available; requires the Perl module Term::ReadKey.
log.abbrevCommit::
If true, makes linkgit:git-log[1], linkgit:git-show[1], and
@@ -2152,6 +2161,13 @@ repack.usedeltabaseoffset::
"false" and repack. Access from old Git versions over the
native protocol are unaffected by this option.
+repack.packKeptObjects::
+ If set to true, makes `git repack` act as if
+ `--pack-kept-objects` was passed. See linkgit:git-repack[1] for
+ details. Defaults to `false` normally, but `true` if a bitmap
+ index is being written (either via `--write-bitmap-index` or
+ `pack.writeBitmaps`).
+
rerere.autoupdate::
When set to true, `git-rerere` updates the index with the
resulting contents after it cleanly resolves conflicts using
@@ -2332,6 +2348,13 @@ transfer.unpackLimit::
not set, the value of this variable is used instead.
The default value is 100.
+uploadarchive.allowUnreachable::
+ If true, allow clients to use `git archive --remote` to request
+ any tree, whether reachable from the ref tips or not. See the
+ discussion in the `SECURITY` section of
+ linkgit:git-upload-archive[1] for more details. Defaults to
+ `false`.
+
uploadpack.hiderefs::
String(s) `upload-pack` uses to decide which refs to omit
from its initial advertisement. Use more than one
diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 17924d0f3f..9adce372ec 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -14,7 +14,7 @@ SYNOPSIS
[--ignore-date] [--ignore-space-change | --ignore-whitespace]
[--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
[--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
- [--[no-]scissors] [-S[<keyid>]]
+ [--[no-]scissors] [-S[<keyid>]] [--patch-format=<format>]
[(<mbox> | <Maildir>)...]
'git am' (--continue | --skip | --abort)
@@ -97,6 +97,12 @@ default. You can use `--no-utf8` to override this.
program that applies
the patch.
+--patch-format::
+ By default the command will try to detect the patch format
+ automatically. This option allows the user to bypass the automatic
+ detection and specify the patch format that the patch(es) should be
+ interpreted as. Valid formats are mbox, stgit, stgit-series and hg.
+
-i::
--interactive::
Run interactively.
@@ -193,6 +199,11 @@ commits, like running 'git am' on the wrong branch or an error in the
commits that is more easily fixed by changing the mailbox (e.g.
errors in the "From:" lines).
+HOOKS
+-----
+This command can run `applypatch-msg`, `pre-applypatch`,
+and `post-applypatch` hooks. See linkgit:githooks[5] for more
+information.
SEE ALSO
--------
diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt
index b97aaab4ed..cfa1e4ebe4 100644
--- a/Documentation/git-archive.txt
+++ b/Documentation/git-archive.txt
@@ -65,7 +65,10 @@ OPTIONS
--remote=<repo>::
Instead of making a tar archive from the local repository,
- retrieve a tar archive from a remote repository.
+ retrieve a tar archive from a remote repository. Note that the
+ remote repository may place restrictions on which sha1
+ expressions may be allowed in `<tree-ish>`. See
+ linkgit:git-upload-archive[1] for details.
--exec=<git-upload-archive>::
Used with --remote to specify the path to the
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 7c42e9cabc..429267abf6 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -176,7 +176,7 @@ OPTIONS
--cleanup=<mode>::
This option determines how the supplied commit message should be
cleaned up before committing. The '<mode>' can be `strip`,
- `whitespace`, `verbatim`, or `default`.
+ `whitespace`, `verbatim`, `scissors` or `default`.
+
--
strip::
@@ -186,6 +186,12 @@ whitespace::
Same as `strip` except #commentary is not removed.
verbatim::
Do not change the message at all.
+scissors::
+ Same as `whitespace`, except that everything from (and
+ including) the line
+ "`# ------------------------ >8 ------------------------`"
+ is truncated if the message is to be edited. "`#`" can be
+ customized with core.commentChar.
default::
Same as `strip` if the message is to be edited.
Otherwise `whitespace`.
diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt
index 2df9953968..260f39fd40 100644
--- a/Documentation/git-cvsimport.txt
+++ b/Documentation/git-cvsimport.txt
@@ -21,8 +21,8 @@ DESCRIPTION
*WARNING:* `git cvsimport` uses cvsps version 2, which is considered
deprecated; it does not work with cvsps version 3 and later. If you are
performing a one-shot import of a CVS repository consider using
-link:http://cvs2svn.tigris.org/cvs2git.html[cvs2git] or
-link:https://github.com/BartMassey/parsecvs[parsecvs].
+http://cvs2svn.tigris.org/cvs2git.html[cvs2git] or
+https://github.com/BartMassey/parsecvs[parsecvs].
Imports a CVS repository into Git. It will either create a new
repository, or incrementally import into an existing one.
diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt
index 2eba627170..09535f2a08 100644
--- a/Documentation/git-filter-branch.txt
+++ b/Documentation/git-filter-branch.txt
@@ -436,7 +436,7 @@ git-filter-branch allows you to make complex shell-scripted rewrites
of your Git history, but you probably don't need this flexibility if
you're simply _removing unwanted data_ like large files or passwords.
For those operations you may want to consider
-link:http://rtyley.github.io/bfg-repo-cleaner/[The BFG Repo-Cleaner],
+http://rtyley.github.io/bfg-repo-cleaner/[The BFG Repo-Cleaner],
a JVM-based alternative to git-filter-branch, typically at least
10-50x faster for those use-cases, and with quite different
characteristics:
@@ -455,7 +455,7 @@ characteristics:
_is_ possible to write filters that include their own parallellism,
in the scripts executed against each commit.
-* The link:http://rtyley.github.io/bfg-repo-cleaner/#examples[command options]
+* The http://rtyley.github.io/bfg-repo-cleaner/#examples[command options]
are much more restrictive than git-filter branch, and dedicated just
to the tasks of removing unwanted data- e.g:
`--strip-blobs-bigger-than 1M`.
diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt
index cdab9ed503..d2d8f4792a 100644
--- a/Documentation/git-pack-objects.txt
+++ b/Documentation/git-pack-objects.txt
@@ -64,6 +64,8 @@ base-name::
the same way as 'git rev-list' with the `--objects` flag
uses its `commit` arguments to build the list of objects it
outputs. The objects on the resulting list are packed.
+ Besides revisions, `--not` or `--shallow <SHA-1>` lines are
+ also accepted.
--unpacked::
This implies `--revs`. When processing the list of
diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt
index 002cfd5eb9..4786a780b5 100644
--- a/Documentation/git-repack.txt
+++ b/Documentation/git-repack.txt
@@ -117,6 +117,14 @@ other objects in that pack they already have locally.
must be able to refer to all reachable objects. This option
overrides the setting of `pack.writebitmaps`.
+--pack-kept-objects::
+ Include objects in `.keep` files when repacking. Note that we
+ still do not delete `.keep` packs after `pack-objects` finishes.
+ This means that we may duplicate objects, but this makes the
+ option safe to use when there are concurrent pushes or fetches.
+ This option is generally only useful if you are writing bitmaps
+ with `-b` or `pack.writebitmaps`, as it ensures that the
+ bitmapped packfile has the necessary objects.
Configuration
-------------
diff --git a/Documentation/git-request-pull.txt b/Documentation/git-request-pull.txt
index b99681ce85..283577b0b6 100644
--- a/Documentation/git-request-pull.txt
+++ b/Documentation/git-request-pull.txt
@@ -13,22 +13,65 @@ SYNOPSIS
DESCRIPTION
-----------
-Summarizes the changes between two commits to the standard output, and includes
-the given URL in the generated summary.
+Generate a request asking your upstream project to pull changes into
+their tree. The request, printed to the standard output, summarizes
+the changes and indicates from where they can be pulled.
+
+The upstream project is expected to have the commit named by
+`<start>` and the output asks it to integrate the changes you made
+since that commit, up to the commit named by `<end>`, by visiting
+the repository named by `<url>`.
+
OPTIONS
-------
-p::
- Show patch text
+ Include patch text in the output.
<start>::
- Commit to start at.
+ Commit to start at. This names a commit that is already in
+ the upstream history.
<url>::
- URL to include in the summary.
+ The repository URL to be pulled from.
<end>::
- Commit to end at; defaults to HEAD.
+ Commit to end at (defaults to HEAD). This names the commit
+ at the tip of the history you are asking to be pulled.
++
+When the repository named by `<url>` has the commit at a tip of a
+ref that is different from the ref you have locally, you can use the
+`<local>:<remote>` syntax, to have its local name, a colon `:`, and
+its remote name.
+
+
+EXAMPLE
+-------
+
+Imagine that you built your work on your `master` branch on top of
+the `v1.0` release, and want it to be integrated to the project.
+First you push that change to your public repository for others to
+see:
+
+ git push https://git.ko.xz/project master
+
+Then, you run this command:
+
+ git request-pull v1.0 https://git.ko.xz/project master
+
+which will produce a request to the upstream, summarizing the
+changes between the `v1.0` release and your `master`, to pull it
+from your public repository.
+
+If you pushed your change to a branch whose name is different from
+the one you have locally, e.g.
+
+ git push https://git.ko.xz/project master:for-linus
+
+then you can ask that to be pulled with
+
+ git request-pull v1.0 https://git.ko.xz/project master:for-linus
+
GIT
---
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 0d2cdcde55..e05e6b3593 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -284,13 +284,13 @@ Input Format
'git rev-parse --parseopt' input format is fully text based. It has two parts,
separated by a line that contains only `--`. The lines before the separator
-(should be more than one) are used for the usage.
+(should be one or more) are used for the usage.
The lines after the separator describe the options.
Each line of options has this format:
------------
-<opt_spec><flags>* SP+ help LF
+<opt_spec><flags>*<arg_hint>? SP+ help LF
------------
`<opt_spec>`::
@@ -313,6 +313,12 @@ Each line of options has this format:
* Use `!` to not make the corresponding negated long option available.
+`<arg_hint>`::
+ `<arg_hint>`, if specified, is used as a name of the argument in the
+ help output, for options that take arguments. `<arg_hint>` is
+ terminated by the first whitespace. When you need to use space in the
+ argument hint use dash instead.
+
The remainder of the line, after stripping the spaces, is used
as the help associated to the option.
@@ -333,6 +339,8 @@ h,help show the help
foo some nifty option --foo
bar= some cool option --bar with an argument
+baz=arg another cool option --baz with a named argument
+qux?path qux may take a path argument but has meaning by itself
An option group Header
C? option C with an optional argument"
@@ -340,6 +348,28 @@ C? option C with an optional argument"
eval "$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)"
------------
+
+Usage text
+~~~~~~~~~~
+
+When `"$@"` is `-h` or `--help` in the above example, the following
+usage text would be shown:
+
+------------
+usage: some-command [options] <args>...
+
+ some-command does foo and bar!
+
+ -h, --help show the help
+ --foo some nifty option --foo
+ --bar ... some cool option --bar with an argument
+ --bar <arg> another cool option --baz with a named argument
+ --qux[=<path>] qux may take a path argument but has meaning by itself
+
+An option group Header
+ -C[...] option C with an optional argument
+------------
+
SQ-QUOTE
--------
diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index db7e803038..375213fe46 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -44,7 +44,7 @@ is also possible).
OPTIONS
-------
-save [-p|--patch] [--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]::
+save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]::
Save your local modifications to a new 'stash', and run `git reset
--hard` to revert them. The <message> part is optional and gives
diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt
index a4acaa038c..def635f578 100644
--- a/Documentation/git-status.txt
+++ b/Documentation/git-status.txt
@@ -97,7 +97,7 @@ configuration variable documented in linkgit:git-config[1].
OUTPUT
------
The output from this command is designed to be used as a commit
-template comment, and all the output lines are prefixed with '#'.
+template comment.
The default, long format, is designed to be human readable,
verbose and descriptive. Its contents and format are subject to change
at any time.
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 21cb59a6d6..77588b0dd8 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -15,7 +15,7 @@ SYNOPSIS
'git submodule' [--quiet] init [--] [<path>...]
'git submodule' [--quiet] deinit [-f|--force] [--] <path>...
'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch]
- [-f|--force] [--rebase|--merge|--checkout] [--reference <repository>]
+ [-f|--force] [--checkout|--rebase|--merge] [--reference <repository>]
[--depth <depth>] [--recursive] [--] [<path>...]
'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
[commit] [--] [<path>...]
@@ -162,7 +162,7 @@ update::
+
For updates that clone missing submodules, checkout-mode updates will
create submodules with detached HEADs; all other modes will create
-submodules with a local branch named after `submodule.<path>.branch`.
+submodules with a local branch named after `submodule.<name>.branch`.
+
For updates that do not clone missing submodules, the submodule's HEAD
is only touched when the remote reference does not match the
@@ -247,7 +247,7 @@ OPTIONS
-b::
--branch::
Branch of repository to add as submodule.
- The name of the branch is recorded as `submodule.<path>.branch` in
+ The name of the branch is recorded as `submodule.<name>.branch` in
`.gitmodules` for `update --remote`.
-f::
@@ -315,6 +315,15 @@ the submodule itself.
This option is only valid for the update command.
Don't fetch new objects from the remote site.
+--checkout::
+ This option is only valid for the update command.
+ Checkout the commit recorded in the superproject on a detached HEAD
+ in the submodule. This is the default behavior, the main use of
+ this option is to override `submodule.$name.update` when set to
+ `merge`, `rebase` or `none`.
+ If the key `submodule.$name.update` is either not explicitly set or
+ set to `checkout`, this option is implicit.
+
--merge::
This option is only valid for the update command.
Merge the commit recorded in the superproject into the current branch
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 404257df9f..b424a1bc48 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -95,6 +95,12 @@ OPTIONS
using fnmatch(3)). Multiple patterns may be given; if any of
them matches, the tag is shown.
+--sort=<type>::
+ Sort in a specific order. Supported type is "refname"
+ (lexicographic order), "version:refname" or "v:refname" (tag
+ names are treated as versions). Prepend "-" to reverse sort
+ order.
+
--column[=<options>]::
--no-column::
Display tag listing in columns. See configuration variable
diff --git a/Documentation/git-upload-archive.txt b/Documentation/git-upload-archive.txt
index d09bbb52b1..cbef61ba88 100644
--- a/Documentation/git-upload-archive.txt
+++ b/Documentation/git-upload-archive.txt
@@ -20,6 +20,38 @@ This command is usually not invoked directly by the end user. The UI
for the protocol is on the 'git archive' side, and the program pair
is meant to be used to get an archive from a remote repository.
+SECURITY
+--------
+
+In order to protect the privacy of objects that have been removed from
+history but may not yet have been pruned, `git-upload-archive` avoids
+serving archives for commits and trees that are not reachable from the
+repository's refs. However, because calculating object reachability is
+computationally expensive, `git-upload-archive` implements a stricter
+but easier-to-check set of rules:
+
+ 1. Clients may request a commit or tree that is pointed to directly by
+ a ref. E.g., `git archive --remote=origin v1.0`.
+
+ 2. Clients may request a sub-tree within a commit or tree using the
+ `ref:path` syntax. E.g., `git archive --remote=origin v1.0:Documentation`.
+
+ 3. Clients may _not_ use other sha1 expressions, even if the end
+ result is reachable. E.g., neither a relative commit like `master^`
+ nor a literal sha1 like `abcd1234` is allowed, even if the result
+ is reachable from the refs.
+
+Note that rule 3 disallows many cases that do not have any privacy
+implications. These rules are subject to change in future versions of
+git, and the server accessed by `git archive --remote` may or may not
+follow these exact rules.
+
+If the config option `uploadArchive.allowUnreachable` is true, these
+rules are ignored, and clients may use arbitrary sha1 expressions.
+This is useful if you do not care about the privacy of unreachable
+objects, or if your object database is already publicly available for
+access via non-smart-http.
+
OPTIONS
-------
<directory>::
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 02bbc084b8..e5f8ed0940 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -43,9 +43,10 @@ unreleased) version of Git, that is available from 'master'
branch of the `git.git` repository.
Documentation for older releases are available here:
-* link:v1.9.0/git.html[documentation for release 1.9.0]
+* link:v1.9.1/git.html[documentation for release 1.9.1]
* release notes for
+ link:RelNotes/1.9.1.txt[1.9.1],
link:RelNotes/1.9.0.txt[1.9.0].
* link:v1.8.5.5/git.html[documentation for release 1.8.5.5]
@@ -720,6 +721,11 @@ Git so take care if using Cogito etc.
index file. If not specified, the default of `$GIT_DIR/index`
is used.
+'GIT_INDEX_VERSION'::
+ This environment variable allows the specification of an index
+ version for new repositories. It won't affect existing index
+ files. By default index file version [23] is used.
+
'GIT_OBJECT_DIRECTORY'::
If the object storage directory is specified via this
environment variable then the sha1 directories are created
diff --git a/Documentation/gitcore-tutorial.txt b/Documentation/gitcore-tutorial.txt
index 058a352980..d2d7c213dd 100644
--- a/Documentation/gitcore-tutorial.txt
+++ b/Documentation/gitcore-tutorial.txt
@@ -1443,7 +1443,7 @@ Although Git is a truly distributed system, it is often
convenient to organize your project with an informal hierarchy
of developers. Linux kernel development is run this way. There
is a nice illustration (page 17, "Merges to Mainline") in
-link:http://www.xenotime.net/linux/mentor/linux-mentoring-2006.pdf[Randy Dunlap's presentation].
+http://www.xenotime.net/linux/mentor/linux-mentoring-2006.pdf[Randy Dunlap's presentation].
It should be stressed that this hierarchy is purely *informal*.
There is nothing fundamental in Git that enforces the "chain of
diff --git a/Documentation/gitcvs-migration.txt b/Documentation/gitcvs-migration.txt
index 5ea94cbceb..5f4e89005c 100644
--- a/Documentation/gitcvs-migration.txt
+++ b/Documentation/gitcvs-migration.txt
@@ -117,7 +117,7 @@ Importing a CVS archive
-----------------------
First, install version 2.1 or higher of cvsps from
-link:http://www.cobite.com/cvsps/[http://www.cobite.com/cvsps/] and make
+http://www.cobite.com/cvsps/[http://www.cobite.com/cvsps/] and make
sure it is in your path. Then cd to a checked out CVS working directory
of the project you are interested in and run linkgit:git-cvsimport[1]:
diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt
index b08d34d84e..8734c1566c 100644
--- a/Documentation/gitignore.txt
+++ b/Documentation/gitignore.txt
@@ -77,6 +77,9 @@ PATTERN FORMAT
Put a backslash ("`\`") in front of the first hash for patterns
that begin with a hash.
+ - Trailing spaces are ignored unless they are quoted with backlash
+ ("`\`").
+
- An optional prefix "`!`" which negates the pattern; any
matching file excluded by a previous pattern will become
included again. It is not possible to re-include a file if a parent
diff --git a/Documentation/gitk.txt b/Documentation/gitk.txt
index 1e9e38ae40..7e03fcc62d 100644
--- a/Documentation/gitk.txt
+++ b/Documentation/gitk.txt
@@ -166,8 +166,14 @@ gitk --max-count=100 --all \-- Makefile::
Files
-----
-Gitk creates the .gitk file in your $HOME directory to store preferences
-such as display options, font, and colors.
+User configuration and preferences are stored at:
+
+* '$XDG_CONFIG_HOME/git/gitk' if it exists, otherwise
+* '$HOME/.gitk' if it exists
+
+If neither of the above exist then '$XDG_CONFIG_HOME/git/gitk' is created and
+used by default. If '$XDG_CONFIG_HOME' is not set it defaults to
+'$HOME/.config' in all cases.
History
-------
diff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.txt
index c2908db763..64f7ad26b4 100644
--- a/Documentation/gitremote-helpers.txt
+++ b/Documentation/gitremote-helpers.txt
@@ -437,6 +437,10 @@ set by Git if the remote helper has the 'option' capability.
'option check-connectivity' \{'true'|'false'\}::
Request the helper to check connectivity of a clone.
+'option force' \{'true'|'false'\}::
+ Request the helper to perform a force update. Defaults to
+ 'false'.
+
'option cloning \{'true'|'false'\}::
Notify the helper this is a clone request (i.e. the current
repository is guaranteed empty).
diff --git a/Documentation/gitrepository-layout.txt b/Documentation/gitrepository-layout.txt
index aa03882ddb..17d2ea6c1e 100644
--- a/Documentation/gitrepository-layout.txt
+++ b/Documentation/gitrepository-layout.txt
@@ -176,6 +176,10 @@ info/grafts::
per line describes a commit and its fake parents by
listing their 40-byte hexadecimal object names separated
by a space and terminated by a newline.
++
+Note that the grafts mechanism is outdated and can lead to problems
+transferring objects between repositories; see linkgit:git-replace[1]
+for a more flexible and robust system to do the same thing.
info/exclude::
This file, by convention among Porcelains, stores the
diff --git a/Documentation/gitweb.txt b/Documentation/gitweb.txt
index cca14b8cc3..cd9c8951b2 100644
--- a/Documentation/gitweb.txt
+++ b/Documentation/gitweb.txt
@@ -84,7 +84,7 @@ separator (rules for Perl's "`split(" ", $line)`").
* Fields use modified URI encoding, defined in RFC 3986, section 2.1
(Percent-Encoding), or rather "Query string encoding" (see
-link:http://en.wikipedia.org/wiki/Query_string#URL_encoding[]), the difference
+http://en.wikipedia.org/wiki/Query_string#URL_encoding[]), the difference
being that SP (" ") can be encoded as "{plus}" (and therefore "{plus}" has to be
also percent-encoded).
+
diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt
index 378306f581..be0858c188 100644
--- a/Documentation/glossary-content.txt
+++ b/Documentation/glossary-content.txt
@@ -176,6 +176,10 @@ current branch integrates with) obviously do not work, as there is no
you can make Git pretend the set of <<def_parent,parents>> a <<def_commit,commit>> has
is different from what was recorded when the commit was
created. Configured via the `.git/info/grafts` file.
++
+Note that the grafts mechanism is outdated and can lead to problems
+transferring objects between repositories; see linkgit:git-replace[1]
+for a more flexible and robust system to do the same thing.
[[def_hash]]hash::
In Git's context, synonym for <<def_object_name,object name>>.
diff --git a/Documentation/merge-strategies.txt b/Documentation/merge-strategies.txt
index 350949810e..7bbd19b300 100644
--- a/Documentation/merge-strategies.txt
+++ b/Documentation/merge-strategies.txt
@@ -1,10 +1,10 @@
MERGE STRATEGIES
----------------
-The merge mechanism ('git-merge' and 'git-pull' commands) allows the
+The merge mechanism (`git merge` and `git pull` commands) allows the
backend 'merge strategies' to be chosen with `-s` option. Some strategies
can also take their own options, which can be passed by giving `-X<option>`
-arguments to 'git-merge' and/or 'git-pull'.
+arguments to `git merge` and/or `git pull`.
resolve::
This can only resolve two heads (i.e. the current branch
diff --git a/Documentation/technical/http-protocol.txt b/Documentation/technical/http-protocol.txt
index 544373b16f..20525d98bb 100644
--- a/Documentation/technical/http-protocol.txt
+++ b/Documentation/technical/http-protocol.txt
@@ -500,7 +500,7 @@ TODO: Document this further.
References
----------
-link:http://www.ietf.org/rfc/rfc1738.txt[RFC 1738: Uniform Resource Locators (URL)]
-link:http://www.ietf.org/rfc/rfc2616.txt[RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1]
+http://www.ietf.org/rfc/rfc1738.txt[RFC 1738: Uniform Resource Locators (URL)]
+http://www.ietf.org/rfc/rfc2616.txt[RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1]
link:technical/pack-protocol.html
link:technical/protocol-capabilities.html
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 2b97352dd3..a651d68656 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v1.9.0
+DEF_VER=v1.9.0.GIT
LF='
'
diff --git a/Makefile b/Makefile
index d4ce53a71b..c5316a34ac 100644
--- a/Makefile
+++ b/Makefile
@@ -59,9 +59,9 @@ all::
# FreeBSD can use either, but MinGW and some others need to use
# libcharset.h's locale_charset() instead.
#
-# Define CHARSET_LIB to you need to link with library other than -liconv to
+# Define CHARSET_LIB to the library you need to link with in order to
# use locale_charset() function. On some platforms this needs to set to
-# -lcharset
+# -lcharset, on others to -liconv .
#
# Define LIBC_CONTAINS_LIBINTL if your gettext implementation doesn't
# need -lintl when linking.
@@ -101,14 +101,6 @@ all::
#
# Define NO_MKSTEMPS if you don't have mkstemps in the C library.
#
-# Define NO_FNMATCH if you don't have fnmatch in the C library.
-#
-# Define NO_FNMATCH_CASEFOLD if your fnmatch function doesn't have the
-# FNM_CASEFOLD GNU extension.
-#
-# Define NO_WILDMATCH if you do not want to use Git's wildmatch
-# implementation as fnmatch
-#
# Define NO_GECOS_IN_PWENT if you don't have pw_gecos in struct passwd
# in the C library.
#
@@ -342,6 +334,10 @@ all::
# Define DEFAULT_HELP_FORMAT to "man", "info" or "html"
# (defaults to "man") if you want to have a different default when
# "git help" is called without a parameter specifying the format.
+#
+# Define TEST_GIT_INDEX_VERSION to 2, 3 or 4 to run the test suite
+# with a different indexfile format version. If it isn't set the index
+# file format used is index-v[23].
GIT-VERSION-FILE: FORCE
@$(SHELL_PATH) ./GIT-VERSION-GEN
@@ -896,6 +892,7 @@ LIB_OBJS += userdiff.o
LIB_OBJS += utf8.o
LIB_OBJS += varint.o
LIB_OBJS += version.o
+LIB_OBJS += versioncmp.o
LIB_OBJS += walker.o
LIB_OBJS += wildmatch.o
LIB_OBJS += wrapper.o
@@ -1283,20 +1280,6 @@ endif
ifdef NO_STRTOULL
COMPAT_CFLAGS += -DNO_STRTOULL
endif
-ifdef NO_FNMATCH
- COMPAT_CFLAGS += -Icompat/fnmatch
- COMPAT_CFLAGS += -DNO_FNMATCH
- COMPAT_OBJS += compat/fnmatch/fnmatch.o
-else
-ifdef NO_FNMATCH_CASEFOLD
- COMPAT_CFLAGS += -Icompat/fnmatch
- COMPAT_CFLAGS += -DNO_FNMATCH_CASEFOLD
- COMPAT_OBJS += compat/fnmatch/fnmatch.o
-endif
-endif
-ifndef NO_WILDMATCH
- COMPAT_CFLAGS += -DUSE_WILDMATCH
-endif
ifdef NO_SETENV
COMPAT_CFLAGS += -DNO_SETENV
COMPAT_OBJS += compat/setenv.o
@@ -2234,6 +2217,9 @@ endif
ifdef GIT_PERF_MAKE_OPTS
@echo GIT_PERF_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_PERF_MAKE_OPTS)))'\' >>$@
endif
+ifdef TEST_GIT_INDEX_VERSION
+ @echo TEST_GIT_INDEX_VERSION=\''$(subst ','\'',$(subst ','\'',$(TEST_GIT_INDEX_VERSION)))'\' >>$@
+endif
### Detect Python interpreter path changes
ifndef NO_PYTHON
diff --git a/archive.c b/archive.c
index 346f3b2f1a..3fc0fb2928 100644
--- a/archive.c
+++ b/archive.c
@@ -17,6 +17,7 @@ static char const * const archive_usage[] = {
static const struct archiver **archivers;
static int nr_archivers;
static int alloc_archivers;
+static int remote_allow_unreachable;
void register_archiver(struct archiver *ar)
{
@@ -257,10 +258,10 @@ static void parse_treeish_arg(const char **argv,
unsigned char sha1[20];
/* Remotes are only allowed to fetch actual refs */
- if (remote) {
+ if (remote && !remote_allow_unreachable) {
char *ref = NULL;
- const char *colon = strchr(name, ':');
- int refnamelen = colon ? colon - name : strlen(name);
+ const char *colon = strchrnul(name, ':');
+ int refnamelen = colon - name;
if (!dwim_ref(name, refnamelen, sha1, &ref))
die("no such ref: %.*s", refnamelen, name);
@@ -401,6 +402,14 @@ static int parse_archive_args(int argc, const char **argv,
return argc;
}
+static int git_default_archive_config(const char *var, const char *value,
+ void *cb)
+{
+ if (!strcmp(var, "uploadarchive.allowunreachable"))
+ remote_allow_unreachable = git_config_bool(var, value);
+ return git_default_config(var, value, cb);
+}
+
int write_archive(int argc, const char **argv, const char *prefix,
int setup_prefix, const char *name_hint, int remote)
{
@@ -411,7 +420,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
if (setup_prefix && prefix == NULL)
prefix = setup_git_directory_gently(&nongit);
- git_config(git_default_config, NULL);
+ git_config(git_default_archive_config, NULL);
init_tar_archiver();
init_zip_archiver();
diff --git a/attr.c b/attr.c
index 8d13d70e80..734222dc45 100644
--- a/attr.c
+++ b/attr.c
@@ -338,12 +338,7 @@ static void handle_attr_line(struct attr_stack *res,
a = parse_attr_line(line, src, lineno, macro_ok);
if (!a)
return;
- if (res->alloc <= res->num_matches) {
- res->alloc = alloc_nr(res->num_matches);
- res->attrs = xrealloc(res->attrs,
- sizeof(struct match_attr *) *
- res->alloc);
- }
+ ALLOC_GROW(res->attrs, res->num_matches + 1, res->alloc);
res->attrs[res->num_matches++] = a;
}
diff --git a/branch.c b/branch.c
index b2d59f137b..660097bc29 100644
--- a/branch.c
+++ b/branch.c
@@ -1,3 +1,4 @@
+#include "git-compat-util.h"
#include "cache.h"
#include "branch.h"
#include "refs.h"
@@ -49,12 +50,11 @@ static int should_setup_rebase(const char *origin)
void install_branch_config(int flag, const char *local, const char *origin, const char *remote)
{
- const char *shortname = remote + 11;
- int remote_is_branch = starts_with(remote, "refs/heads/");
+ const char *shortname = skip_prefix(remote, "refs/heads/");
struct strbuf key = STRBUF_INIT;
int rebasing = should_setup_rebase(origin);
- if (remote_is_branch
+ if (shortname
&& !strcmp(local, shortname)
&& !origin) {
warning(_("Not setting branch %s as its own upstream."),
@@ -77,7 +77,7 @@ void install_branch_config(int flag, const char *local, const char *origin, cons
strbuf_release(&key);
if (flag & BRANCH_CONFIG_VERBOSE) {
- if (remote_is_branch) {
+ if (shortname) {
if (origin)
printf_ln(rebasing ?
_("Branch %s set up to track remote branch %s from %s by rebasing.") :
@@ -114,10 +114,6 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,
struct tracking tracking;
int config_flags = quiet ? 0 : BRANCH_CONFIG_VERBOSE;
- if (strlen(new_ref) > 1024 - 7 - 7 - 1)
- return error(_("Tracking not set up: name too long: %s"),
- new_ref);
-
memset(&tracking, 0, sizeof(tracking));
tracking.spec.dst = (char *)orig_ref;
if (for_each_remote(find_tracked_branch, &tracking))
diff --git a/builtin/add.c b/builtin/add.c
index 4b045bace1..459208a326 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -15,6 +15,7 @@
#include "diffcore.h"
#include "revision.h"
#include "bulk-checkin.h"
+#include "argv-array.h"
static const char * const builtin_add_usage[] = {
N_("git add [options] [--] <pathspec>..."),
@@ -141,23 +142,21 @@ static void refresh(int verbose, const struct pathspec *pathspec)
int run_add_interactive(const char *revision, const char *patch_mode,
const struct pathspec *pathspec)
{
- int status, ac, i;
- const char **args;
+ int status, i;
+ struct argv_array argv = ARGV_ARRAY_INIT;
- args = xcalloc(sizeof(const char *), (pathspec->nr + 6));
- ac = 0;
- args[ac++] = "add--interactive";
+ argv_array_push(&argv, "add--interactive");
if (patch_mode)
- args[ac++] = patch_mode;
+ argv_array_push(&argv, patch_mode);
if (revision)
- args[ac++] = revision;
- args[ac++] = "--";
+ argv_array_push(&argv, revision);
+ argv_array_push(&argv, "--");
for (i = 0; i < pathspec->nr; i++)
/* pass original pathspec, to be re-parsed */
- args[ac++] = pathspec->items[i].original;
+ argv_array_push(&argv, pathspec->items[i].original);
- status = run_command_v_opt(args, RUN_GIT_CMD);
- free(args);
+ status = run_command_v_opt(argv.argv, RUN_GIT_CMD);
+ argv_array_clear(&argv);
return status;
}
diff --git a/builtin/apply.c b/builtin/apply.c
index a7e72d57ab..0189523798 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -4152,7 +4152,7 @@ static int use_patch(struct patch *p)
/* See if it matches any of exclude/include rule */
for (i = 0; i < limit_by_name.nr; i++) {
struct string_list_item *it = &limit_by_name.items[i];
- if (!fnmatch(it->string, pathname, 0))
+ if (!wildmatch(it->string, pathname, 0, NULL))
return (it->util != NULL);
}
diff --git a/builtin/branch.c b/builtin/branch.c
index b4d771673e..652b1d2d14 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -315,7 +315,7 @@ static int match_patterns(const char **pattern, const char *refname)
if (!*pattern)
return 1; /* no pattern always matches */
while (*pattern) {
- if (!fnmatch(*pattern, refname, 0))
+ if (!wildmatch(*pattern, refname, 0, NULL))
return 1;
pattern++;
}
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index d5a93e0e91..707330499f 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -269,6 +269,8 @@ static int batch_objects(struct batch_options *opt)
{
struct strbuf buf = STRBUF_INIT;
struct expand_data data;
+ int save_warning;
+ int retval = 0;
if (!opt->format)
opt->format = "%(objectname) %(objecttype) %(objectsize)";
@@ -297,11 +299,10 @@ static int batch_objects(struct batch_options *opt)
* warn) ends up dwarfing the actual cost of the object lookups
* themselves. We can work around it by just turning off the warning.
*/
+ save_warning = warn_on_object_refname_ambiguity;
warn_on_object_refname_ambiguity = 0;
while (strbuf_getline(&buf, stdin, '\n') != EOF) {
- int error;
-
if (data.split_on_whitespace) {
/*
* Split at first whitespace, tying off the beginning
@@ -316,12 +317,14 @@ static int batch_objects(struct batch_options *opt)
data.rest = p;
}
- error = batch_one_object(buf.buf, opt, &data);
- if (error)
- return error;
+ retval = batch_one_object(buf.buf, opt, &data);
+ if (retval)
+ break;
}
- return 0;
+ strbuf_release(&buf);
+ warn_on_object_refname_ambiguity = save_warning;
+ return retval;
}
static const char * const cat_file_usage[] = {
diff --git a/builtin/check-attr.c b/builtin/check-attr.c
index e9af7b2bfb..5600ec3f61 100644
--- a/builtin/check-attr.c
+++ b/builtin/check-attr.c
@@ -102,6 +102,9 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
struct git_attr_check *check;
int cnt, i, doubledash, filei;
+ if (!is_bare_repository())
+ setup_work_tree();
+
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, prefix, check_attr_options,
diff --git a/builtin/checkout.c b/builtin/checkout.c
index ada51fa70f..1b86d9c868 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -53,10 +53,10 @@ struct checkout_opts {
static int post_checkout_hook(struct commit *old, struct commit *new,
int changed)
{
- return run_hook(NULL, "post-checkout",
- sha1_to_hex(old ? old->object.sha1 : null_sha1),
- sha1_to_hex(new ? new->object.sha1 : null_sha1),
- changed ? "1" : "0", NULL);
+ return run_hook_le(NULL, "post-checkout",
+ sha1_to_hex(old ? old->object.sha1 : null_sha1),
+ sha1_to_hex(new ? new->object.sha1 : null_sha1),
+ changed ? "1" : "0", NULL);
/* "new" can be NULL when checking out from the index before
a commit exists. */
diff --git a/builtin/clean.c b/builtin/clean.c
index 114d7bf879..cf76b1f412 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -947,17 +947,15 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
if (pathspec.nr)
matches = dir_path_match(ent, &pathspec, 0, NULL);
- if (S_ISDIR(st.st_mode)) {
- if (remove_directories || (matches == MATCHED_EXACTLY)) {
- rel = relative_path(ent->name, prefix, &buf);
- string_list_append(&del_list, rel);
- }
- } else {
- if (pathspec.nr && !matches)
- continue;
- rel = relative_path(ent->name, prefix, &buf);
- string_list_append(&del_list, rel);
- }
+ if (pathspec.nr && !matches)
+ continue;
+
+ if (S_ISDIR(st.st_mode) && !remove_directories &&
+ matches != MATCHED_EXACTLY)
+ continue;
+
+ rel = relative_path(ent->name, prefix, &buf);
+ string_list_append(&del_list, rel);
}
if (interactive && del_list.nr > 0)
diff --git a/builtin/clone.c b/builtin/clone.c
index 43e772ccdb..9b3c04d914 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -660,8 +660,8 @@ static int checkout(void)
commit_locked_index(lock_file))
die(_("unable to write new index file"));
- err |= run_hook(NULL, "post-checkout", sha1_to_hex(null_sha1),
- sha1_to_hex(sha1), "1", NULL);
+ err |= run_hook_le(NULL, "post-checkout", sha1_to_hex(null_sha1),
+ sha1_to_hex(sha1), "1", NULL);
if (!err && option_recursive)
err = run_command_v_opt(argv_submodule, RUN_GIT_CMD);
diff --git a/builtin/commit.c b/builtin/commit.c
index 3783bcadcd..d9550c54d0 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -113,6 +113,7 @@ static char *sign_commit;
static enum {
CLEANUP_SPACE,
CLEANUP_NONE,
+ CLEANUP_SCISSORS,
CLEANUP_ALL
} cleanup_mode;
static const char *cleanup_arg;
@@ -610,7 +611,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
/* This checks and barfs if author is badly specified */
determine_author_info(author_ident);
- if (!no_verify && run_hook(index_file, "pre-commit", NULL))
+ if (!no_verify && run_commit_hook(use_editor, index_file, "pre-commit", NULL))
return 0;
if (squash_message) {
@@ -755,7 +756,9 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
int ident_shown = 0;
int saved_color_setting;
char *ai_tmp, *ci_tmp;
- if (whence != FROM_COMMIT)
+ if (whence != FROM_COMMIT) {
+ if (cleanup_mode == CLEANUP_SCISSORS)
+ wt_status_add_cut_line(s->fp);
status_printf_ln(s, GIT_COLOR_NORMAL,
whence == FROM_MERGE
? _("\n"
@@ -771,6 +774,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
git_path(whence == FROM_MERGE
? "MERGE_HEAD"
: "CHERRY_PICK_HEAD"));
+ }
fprintf(s->fp, "\n");
if (cleanup_mode == CLEANUP_ALL)
@@ -778,6 +782,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
_("Please enter the commit message for your changes."
" Lines starting\nwith '%c' will be ignored, and an empty"
" message aborts the commit.\n"), comment_line_char);
+ else if (cleanup_mode == CLEANUP_SCISSORS && whence == FROM_COMMIT)
+ wt_status_add_cut_line(s->fp);
else /* CLEANUP_SPACE, that is. */
status_printf(s, GIT_COLOR_NORMAL,
_("Please enter the commit message for your changes."
@@ -867,8 +873,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
return 0;
}
- if (run_hook(index_file, "prepare-commit-msg",
- git_path(commit_editmsg), hook_arg1, hook_arg2, NULL))
+ if (run_commit_hook(use_editor, index_file, "prepare-commit-msg",
+ git_path(commit_editmsg), hook_arg1, hook_arg2, NULL))
return 0;
if (use_editor) {
@@ -884,7 +890,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
}
if (!no_verify &&
- run_hook(index_file, "commit-msg", git_path(commit_editmsg), NULL)) {
+ run_commit_hook(use_editor, index_file, "commit-msg", git_path(commit_editmsg), NULL)) {
return 0;
}
@@ -1068,8 +1074,6 @@ static int parse_and_validate_options(int argc, const char *argv[],
use_editor = 0;
if (0 <= edit_flag)
use_editor = edit_flag;
- if (!use_editor)
- setenv("GIT_EDITOR", ":", 1);
/* Sanity check options */
if (amend && !current_head)
@@ -1133,6 +1137,8 @@ static int parse_and_validate_options(int argc, const char *argv[],
cleanup_mode = CLEANUP_SPACE;
else if (!strcmp(cleanup_arg, "strip"))
cleanup_mode = CLEANUP_ALL;
+ else if (!strcmp(cleanup_arg, "scissors"))
+ cleanup_mode = use_editor ? CLEANUP_SCISSORS : CLEANUP_SPACE;
else
die(_("Invalid cleanup mode %s"), cleanup_arg);
@@ -1450,6 +1456,29 @@ static int run_rewrite_hook(const unsigned char *oldsha1,
return finish_command(&proc);
}
+int run_commit_hook(int editor_is_used, const char *index_file, const char *name, ...)
+{
+ const char *hook_env[3] = { NULL };
+ char index[PATH_MAX];
+ va_list args;
+ int ret;
+
+ snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
+ hook_env[0] = index;
+
+ /*
+ * Let the hook know that no editor will be launched.
+ */
+ if (!editor_is_used)
+ hook_env[1] = "GIT_EDITOR=:";
+
+ va_start(args, name);
+ ret = run_hook_ve(hook_env, name, args);
+ va_end(args);
+
+ return ret;
+}
+
int cmd_commit(int argc, const char **argv, const char *prefix)
{
static struct wt_status s;
@@ -1605,8 +1634,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
die(_("could not read commit message: %s"), strerror(saved_errno));
}
- /* Truncate the message just before the diff, if any. */
- if (verbose)
+ if (verbose || /* Truncate the message just before the diff, if any. */
+ cleanup_mode == CLEANUP_SCISSORS)
wt_status_truncate_message_at_cut_line(&sb);
if (cleanup_mode != CLEANUP_NONE)
@@ -1674,7 +1703,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
"not exceeded, and then \"git reset HEAD\" to recover."));
rerere(0);
- run_hook(get_index_file(), "post-commit", NULL);
+ run_commit_hook(use_editor, get_index_file(), "post-commit", NULL);
if (amend && !no_post_rewrite) {
struct notes_rewrite_cfg *cfg;
cfg = init_copy_notes_for_rewrite("amend");
diff --git a/builtin/config.c b/builtin/config.c
index 92ebf23f0a..5677c942b6 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -21,8 +21,7 @@ static char key_delim = ' ';
static char term = '\n';
static int use_global_config, use_system_config, use_local_config;
-static const char *given_config_file;
-static const char *given_config_blob;
+static struct git_config_source given_config_source;
static int actions, types;
static const char *get_color_slot, *get_colorbool_slot;
static int end_null;
@@ -55,8 +54,8 @@ static struct option builtin_config_options[] = {
OPT_BOOL(0, "global", &use_global_config, N_("use global config file")),
OPT_BOOL(0, "system", &use_system_config, N_("use system config file")),
OPT_BOOL(0, "local", &use_local_config, N_("use repository config file")),
- OPT_STRING('f', "file", &given_config_file, N_("file"), N_("use given config file")),
- OPT_STRING(0, "blob", &given_config_blob, N_("blob-id"), N_("read config from given blob object")),
+ OPT_STRING('f', "file", &given_config_source.file, N_("file"), N_("use given config file")),
+ OPT_STRING(0, "blob", &given_config_source.blob, N_("blob-id"), N_("read config from given blob object")),
OPT_GROUP(N_("Action")),
OPT_BIT(0, "get", &actions, N_("get value: name [value-regex]"), ACTION_GET),
OPT_BIT(0, "get-all", &actions, N_("get all values: key [value-regex]"), ACTION_GET_ALL),
@@ -224,8 +223,7 @@ static int get_value(const char *key_, const char *regex_)
}
git_config_with_options(collect_config, &values,
- given_config_file, given_config_blob,
- respect_includes);
+ &given_config_source, respect_includes);
ret = !values.nr;
@@ -309,8 +307,7 @@ static void get_color(const char *def_color)
get_color_found = 0;
parsed_color[0] = '\0';
git_config_with_options(git_get_color_config, NULL,
- given_config_file, given_config_blob,
- respect_includes);
+ &given_config_source, respect_includes);
if (!get_color_found && def_color)
color_parse(def_color, "command line", parsed_color);
@@ -339,8 +336,7 @@ static int get_colorbool(int print)
get_diff_color_found = -1;
get_color_ui_found = -1;
git_config_with_options(git_get_colorbool_config, NULL,
- given_config_file, given_config_blob,
- respect_includes);
+ &given_config_source, respect_includes);
if (get_colorbool_found < 0) {
if (!strcmp(get_colorbool_slot, "color.diff"))
@@ -362,9 +358,12 @@ static int get_colorbool(int print)
return get_colorbool_found ? 0 : 1;
}
-static void check_blob_write(void)
+static void check_write(void)
{
- if (given_config_blob)
+ if (given_config_source.use_stdin)
+ die("writing to stdin is not supported");
+
+ if (given_config_source.blob)
die("writing config blobs is not supported");
}
@@ -435,7 +434,7 @@ static int get_urlmatch(const char *var, const char *url)
}
git_config_with_options(urlmatch_config_entry, &config,
- given_config_file, NULL, respect_includes);
+ &given_config_source, respect_includes);
for_each_string_list_item(item, &values) {
struct urlmatch_current_candidate_value *matched = item->util;
@@ -464,18 +463,24 @@ int cmd_config(int argc, const char **argv, const char *prefix)
int nongit = !startup_info->have_repository;
char *value;
- given_config_file = getenv(CONFIG_ENVIRONMENT);
+ given_config_source.file = getenv(CONFIG_ENVIRONMENT);
argc = parse_options(argc, argv, prefix, builtin_config_options,
builtin_config_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
if (use_global_config + use_system_config + use_local_config +
- !!given_config_file + !!given_config_blob > 1) {
+ !!given_config_source.file + !!given_config_source.blob > 1) {
error("only one config file at a time.");
usage_with_options(builtin_config_usage, builtin_config_options);
}
+ if (given_config_source.file &&
+ !strcmp(given_config_source.file, "-")) {
+ given_config_source.file = NULL;
+ given_config_source.use_stdin = 1;
+ }
+
if (use_global_config) {
char *user_config = NULL;
char *xdg_config = NULL;
@@ -493,24 +498,24 @@ int cmd_config(int argc, const char **argv, const char *prefix)
if (access_or_warn(user_config, R_OK, 0) &&
xdg_config && !access_or_warn(xdg_config, R_OK, 0))
- given_config_file = xdg_config;
+ given_config_source.file = xdg_config;
else
- given_config_file = user_config;
+ given_config_source.file = user_config;
}
else if (use_system_config)
- given_config_file = git_etc_gitconfig();
+ given_config_source.file = git_etc_gitconfig();
else if (use_local_config)
- given_config_file = git_pathdup("config");
- else if (given_config_file) {
- if (!is_absolute_path(given_config_file) && prefix)
- given_config_file =
+ given_config_source.file = git_pathdup("config");
+ else if (given_config_source.file) {
+ if (!is_absolute_path(given_config_source.file) && prefix)
+ given_config_source.file =
xstrdup(prefix_filename(prefix,
strlen(prefix),
- given_config_file));
+ given_config_source.file));
}
if (respect_includes == -1)
- respect_includes = !given_config_file;
+ respect_includes = !given_config_source.file;
if (end_null) {
term = '\0';
@@ -549,57 +554,58 @@ int cmd_config(int argc, const char **argv, const char *prefix)
if (actions == ACTION_LIST) {
check_argc(argc, 0, 0);
if (git_config_with_options(show_all_config, NULL,
- given_config_file,
- given_config_blob,
+ &given_config_source,
respect_includes) < 0) {
- if (given_config_file)
+ if (given_config_source.file)
die_errno("unable to read config file '%s'",
- given_config_file);
+ given_config_source.file);
else
die("error processing config file(s)");
}
}
else if (actions == ACTION_EDIT) {
check_argc(argc, 0, 0);
- if (!given_config_file && nongit)
+ if (!given_config_source.file && nongit)
die("not in a git directory");
- if (given_config_blob)
+ if (given_config_source.use_stdin)
+ die("editing stdin is not supported");
+ if (given_config_source.blob)
die("editing blobs is not supported");
git_config(git_default_config, NULL);
- launch_editor(given_config_file ?
- given_config_file : git_path("config"),
+ launch_editor(given_config_source.file ?
+ given_config_source.file : git_path("config"),
NULL, NULL);
}
else if (actions == ACTION_SET) {
int ret;
- check_blob_write();
+ check_write();
check_argc(argc, 2, 2);
value = normalize_value(argv[0], argv[1]);
- ret = git_config_set_in_file(given_config_file, argv[0], value);
+ ret = git_config_set_in_file(given_config_source.file, argv[0], value);
if (ret == CONFIG_NOTHING_SET)
error("cannot overwrite multiple values with a single value\n"
" Use a regexp, --add or --replace-all to change %s.", argv[0]);
return ret;
}
else if (actions == ACTION_SET_ALL) {
- check_blob_write();
+ check_write();
check_argc(argc, 2, 3);
value = normalize_value(argv[0], argv[1]);
- return git_config_set_multivar_in_file(given_config_file,
+ return git_config_set_multivar_in_file(given_config_source.file,
argv[0], value, argv[2], 0);
}
else if (actions == ACTION_ADD) {
- check_blob_write();
+ check_write();
check_argc(argc, 2, 2);
value = normalize_value(argv[0], argv[1]);
- return git_config_set_multivar_in_file(given_config_file,
+ return git_config_set_multivar_in_file(given_config_source.file,
argv[0], value, "^$", 0);
}
else if (actions == ACTION_REPLACE_ALL) {
- check_blob_write();
+ check_write();
check_argc(argc, 2, 3);
value = normalize_value(argv[0], argv[1]);
- return git_config_set_multivar_in_file(given_config_file,
+ return git_config_set_multivar_in_file(given_config_source.file,
argv[0], value, argv[2], 1);
}
else if (actions == ACTION_GET) {
@@ -623,26 +629,26 @@ int cmd_config(int argc, const char **argv, const char *prefix)
return get_urlmatch(argv[0], argv[1]);
}
else if (actions == ACTION_UNSET) {
- check_blob_write();
+ check_write();
check_argc(argc, 1, 2);
if (argc == 2)
- return git_config_set_multivar_in_file(given_config_file,
+ return git_config_set_multivar_in_file(given_config_source.file,
argv[0], NULL, argv[1], 0);
else
- return git_config_set_in_file(given_config_file,
+ return git_config_set_in_file(given_config_source.file,
argv[0], NULL);
}
else if (actions == ACTION_UNSET_ALL) {
- check_blob_write();
+ check_write();
check_argc(argc, 1, 2);
- return git_config_set_multivar_in_file(given_config_file,
+ return git_config_set_multivar_in_file(given_config_source.file,
argv[0], NULL, argv[1], 1);
}
else if (actions == ACTION_RENAME_SECTION) {
int ret;
- check_blob_write();
+ check_write();
check_argc(argc, 2, 2);
- ret = git_config_rename_section_in_file(given_config_file,
+ ret = git_config_rename_section_in_file(given_config_source.file,
argv[0], argv[1]);
if (ret < 0)
return ret;
@@ -651,9 +657,9 @@ int cmd_config(int argc, const char **argv, const char *prefix)
}
else if (actions == ACTION_REMOVE_SECTION) {
int ret;
- check_blob_write();
+ check_write();
check_argc(argc, 1, 1);
- ret = git_config_rename_section_in_file(given_config_file,
+ ret = git_config_rename_section_in_file(given_config_source.file,
argv[0], NULL);
if (ret < 0)
return ret;
diff --git a/builtin/describe.c b/builtin/describe.c
index dadd999c41..24d740c8b1 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -138,7 +138,7 @@ static int get_name(const char *path, const unsigned char *sha1, int flag, void
return 0;
/* Accept only tags that match the pattern, if given */
- if (pattern && (!is_tag || fnmatch(pattern, path + 10, 0)))
+ if (pattern && (!is_tag || wildmatch(pattern, path + 10, 0, NULL)))
return 0;
/* Is it annotated? */
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 51798b48b5..3e1d5c3334 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -864,7 +864,7 @@ static int grab_single_ref(const char *refname, const unsigned char *sha1, int f
refname[plen] == '/' ||
p[plen-1] == '/'))
break;
- if (!fnmatch(p, refname, FNM_PATHNAME))
+ if (!wildmatch(p, refname, WM_PATHNAME, NULL))
break;
}
if (!*pattern)
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 1affdd5e92..fc150c8821 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -144,7 +144,7 @@ static int traverse_reachable(void)
unsigned int nr = 0;
int result = 0;
if (show_progress)
- progress = start_progress_delay("Checking connectivity", 0, 0, 2);
+ progress = start_progress_delay(_("Checking connectivity"), 0, 0, 2);
while (pending.nr) {
struct object_array_entry *entry;
struct object *obj;
@@ -541,7 +541,7 @@ static void fsck_object_dir(const char *path)
fprintf(stderr, "Checking object directory\n");
if (show_progress)
- progress = start_progress("Checking object directories", 256);
+ progress = start_progress(_("Checking object directories"), 256);
for (i = 0; i < 256; i++) {
static char dir[4096];
sprintf(dir, "%s/%02x", path, i);
@@ -630,7 +630,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
struct alternate_object_database *alt;
errors_found = 0;
- read_replace_refs = 0;
+ check_replace_refs = 0;
argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
@@ -670,7 +670,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
total += p->num_objects;
}
- progress = start_progress("Checking objects", total);
+ progress = start_progress(_("Checking objects"), total);
}
for (p = packed_git; p; p = p->next) {
/* verify gives error messages itself */
diff --git a/builtin/gc.c b/builtin/gc.c
index 63d400bcb2..11cf295515 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -184,7 +184,7 @@ static int need_to_gc(void)
else if (!too_many_loose_objects())
return 0;
- if (run_hook(NULL, "pre-auto-gc", NULL))
+ if (run_hook_le(NULL, "pre-auto-gc", NULL))
return 0;
return 1;
}
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 2f37a38fbc..b9f6e12c0e 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1291,7 +1291,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
if (keep_fd < 0) {
if (errno != EEXIST)
die_errno(_("cannot write keep file '%s'"),
- keep_name);
+ keep_name ? keep_name : name);
} else {
if (keep_msg_len > 0) {
write_or_die(keep_fd, keep_msg, keep_msg_len);
@@ -1299,7 +1299,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
}
if (close(keep_fd) != 0)
die_errno(_("cannot close written keep file '%s'"),
- keep_name);
+ keep_name ? keep_name : name);
report = "keep";
}
}
@@ -1502,7 +1502,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
if (argc == 2 && !strcmp(argv[1], "-h"))
usage(index_pack_usage);
- read_replace_refs = 0;
+ check_replace_refs = 0;
reset_pack_idx_option(&opts);
git_config(git_index_pack_config, &opts);
diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
index 39e5144b9e..3e9eefb091 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -22,7 +22,7 @@ static int tail_match(const char **pattern, const char *path)
if (snprintf(pathbuf, sizeof(pathbuf), "/%s", path) > sizeof(pathbuf))
return error("insanely long ref %.*s...", 20, path);
while ((p = *(pattern++)) != NULL) {
- if (!fnmatch(p, pathbuf, 0))
+ if (!wildmatch(p, pathbuf, 0, NULL))
return 1;
}
return 0;
diff --git a/builtin/merge.c b/builtin/merge.c
index f0cf1205fa..e15d0e145a 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -421,7 +421,7 @@ static void finish(struct commit *head_commit,
}
/* Run a post-merge hook */
- run_hook(NULL, "post-merge", squash ? "1" : "0", NULL);
+ run_hook_le(NULL, "post-merge", squash ? "1" : "0", NULL);
strbuf_release(&reflog_message);
}
@@ -824,8 +824,8 @@ static void prepare_to_commit(struct commit_list *remoteheads)
if (0 < option_edit)
strbuf_commented_addf(&msg, _(merge_editor_comment), comment_line_char);
write_merge_msg(&msg);
- if (run_hook(get_index_file(), "prepare-commit-msg",
- git_path("MERGE_MSG"), "merge", NULL, NULL))
+ if (run_commit_hook(0 < option_edit, get_index_file(), "prepare-commit-msg",
+ git_path("MERGE_MSG"), "merge", NULL))
abort_commit(remoteheads, NULL);
if (0 < option_edit) {
if (launch_editor(git_path("MERGE_MSG"), NULL, NULL))
diff --git a/builtin/mktree.c b/builtin/mktree.c
index f92ba404ab..a964d6be52 100644
--- a/builtin/mktree.c
+++ b/builtin/mktree.c
@@ -23,10 +23,7 @@ static void append_to_tree(unsigned mode, unsigned char *sha1, char *path)
if (strchr(path, '/'))
die("path %s contains slash", path);
- if (alloc <= used) {
- alloc = alloc_nr(used);
- entries = xrealloc(entries, sizeof(*entries) * alloc);
- }
+ ALLOC_GROW(entries, used + 1, alloc);
ent = entries[used++] = xmalloc(sizeof(**entries) + len + 1);
ent->mode = mode;
ent->len = len;
diff --git a/builtin/mv.c b/builtin/mv.c
index 21c46d1636..2a7243f52e 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -162,7 +162,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
if (strncmp(path, src_w_slash, len_w_slash))
break;
}
- free((char *)src_w_slash);
+ if (src_w_slash != src)
+ free((char *)src_w_slash);
if (last - first < 1)
bad = _("source directory is empty");
@@ -179,6 +180,9 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
modes = xrealloc(modes,
(argc + last - first)
* sizeof(enum update_mode));
+ submodule_gitfile = xrealloc(submodule_gitfile,
+ (argc + last - first)
+ * sizeof(char *));
}
dst = add_slash(dst);
@@ -192,6 +196,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
prefix_path(dst, dst_len,
path + length + 1);
modes[argc + j] = INDEX;
+ submodule_gitfile[argc + j] = NULL;
}
argc += last - first;
}
@@ -227,6 +232,11 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
memmove(destination + i,
destination + i + 1,
(argc - i) * sizeof(char *));
+ memmove(modes + i, modes + i + 1,
+ (argc - i) * sizeof(enum update_mode));
+ memmove(submodule_gitfile + i,
+ submodule_gitfile + i + 1,
+ (argc - i) * sizeof(char *));
i--;
}
} else
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 0b21d7e5b2..c824d4ec5f 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -87,7 +87,7 @@ static int subpath_matches(const char *path, const char *filter)
const char *subpath = path;
while (subpath) {
- if (!fnmatch(filter, subpath, 0))
+ if (!wildmatch(filter, subpath, 0, NULL))
return subpath - path;
subpath = strchr(subpath, '/');
if (subpath)
diff --git a/builtin/notes.c b/builtin/notes.c
index 2b24d059b5..bb89930373 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -269,7 +269,11 @@ static int parse_reuse_arg(const struct option *opt, const char *arg, int unset)
die(_("Failed to resolve '%s' as a valid ref."), arg);
if (!(buf = read_sha1_file(object, &type, &len)) || !len) {
free(buf);
- die(_("Failed to read object '%s'."), arg);;
+ die(_("Failed to read object '%s'."), arg);
+ }
+ if (type != OBJ_BLOB) {
+ free(buf);
+ die(_("Cannot read note data from non-blob object '%s'."), arg);
}
strbuf_add(&(msg->buf), buf, len);
free(buf);
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index c73337931b..7950c4342f 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -708,7 +708,7 @@ static struct object_entry **compute_write_order(void)
static off_t write_reused_pack(struct sha1file *f)
{
unsigned char buffer[8192];
- off_t to_write;
+ off_t to_write, total;
int fd;
if (!is_pack_valid(reuse_packfile))
@@ -725,7 +725,7 @@ static off_t write_reused_pack(struct sha1file *f)
if (reuse_packfile_offset < 0)
reuse_packfile_offset = reuse_packfile->pack_size - 20;
- to_write = reuse_packfile_offset - sizeof(struct pack_header);
+ total = to_write = reuse_packfile_offset - sizeof(struct pack_header);
while (to_write) {
int read_pack = xread(fd, buffer, sizeof(buffer));
@@ -738,10 +738,23 @@ static off_t write_reused_pack(struct sha1file *f)
sha1write(f, buffer, read_pack);
to_write -= read_pack;
+
+ /*
+ * We don't know the actual number of objects written,
+ * only how many bytes written, how many bytes total, and
+ * how many objects total. So we can fake it by pretending all
+ * objects we are writing are the same size. This gives us a
+ * smooth progress meter, and at the end it matches the true
+ * answer.
+ */
+ written = reuse_packfile_objects *
+ (((double)(total - to_write)) / total);
+ display_progress(progress_state, written);
}
close(fd);
- written += reuse_packfile_objects;
+ written = reuse_packfile_objects;
+ display_progress(progress_state, written);
return reuse_packfile_offset - sizeof(struct pack_header);
}
@@ -755,7 +768,7 @@ static void write_pack_file(void)
struct object_entry **write_order;
if (progress > pack_to_stdout)
- progress_state = start_progress("Writing objects", nr_result);
+ progress_state = start_progress(_("Writing objects"), nr_result);
written_list = xmalloc(to_pack.nr_objects * sizeof(*written_list));
write_order = compute_write_order();
@@ -803,7 +816,7 @@ static void write_pack_file(void)
if (!pack_to_stdout) {
struct stat st;
- char tmpname[PATH_MAX];
+ struct strbuf tmpname = STRBUF_INIT;
/*
* Packs are runtime accessed in their mtime
@@ -823,26 +836,22 @@ static void write_pack_file(void)
utb.modtime = --last_mtime;
if (utime(pack_tmp_name, &utb) < 0)
warning("failed utime() on %s: %s",
- tmpname, strerror(errno));
+ pack_tmp_name, strerror(errno));
}
- /* Enough space for "-<sha-1>.pack"? */
- if (sizeof(tmpname) <= strlen(base_name) + 50)
- die("pack base name '%s' too long", base_name);
- snprintf(tmpname, sizeof(tmpname), "%s-", base_name);
+ strbuf_addf(&tmpname, "%s-", base_name);
if (write_bitmap_index) {
bitmap_writer_set_checksum(sha1);
bitmap_writer_build_type_index(written_list, nr_written);
}
- finish_tmp_packfile(tmpname, pack_tmp_name,
+ finish_tmp_packfile(&tmpname, pack_tmp_name,
written_list, nr_written,
&pack_idx_opts, sha1);
if (write_bitmap_index) {
- char *end_of_name_prefix = strrchr(tmpname, 0);
- sprintf(end_of_name_prefix, "%s.bitmap", sha1_to_hex(sha1));
+ strbuf_addf(&tmpname, "%s.bitmap", sha1_to_hex(sha1));
stop_progress(&progress_state);
@@ -851,10 +860,11 @@ static void write_pack_file(void)
bitmap_writer_select_commits(indexed_commits, indexed_commits_nr, -1);
bitmap_writer_build(&to_pack);
bitmap_writer_finish(written_list, nr_written,
- tmpname, write_bitmap_options);
+ tmpname.buf, write_bitmap_options);
write_bitmap_index = 0;
}
+ strbuf_release(&tmpname);
free(pack_tmp_name);
puts(sha1_to_hex(sha1));
}
@@ -998,6 +1008,10 @@ static void create_object_entry(const unsigned char *sha1,
entry->no_try_delta = no_try_delta;
}
+static const char no_closure_warning[] = N_(
+"disabling bitmap writing, as some objects are not being packed"
+);
+
static int add_object_entry(const unsigned char *sha1, enum object_type type,
const char *name, int exclude)
{
@@ -1008,14 +1022,20 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type,
if (have_duplicate_entry(sha1, exclude, &index_pos))
return 0;
- if (!want_object_in_pack(sha1, exclude, &found_pack, &found_offset))
+ if (!want_object_in_pack(sha1, exclude, &found_pack, &found_offset)) {
+ /* The pack is missing an object, so it will not have closure */
+ if (write_bitmap_index) {
+ warning(_(no_closure_warning));
+ write_bitmap_index = 0;
+ }
return 0;
+ }
create_object_entry(sha1, type, pack_name_hash(name),
exclude, name && no_try_delta(name),
index_pos, found_pack, found_offset);
- display_progress(progress_state, to_pack.nr_objects);
+ display_progress(progress_state, nr_result);
return 1;
}
@@ -1031,7 +1051,7 @@ static int add_object_entry_from_bitmap(const unsigned char *sha1,
create_object_entry(sha1, type, name_hash, 0, 0, index_pos, pack, offset);
- display_progress(progress_state, to_pack.nr_objects);
+ display_progress(progress_state, nr_result);
return 1;
}
@@ -1213,12 +1233,9 @@ static int check_pbase_path(unsigned hash)
if (0 <= pos)
return 1;
pos = -pos - 1;
- if (done_pbase_paths_alloc <= done_pbase_paths_num) {
- done_pbase_paths_alloc = alloc_nr(done_pbase_paths_alloc);
- done_pbase_paths = xrealloc(done_pbase_paths,
- done_pbase_paths_alloc *
- sizeof(unsigned));
- }
+ ALLOC_GROW(done_pbase_paths,
+ done_pbase_paths_num + 1,
+ done_pbase_paths_alloc);
done_pbase_paths_num++;
if (pos < done_pbase_paths_num)
memmove(done_pbase_paths + pos + 1,
@@ -2154,7 +2171,7 @@ static void prepare_pack(int window, int depth)
if (nr_deltas && n > 1) {
unsigned nr_done = 0;
if (progress)
- progress_state = start_progress("Compressing objects",
+ progress_state = start_progress(_("Compressing objects"),
nr_deltas);
qsort(delta_list, n, sizeof(*delta_list), type_size_sort);
ll_find_deltas(delta_list, n, window+1, depth, &nr_done);
@@ -2433,12 +2450,7 @@ static int get_object_list_from_bitmap(struct rev_info *revs)
&reuse_packfile_offset)) {
assert(reuse_packfile_objects);
nr_result += reuse_packfile_objects;
-
- if (progress) {
- fprintf(stderr, "Reusing existing pack: %d, done.\n",
- reuse_packfile_objects);
- fflush(stderr);
- }
+ display_progress(progress_state, nr_result);
}
traverse_bitmap_commit_list(&add_object_entry_from_bitmap);
@@ -2455,6 +2467,9 @@ static void get_object_list(int ac, const char **av)
save_commit_buffer = 0;
setup_revisions(ac, av, &revs, NULL);
+ /* make sure shallows are read */
+ is_repository_shallow();
+
while (fgets(line, sizeof(line), stdin) != NULL) {
int len = strlen(line);
if (len && line[len - 1] == '\n')
@@ -2467,6 +2482,13 @@ static void get_object_list(int ac, const char **av)
write_bitmap_index = 0;
continue;
}
+ if (starts_with(line, "--shallow ")) {
+ unsigned char sha1[20];
+ if (get_sha1_hex(line + 10, sha1))
+ die("not an SHA-1 '%s'", line + 10);
+ register_shallow(sha1);
+ continue;
+ }
die("not a rev '%s'", line);
}
if (handle_revision_arg(line, &revs, flags, REVARG_CANNOT_BE_FILENAME))
@@ -2612,7 +2634,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
OPT_END(),
};
- read_replace_refs = 0;
+ check_replace_refs = 0;
reset_pack_idx_option(&pack_idx_opts);
git_config(git_pack_config, NULL);
@@ -2687,7 +2709,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
prepare_packed_git();
if (progress)
- progress_state = start_progress("Counting objects", 0);
+ progress_state = start_progress(_("Counting objects"), 0);
if (!use_internal_rev_list)
read_object_list_from_stdin();
else {
diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
index fcf5fb6129..6879468c46 100644
--- a/builtin/prune-packed.c
+++ b/builtin/prune-packed.c
@@ -46,7 +46,7 @@ void prune_packed_objects(int opts)
strbuf_addstr(&pathname, dir);
if (opts & PRUNE_PACKED_VERBOSE)
- progress = start_progress_delay("Removing duplicate objects",
+ progress = start_progress_delay(_("Removing duplicate objects"),
256, 95, 2);
if (pathname.len && pathname.buf[pathname.len - 1] != '/')
diff --git a/builtin/prune.c b/builtin/prune.c
index de43b26cfe..144a3bdb33 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -150,7 +150,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
expire = ULONG_MAX;
save_commit_buffer = 0;
- read_replace_refs = 0;
+ check_replace_refs = 0;
init_revisions(&revs, prefix);
argc = parse_options(argc, argv, prefix, options, prune_usage, 0);
@@ -169,7 +169,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
if (show_progress == -1)
show_progress = isatty(2);
if (show_progress)
- progress = start_progress_delay("Checking connectivity", 0, 0, 2);
+ progress = start_progress_delay(_("Checking connectivity"), 0, 0, 2);
mark_reachable_objects(&revs, 1, progress);
stop_progress(&progress);
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 85bba356fa..c3230817db 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -828,14 +828,10 @@ static void execute_commands(struct command *commands,
}
}
- if (shallow_update) {
- if (!checked_connectivity)
- error("BUG: run 'git fsck' for safety.\n"
- "If there are errors, try to remove "
- "the reported refs above");
- if (alt_shallow_file && *alt_shallow_file)
- unlink(alt_shallow_file);
- }
+ if (shallow_update && !checked_connectivity)
+ error("BUG: run 'git fsck' for safety.\n"
+ "If there are errors, try to remove "
+ "the reported refs above");
}
static struct command *read_head_info(struct sha1_array *shallow)
@@ -1087,10 +1083,6 @@ static void update_shallow_info(struct command *commands,
cmd->skip_update = 1;
}
}
- if (alt_shallow_file && *alt_shallow_file) {
- unlink(alt_shallow_file);
- alt_shallow_file = NULL;
- }
free(ref_status);
}
diff --git a/builtin/reflog.c b/builtin/reflog.c
index 852cff60b7..c12a9784e6 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -561,7 +561,7 @@ static void set_reflog_expiry_param(struct cmd_reflog_expire_cb *cb, int slot, c
return; /* both given explicitly -- nothing to tweak */
for (ent = reflog_expire_cfg; ent; ent = ent->next) {
- if (!fnmatch(ent->pattern, ref, 0)) {
+ if (!wildmatch(ent->pattern, ref, 0, NULL)) {
if (!(slot & EXPIRE_TOTAL))
cb->expire_total = ent->expire_total;
if (!(slot & EXPIRE_UNREACH))
diff --git a/builtin/repack.c b/builtin/repack.c
index 49f5857627..6b0b62dcb2 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -9,6 +9,7 @@
#include "argv-array.h"
static int delta_base_offset = 1;
+static int pack_kept_objects = -1;
static char *packdir, *packtmp;
static const char *const git_repack_usage[] = {
@@ -22,6 +23,10 @@ static int repack_config(const char *var, const char *value, void *cb)
delta_base_offset = git_config_bool(var, value);
return 0;
}
+ if (!strcmp(var, "repack.packkeptobjects")) {
+ pack_kept_objects = git_config_bool(var, value);
+ return 0;
+ }
return git_default_config(var, value, cb);
}
@@ -175,6 +180,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
N_("limits the maximum delta depth")),
OPT_STRING(0, "max-pack-size", &max_pack_size, N_("bytes"),
N_("maximum size of each packfile")),
+ OPT_BOOL(0, "pack-kept-objects", &pack_kept_objects,
+ N_("repack objects in packs marked with .keep")),
OPT_END()
};
@@ -183,6 +190,9 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix, builtin_repack_options,
git_repack_usage, 0);
+ if (pack_kept_objects < 0)
+ pack_kept_objects = write_bitmap;
+
packdir = mkpathdup("%s/pack", get_object_directory());
packtmp = mkpathdup("%s/.tmp-%d-pack", packdir, (int)getpid());
@@ -190,7 +200,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
argv_array_push(&cmd_args, "pack-objects");
argv_array_push(&cmd_args, "--keep-true-parents");
- argv_array_push(&cmd_args, "--honor-pack-keep");
+ if (!pack_kept_objects)
+ argv_array_push(&cmd_args, "--honor-pack-keep");
argv_array_push(&cmd_args, "--non-empty");
argv_array_push(&cmd_args, "--all");
argv_array_push(&cmd_args, "--reflog");
diff --git a/builtin/replace.c b/builtin/replace.c
index 2336325ce3..b62420a01a 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -36,7 +36,7 @@ static int show_reference(const char *refname, const unsigned char *sha1,
{
struct show_data *data = cb_data;
- if (!fnmatch(data->pattern, refname, 0)) {
+ if (!wildmatch(data->pattern, refname, 0, NULL)) {
if (data->format == REPLACE_FORMAT_SHORT)
printf("%s\n", refname);
else if (data->format == REPLACE_FORMAT_MEDIUM)
@@ -178,7 +178,7 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
OPT_END()
};
- read_replace_refs = 0;
+ check_replace_refs = 0;
argc = parse_options(argc, argv, prefix, options, git_replace_usage, 0);
diff --git a/builtin/reset.c b/builtin/reset.c
index 4fd1c6c51d..f4e087596b 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -333,7 +333,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
if (reset_type == NONE)
reset_type = MIXED; /* by default */
- if (reset_type != SOFT && reset_type != MIXED)
+ if (reset_type != SOFT && (reset_type != MIXED || get_git_work_tree()))
setup_work_tree();
if (reset_type == MIXED && is_bare_repository())
@@ -356,8 +356,9 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
if (read_from_tree(&pathspec, sha1, intent_to_add))
return 1;
- refresh_index(&the_index, flags, NULL, NULL,
- _("Unstaged changes after reset:"));
+ if (get_git_work_tree())
+ refresh_index(&the_index, flags, NULL, NULL,
+ _("Unstaged changes after reset:"));
} else {
int err = reset_index(sha1, reset_type, quiet);
if (reset_type == KEEP && !err)
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 45901df371..1a6122d3ae 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -395,9 +395,10 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
usage[unb++] = strbuf_detach(&sb, NULL);
}
- /* parse: (<short>|<short>,<long>|<long>)[=?]? SP+ <help> */
+ /* parse: (<short>|<short>,<long>|<long>)[*=?!]*<arghint>? SP+ <help> */
while (strbuf_getline(&sb, stdin, '\n') != EOF) {
const char *s;
+ const char *end;
struct option *o;
if (!sb.len)
@@ -419,6 +420,16 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
o->value = &parsed;
o->flags = PARSE_OPT_NOARG;
o->callback = &parseopt_dump;
+
+ /* Possible argument name hint */
+ end = s;
+ while (s > sb.buf && strchr("*=?!", s[-1]) == NULL)
+ --s;
+ if (s != sb.buf && s != end)
+ o->argh = xmemdupz(s, end - s);
+ if (s == sb.buf)
+ s = end;
+
while (s > sb.buf && strchr("*=?!", s[-1])) {
switch (*--s) {
case '=':
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index d9217ce1e1..d87317290c 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -450,7 +450,7 @@ static int append_matching_ref(const char *refname, const unsigned char *sha1, i
slash--;
if (!*tail)
return 0;
- if (fnmatch(match_ref_pattern, tail, 0))
+ if (wildmatch(match_ref_pattern, tail, 0, NULL))
return 0;
if (starts_with(refname, "refs/heads/"))
return append_head_ref(refname, sha1, flag, cb_data);
diff --git a/builtin/tag.c b/builtin/tag.c
index 74d3780b77..40356e3e41 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -27,9 +27,16 @@ static const char * const git_tag_usage[] = {
NULL
};
+#define STRCMP_SORT 0 /* must be zero */
+#define VERCMP_SORT 1
+#define SORT_MASK 0x7fff
+#define REVERSE_SORT 0x8000
+
struct tag_filter {
const char **patterns;
int lines;
+ int sort;
+ struct string_list tags;
struct commit_list *with_commit;
};
@@ -42,7 +49,7 @@ static int match_pattern(const char **patterns, const char *ref)
if (!*patterns)
return 1;
for (; *patterns; patterns++)
- if (!fnmatch(*patterns, ref, 0))
+ if (!wildmatch(*patterns, ref, 0, NULL))
return 1;
return 0;
}
@@ -166,7 +173,10 @@ static int show_reference(const char *refname, const unsigned char *sha1,
return 0;
if (!filter->lines) {
- printf("%s\n", refname);
+ if (filter->sort)
+ string_list_append(&filter->tags, refname);
+ else
+ printf("%s\n", refname);
return 0;
}
printf("%-15s ", refname);
@@ -177,17 +187,39 @@ static int show_reference(const char *refname, const unsigned char *sha1,
return 0;
}
+static int sort_by_version(const void *a_, const void *b_)
+{
+ const struct string_list_item *a = a_;
+ const struct string_list_item *b = b_;
+ return versioncmp(a->string, b->string);
+}
+
static int list_tags(const char **patterns, int lines,
- struct commit_list *with_commit)
+ struct commit_list *with_commit, int sort)
{
struct tag_filter filter;
filter.patterns = patterns;
filter.lines = lines;
+ filter.sort = sort;
filter.with_commit = with_commit;
+ memset(&filter.tags, 0, sizeof(filter.tags));
+ filter.tags.strdup_strings = 1;
for_each_tag_ref(show_reference, (void *) &filter);
-
+ if (sort) {
+ int i;
+ if ((sort & SORT_MASK) == VERCMP_SORT)
+ qsort(filter.tags.items, filter.tags.nr,
+ sizeof(struct string_list_item), sort_by_version);
+ if (sort & REVERSE_SORT)
+ for (i = filter.tags.nr - 1; i >= 0; i--)
+ printf("%s\n", filter.tags.items[i].string);
+ else
+ for (i = 0; i < filter.tags.nr; i++)
+ printf("%s\n", filter.tags.items[i].string);
+ string_list_clear(&filter.tags, 0);
+ }
return 0;
}
@@ -427,6 +459,29 @@ static int parse_opt_points_at(const struct option *opt __attribute__((unused)),
return 0;
}
+static int parse_opt_sort(const struct option *opt, const char *arg, int unset)
+{
+ int *sort = opt->value;
+ int flags = 0;
+
+ if (*arg == '-') {
+ flags |= REVERSE_SORT;
+ arg++;
+ }
+ if (starts_with(arg, "version:")) {
+ *sort = VERCMP_SORT;
+ arg += 8;
+ } else if (starts_with(arg, "v:")) {
+ *sort = VERCMP_SORT;
+ arg += 2;
+ } else
+ *sort = STRCMP_SORT;
+ if (strcmp(arg, "refname"))
+ die(_("unsupported sort specification %s"), arg);
+ *sort |= flags;
+ return 0;
+}
+
int cmd_tag(int argc, const char **argv, const char *prefix)
{
struct strbuf buf = STRBUF_INIT;
@@ -437,7 +492,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
struct create_tag_options opt;
char *cleanup_arg = NULL;
int annotate = 0, force = 0, lines = -1;
- int cmdmode = 0;
+ int cmdmode = 0, sort = 0;
const char *msgfile = NULL, *keyid = NULL;
struct msg_arg msg = { 0, STRBUF_INIT };
struct commit_list *with_commit = NULL;
@@ -462,6 +517,10 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
N_("use another key to sign the tag")),
OPT__FORCE(&force, N_("replace the tag if exists")),
OPT_COLUMN(0, "column", &colopts, N_("show tag list in columns")),
+ {
+ OPTION_CALLBACK, 0, "sort", &sort, N_("type"), N_("sort tags"),
+ PARSE_OPT_NONEG, parse_opt_sort
+ },
OPT_GROUP(N_("Tag listing options")),
{
@@ -471,6 +530,12 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
parse_opt_with_commit, (intptr_t)"HEAD",
},
{
+ OPTION_CALLBACK, 0, "with", &with_commit, N_("commit"),
+ N_("print only tags that contain the commit"),
+ PARSE_OPT_HIDDEN | PARSE_OPT_LASTARG_DEFAULT,
+ parse_opt_with_commit, (intptr_t)"HEAD",
+ },
+ {
OPTION_CALLBACK, 0, "points-at", NULL, N_("object"),
N_("print only tags of the object"), 0, parse_opt_points_at
},
@@ -509,7 +574,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
copts.padding = 2;
run_column_filter(colopts, &copts);
}
- ret = list_tags(argv, lines == -1 ? 0 : lines, with_commit);
+ if (lines != -1 && sort)
+ die(_("--sort and -n are incompatible"));
+ ret = list_tags(argv, lines == -1 ? 0 : lines, with_commit, sort);
if (column_active(colopts))
stop_column_filter();
return ret;
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 62ff673f68..99cde45879 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -480,7 +480,7 @@ static void unpack_all(void)
use(sizeof(struct pack_header));
if (!quiet)
- progress = start_progress("Unpacking objects", nr_objects);
+ progress = start_progress(_("Unpacking objects"), nr_objects);
obj_list = xcalloc(nr_objects, sizeof(*obj_list));
for (i = 0; i < nr_objects; i++) {
unpack_one(i);
@@ -497,7 +497,7 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
int i;
unsigned char sha1[20];
- read_replace_refs = 0;
+ check_replace_refs = 0;
git_config(git_default_config, NULL);
diff --git a/bulk-checkin.c b/bulk-checkin.c
index 118c62528b..98e651c284 100644
--- a/bulk-checkin.c
+++ b/bulk-checkin.c
@@ -4,6 +4,7 @@
#include "bulk-checkin.h"
#include "csum-file.h"
#include "pack.h"
+#include "strbuf.h"
static int pack_compression_level = Z_DEFAULT_COMPRESSION;
@@ -23,7 +24,7 @@ static struct bulk_checkin_state {
static void finish_bulk_checkin(struct bulk_checkin_state *state)
{
unsigned char sha1[20];
- char packname[PATH_MAX];
+ struct strbuf packname = STRBUF_INIT;
int i;
if (!state->f)
@@ -43,8 +44,8 @@ static void finish_bulk_checkin(struct bulk_checkin_state *state)
close(fd);
}
- sprintf(packname, "%s/pack/pack-", get_object_directory());
- finish_tmp_packfile(packname, state->pack_tmp_name,
+ strbuf_addf(&packname, "%s/pack/pack-", get_object_directory());
+ finish_tmp_packfile(&packname, state->pack_tmp_name,
state->written, state->nr_written,
&state->pack_idx_opts, sha1);
for (i = 0; i < state->nr_written; i++)
@@ -54,6 +55,7 @@ clear_exit:
free(state->written);
memset(state, 0, sizeof(*state));
+ strbuf_release(&packname);
/* Make objects we just wrote available to ourselves */
reprepare_packed_git();
}
diff --git a/bundle.c b/bundle.c
index e99065ce42..a85e0e4532 100644
--- a/bundle.c
+++ b/bundle.c
@@ -14,12 +14,8 @@ static const char bundle_signature[] = "# v2 git bundle\n";
static void add_to_ref_list(const unsigned char *sha1, const char *name,
struct ref_list *list)
{
- if (list->nr + 1 >= list->alloc) {
- list->alloc = alloc_nr(list->nr + 1);
- list->list = xrealloc(list->list,
- list->alloc * sizeof(list->list[0]));
- }
- memcpy(list->list[list->nr].sha1, sha1, 20);
+ ALLOC_GROW(list->list, list->nr + 1, list->alloc);
+ hashcpy(list->list[list->nr].sha1, sha1);
list->list[list->nr].name = xstrdup(name);
list->nr++;
}
diff --git a/cache-tree.c b/cache-tree.c
index 0bbec43216..7fa524a113 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -75,11 +75,7 @@ static struct cache_tree_sub *find_subtree(struct cache_tree *it,
return NULL;
pos = -pos-1;
- if (it->subtree_alloc <= it->subtree_nr) {
- it->subtree_alloc = alloc_nr(it->subtree_alloc);
- it->down = xrealloc(it->down, it->subtree_alloc *
- sizeof(*it->down));
- }
+ ALLOC_GROW(it->down, it->subtree_nr + 1, it->subtree_alloc);
it->subtree_nr++;
down = xmalloc(sizeof(*down) + pathlen + 1);
@@ -121,11 +117,11 @@ void cache_tree_invalidate_path(struct cache_tree *it, const char *path)
if (!it)
return;
- slash = strchr(path, '/');
+ slash = strchrnul(path, '/');
+ namelen = slash - path;
it->entry_count = -1;
- if (!slash) {
+ if (!*slash) {
int pos;
- namelen = strlen(path);
pos = subtree_pos(it, path, namelen);
if (0 <= pos) {
cache_tree_free(&it->down[pos]->cache_tree);
@@ -143,7 +139,6 @@ void cache_tree_invalidate_path(struct cache_tree *it, const char *path)
}
return;
}
- namelen = slash - path;
down = find_subtree(it, path, namelen, 0);
if (down)
cache_tree_invalidate_path(down->cache_tree, slash + 1);
@@ -554,22 +549,19 @@ static struct cache_tree *cache_tree_find(struct cache_tree *it, const char *pat
const char *slash;
struct cache_tree_sub *sub;
- slash = strchr(path, '/');
- if (!slash)
- slash = path + strlen(path);
- /* between path and slash is the name of the
- * subtree to look for.
+ slash = strchrnul(path, '/');
+ /*
+ * Between path and slash is the name of the subtree
+ * to look for.
*/
sub = find_subtree(it, path, slash - path, 0);
if (!sub)
return NULL;
it = sub->cache_tree;
- if (slash)
- while (*slash && *slash == '/')
- slash++;
- if (!slash || !*slash)
- return it; /* prefix ended with slashes */
+
path = slash;
+ while (*path == '/')
+ path++;
}
return it;
}
diff --git a/cache.h b/cache.h
index 4c0043113c..107ac61b68 100644
--- a/cache.h
+++ b/cache.h
@@ -581,7 +581,17 @@ extern size_t packed_git_limit;
extern size_t delta_base_cache_limit;
extern unsigned long big_file_threshold;
extern unsigned long pack_size_limit_cfg;
-extern int read_replace_refs;
+
+/*
+ * Do replace refs need to be checked this run? This variable is
+ * initialized to true unless --no-replace-object is used or
+ * $GIT_NO_REPLACE_OBJECTS is set, but is set to false by some
+ * commands that do not want replace references to be active. As an
+ * optimization it is also set to false if replace references have
+ * been sought but there were none.
+ */
+extern int check_replace_refs;
+
extern int fsync_object_files;
extern int core_preload_index;
extern int core_apply_sparse_checkout;
@@ -660,9 +670,28 @@ extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)
extern char *git_path_submodule(const char *path, const char *fmt, ...)
__attribute__((format (printf, 2, 3)));
-extern char *sha1_file_name(const unsigned char *sha1);
+/*
+ * Return the name of the file in the local object database that would
+ * be used to store a loose object with the specified sha1. The
+ * return value is a pointer to a statically allocated buffer that is
+ * overwritten each time the function is called.
+ */
+extern const char *sha1_file_name(const unsigned char *sha1);
+
+/*
+ * Return the name of the (local) packfile with the specified sha1 in
+ * its name. The return value is a pointer to memory that is
+ * overwritten each time this function is called.
+ */
extern char *sha1_pack_name(const unsigned char *sha1);
+
+/*
+ * Return the name of the (local) pack index file with the specified
+ * sha1 in its name. The return value is a pointer to memory that is
+ * overwritten each time this function is called.
+ */
extern char *sha1_pack_index_name(const unsigned char *sha1);
+
extern const char *find_unique_abbrev(const unsigned char *sha1, int);
extern const unsigned char null_sha1[20];
@@ -789,13 +818,26 @@ static inline void *read_sha1_file(const unsigned char *sha1, enum object_type *
{
return read_sha1_file_extended(sha1, type, size, LOOKUP_REPLACE_OBJECT);
}
+
+/*
+ * This internal function is only declared here for the benefit of
+ * lookup_replace_object(). Please do not call it directly.
+ */
extern const unsigned char *do_lookup_replace_object(const unsigned char *sha1);
+
+/*
+ * If object sha1 should be replaced, return the replacement object's
+ * name (replaced recursively, if necessary). The return value is
+ * either sha1 or a pointer to a permanently-allocated value. When
+ * object replacement is suppressed, always return sha1.
+ */
static inline const unsigned char *lookup_replace_object(const unsigned char *sha1)
{
- if (!read_replace_refs)
+ if (!check_replace_refs)
return sha1;
return do_lookup_replace_object(sha1);
}
+
static inline const unsigned char *lookup_replace_object_extended(const unsigned char *sha1, unsigned flag)
{
if (!(flag & LOOKUP_REPLACE_OBJECT))
@@ -822,7 +864,19 @@ extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned l
extern int move_temp_to_file(const char *tmpfile, const char *filename);
extern int has_sha1_pack(const unsigned char *sha1);
+
+/*
+ * Return true iff we have an object named sha1, whether local or in
+ * an alternate object database, and whether packed or loose. This
+ * function does not respect replace references.
+ */
extern int has_sha1_file(const unsigned char *sha1);
+
+/*
+ * Return true iff an alternate object database has a loose object
+ * with the specified name. This function does not respect replace
+ * references.
+ */
extern int has_loose_object_nonlocal(const unsigned char *sha1);
extern int has_pack_index(const unsigned char *sha1);
@@ -961,6 +1015,7 @@ void datestamp(char *buf, int bufsize);
unsigned long approxidate_careful(const char *, int *);
unsigned long approxidate_relative(const char *date, const struct timeval *now);
enum date_mode parse_date_format(const char *format);
+int date_overflows(unsigned long date);
#define IDENT_STRICT 1
#define IDENT_NO_DATE 2
@@ -1085,17 +1140,46 @@ extern struct packed_git *find_sha1_pack(const unsigned char *sha1,
struct packed_git *packs);
extern void pack_report(void);
+
+/*
+ * mmap the index file for the specified packfile (if it is not
+ * already mmapped). Return 0 on success.
+ */
extern int open_pack_index(struct packed_git *);
+
+/*
+ * munmap the index file for the specified packfile (if it is
+ * currently mmapped).
+ */
extern void close_pack_index(struct packed_git *);
+
extern unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t, unsigned long *);
extern void close_pack_windows(struct packed_git *);
extern void unuse_pack(struct pack_window **);
extern void free_pack_by_name(const char *);
extern void clear_delta_base_cache(void);
extern struct packed_git *add_packed_git(const char *, int, int);
-extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t);
-extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t);
-extern off_t find_pack_entry_one(const unsigned char *, struct packed_git *);
+
+/*
+ * Return the SHA-1 of the nth object within the specified packfile.
+ * Open the index if it is not already open. The return value points
+ * at the SHA-1 within the mmapped index. Return NULL if there is an
+ * error.
+ */
+extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t n);
+
+/*
+ * Return the offset of the nth object within the specified packfile.
+ * The index must already be opened.
+ */
+extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t n);
+
+/*
+ * If the object named sha1 is present in the specified packfile,
+ * return its offset within the packfile; otherwise, return 0.
+ */
+extern off_t find_pack_entry_one(const unsigned char *sha1, struct packed_git *);
+
extern int is_pack_valid(struct packed_git *);
extern void *unpack_entry(struct packed_git *, off_t, enum object_type *, unsigned long *);
extern unsigned long unpack_object_header_buffer(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);
@@ -1148,6 +1232,12 @@ extern int update_server_info(int);
#define CONFIG_INVALID_PATTERN 6
#define CONFIG_GENERIC_ERROR 7
+struct git_config_source {
+ unsigned int use_stdin:1;
+ const char *file;
+ const char *blob;
+};
+
typedef int (*config_fn_t)(const char *, const char *, void *);
extern int git_default_config(const char *, const char *, void *);
extern int git_config_from_file(config_fn_t fn, const char *, void *);
@@ -1157,8 +1247,7 @@ extern void git_config_push_parameter(const char *text);
extern int git_config_from_parameters(config_fn_t fn, void *data);
extern int git_config(config_fn_t fn, void *);
extern int git_config_with_options(config_fn_t fn, void *,
- const char *filename,
- const char *blob_ref,
+ struct git_config_source *config_source,
int respect_includes);
extern int git_config_early(config_fn_t fn, void *, const char *repo_config);
extern int git_parse_ulong(const char *, unsigned long *);
@@ -1369,4 +1458,6 @@ int stat_validity_check(struct stat_validity *sv, const char *path);
*/
void stat_validity_update(struct stat_validity *sv, int fd);
+int versioncmp(const char *s1, const char *s2);
+
#endif /* CACHE_H */
diff --git a/commit.c b/commit.c
index 6bf4fe00d4..0f28902bc3 100644
--- a/commit.c
+++ b/commit.c
@@ -10,6 +10,7 @@
#include "mergesort.h"
#include "commit-slab.h"
#include "prio-queue.h"
+#include "sha1-lookup.h"
static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
@@ -114,23 +115,16 @@ static unsigned long parse_commit_date(const char *buf, const char *tail)
static struct commit_graft **commit_graft;
static int commit_graft_alloc, commit_graft_nr;
+static const unsigned char *commit_graft_sha1_access(size_t index, void *table)
+{
+ struct commit_graft **commit_graft_table = table;
+ return commit_graft_table[index]->sha1;
+}
+
static int commit_graft_pos(const unsigned char *sha1)
{
- int lo, hi;
- lo = 0;
- hi = commit_graft_nr;
- while (lo < hi) {
- int mi = (lo + hi) / 2;
- struct commit_graft *graft = commit_graft[mi];
- int cmp = hashcmp(sha1, graft->sha1);
- if (!cmp)
- return mi;
- if (cmp < 0)
- hi = mi;
- else
- lo = mi + 1;
- }
- return -lo - 1;
+ return sha1_pos(sha1, commit_graft, commit_graft_nr,
+ commit_graft_sha1_access);
}
int register_commit_graft(struct commit_graft *graft, int ignore_dups)
@@ -147,12 +141,8 @@ int register_commit_graft(struct commit_graft *graft, int ignore_dups)
return 1;
}
pos = -pos - 1;
- if (commit_graft_alloc <= ++commit_graft_nr) {
- commit_graft_alloc = alloc_nr(commit_graft_alloc);
- commit_graft = xrealloc(commit_graft,
- sizeof(*commit_graft) *
- commit_graft_alloc);
- }
+ ALLOC_GROW(commit_graft, commit_graft_nr + 1, commit_graft_alloc);
+ commit_graft_nr++;
if (pos < commit_graft_nr)
memmove(commit_graft + pos + 1,
commit_graft + pos,
@@ -548,7 +538,7 @@ define_commit_slab(author_date_slab, unsigned long);
static void record_author_date(struct author_date_slab *author_date,
struct commit *commit)
{
- const char *buf, *line_end;
+ const char *buf, *line_end, *ident_line;
char *buffer = NULL;
struct ident_split ident;
char *date_end;
@@ -566,14 +556,14 @@ static void record_author_date(struct author_date_slab *author_date,
buf;
buf = line_end + 1) {
line_end = strchrnul(buf, '\n');
- if (!starts_with(buf, "author ")) {
+ ident_line = skip_prefix(buf, "author ");
+ if (!ident_line) {
if (!line_end[0] || line_end[1] == '\n')
return; /* end of header */
continue;
}
if (split_ident_line(&ident,
- buf + strlen("author "),
- line_end - (buf + strlen("author "))) ||
+ ident_line, line_end - ident_line) ||
!ident.date_begin || !ident.date_end)
goto fail_exit; /* malformed "author" line */
break;
@@ -1193,10 +1183,8 @@ static void parse_gpg_output(struct signature_check *sigc)
for (i = 0; i < ARRAY_SIZE(sigcheck_gpg_status); i++) {
const char *found, *next;
- if (starts_with(buf, sigcheck_gpg_status[i].check + 1)) {
- /* At the very beginning of the buffer */
- found = buf + strlen(sigcheck_gpg_status[i].check + 1);
- } else {
+ found = skip_prefix(buf, sigcheck_gpg_status[i].check + 1);
+ if (!found) {
found = strstr(buf, sigcheck_gpg_status[i].check);
if (!found)
continue;
diff --git a/commit.h b/commit.h
index 16d9c43513..a9f177ba48 100644
--- a/commit.h
+++ b/commit.h
@@ -209,7 +209,7 @@ extern int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
extern void setup_alternate_shallow(struct lock_file *shallow_lock,
const char **alternate_shallow_file,
const struct sha1_array *extra);
-extern char *setup_temporary_shallow(const struct sha1_array *extra);
+extern const char *setup_temporary_shallow(const struct sha1_array *extra);
extern void advertise_shallow_grafts(int);
struct shallow_info {
@@ -304,4 +304,7 @@ extern void check_commit_signature(const struct commit* commit, struct signature
int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused);
+LAST_ARG_MUST_BE_NULL
+extern int run_commit_hook(int editor_is_used, const char *index_file, const char *name, ...);
+
#endif /* COMMIT_H */
diff --git a/compat/fnmatch/fnmatch.c b/compat/fnmatch/fnmatch.c
deleted file mode 100644
index 378c467401..0000000000
--- a/compat/fnmatch/fnmatch.c
+++ /dev/null
@@ -1,494 +0,0 @@
-/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-/* Enable GNU extensions in fnmatch.h. */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-#endif
-
-#include <stddef.h>
-#include <errno.h>
-#include <fnmatch.h>
-#include <ctype.h>
-
-#if HAVE_STRING_H || defined _LIBC
-# include <string.h>
-#else
-# include <strings.h>
-#endif
-
-#if defined STDC_HEADERS || defined _LIBC
-# include <stdlib.h>
-#endif
-
-/* For platforms which support the ISO C amendment 1 functionality we
- support user defined character classes. */
-#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
-/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
-# include <wchar.h>
-# include <wctype.h>
-#endif
-
-/* Comment out all this code if we are using the GNU C Library, and are not
- actually compiling the library itself. This code is part of the GNU C
- Library, but also included in many other GNU distributions. Compiling
- and linking in this code is a waste when using the GNU C library
- (especially if it is a shared library). Rather than having every GNU
- program understand `configure --with-gnu-libc' and omit the object files,
- it is simpler to just do this in the source for each such file. */
-
-#if defined NO_FNMATCH || defined NO_FNMATCH_CASEFOLD || \
- defined _LIBC || !defined __GNU_LIBRARY__
-
-
-# if defined STDC_HEADERS || !defined isascii
-# define ISASCII(c) 1
-# else
-# define ISASCII(c) isascii(c)
-# endif
-
-# ifdef isblank
-# define ISBLANK(c) (ISASCII (c) && isblank (c))
-# else
-# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
-# endif
-# ifdef isgraph
-# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
-# else
-# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
-# endif
-
-# define ISPRINT(c) (ISASCII (c) && isprint (c))
-# define ISDIGIT(c) (ISASCII (c) && isdigit (c))
-# define ISALNUM(c) (ISASCII (c) && isalnum (c))
-# define ISALPHA(c) (ISASCII (c) && isalpha (c))
-# define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
-# define ISLOWER(c) (ISASCII (c) && islower (c))
-# define ISPUNCT(c) (ISASCII (c) && ispunct (c))
-# define ISSPACE(c) (ISASCII (c) && isspace (c))
-# define ISUPPER(c) (ISASCII (c) && isupper (c))
-# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
-
-# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
-
-# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
-/* The GNU C library provides support for user-defined character classes
- and the functions from ISO C amendment 1. */
-# ifdef CHARCLASS_NAME_MAX
-# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
-# else
-/* This shouldn't happen but some implementation might still have this
- problem. Use a reasonable default value. */
-# define CHAR_CLASS_MAX_LENGTH 256
-# endif
-
-# ifdef _LIBC
-# define IS_CHAR_CLASS(string) __wctype (string)
-# else
-# define IS_CHAR_CLASS(string) wctype (string)
-# endif
-# else
-# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
-
-# define IS_CHAR_CLASS(string) \
- (STREQ (string, "alpha") || STREQ (string, "upper") \
- || STREQ (string, "lower") || STREQ (string, "digit") \
- || STREQ (string, "alnum") || STREQ (string, "xdigit") \
- || STREQ (string, "space") || STREQ (string, "print") \
- || STREQ (string, "punct") || STREQ (string, "graph") \
- || STREQ (string, "cntrl") || STREQ (string, "blank"))
-# endif
-
-/* Avoid depending on library functions or files
- whose names are inconsistent. */
-
-# if !defined _LIBC && !defined getenv
-extern char *getenv (const char *name);
-# endif
-
-# ifndef errno
-extern int errno;
-# endif
-
-# ifndef NULL
-# define NULL 0
-# endif
-
-/* This function doesn't exist on most systems. */
-
-# if !defined HAVE___STRCHRNUL && !defined _LIBC
-static char *
-__strchrnul (const char *s, int c)
-
-
-{
- char *result = strchr (s, c);
- if (result == NULL)
- result = strchr (s, '\0');
- return result;
-}
-# endif
-
-# ifndef internal_function
-/* Inside GNU libc we mark some function in a special way. In other
- environments simply ignore the marking. */
-# define internal_function
-# endif
-
-/* Match STRING against the filename pattern PATTERN, returning zero if
- it matches, nonzero if not. */
-static int internal_fnmatch __P ((const char *pattern, const char *string,
- int no_leading_period, int flags))
- internal_function;
-static int
-internal_function
-internal_fnmatch (const char *pattern, const char *string, int no_leading_period, int flags)
-
-
-
-
-{
- register const char *p = pattern, *n = string;
- register unsigned char c;
-
-/* Note that this evaluates C many times. */
-# ifdef _LIBC
-# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
-# else
-# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
-# endif
-
- while ((c = *p++) != '\0')
- {
- c = FOLD (c);
-
- switch (c)
- {
- case '?':
- if (*n == '\0')
- return FNM_NOMATCH;
- else if (*n == '/' && (flags & FNM_FILE_NAME))
- return FNM_NOMATCH;
- else if (*n == '.' && no_leading_period
- && (n == string
- || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
- return FNM_NOMATCH;
- break;
-
- case '\\':
- if (!(flags & FNM_NOESCAPE))
- {
- c = *p++;
- if (c == '\0')
- /* Trailing \ loses. */
- return FNM_NOMATCH;
- c = FOLD (c);
- }
- if (FOLD ((unsigned char) *n) != c)
- return FNM_NOMATCH;
- break;
-
- case '*':
- if (*n == '.' && no_leading_period
- && (n == string
- || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
- return FNM_NOMATCH;
-
- for (c = *p++; c == '?' || c == '*'; c = *p++)
- {
- if (*n == '/' && (flags & FNM_FILE_NAME))
- /* A slash does not match a wildcard under FNM_FILE_NAME. */
- return FNM_NOMATCH;
- else if (c == '?')
- {
- /* A ? needs to match one character. */
- if (*n == '\0')
- /* There isn't another character; no match. */
- return FNM_NOMATCH;
- else
- /* One character of the string is consumed in matching
- this ? wildcard, so *??? won't match if there are
- less than three characters. */
- ++n;
- }
- }
-
- if (c == '\0')
- /* The wildcard(s) is/are the last element of the pattern.
- If the name is a file name and contains another slash
- this does mean it cannot match. */
- return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL
- ? FNM_NOMATCH : 0);
- else
- {
- const char *endp;
-
- endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
-
- if (c == '[')
- {
- int flags2 = ((flags & FNM_FILE_NAME)
- ? flags : (flags & ~FNM_PERIOD));
-
- for (--p; n < endp; ++n)
- if (internal_fnmatch (p, n,
- (no_leading_period
- && (n == string
- || (n[-1] == '/'
- && (flags
- & FNM_FILE_NAME)))),
- flags2)
- == 0)
- return 0;
- }
- else if (c == '/' && (flags & FNM_FILE_NAME))
- {
- while (*n != '\0' && *n != '/')
- ++n;
- if (*n == '/'
- && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
- flags) == 0))
- return 0;
- }
- else
- {
- int flags2 = ((flags & FNM_FILE_NAME)
- ? flags : (flags & ~FNM_PERIOD));
-
- if (c == '\\' && !(flags & FNM_NOESCAPE))
- c = *p;
- c = FOLD (c);
- for (--p; n < endp; ++n)
- if (FOLD ((unsigned char) *n) == c
- && (internal_fnmatch (p, n,
- (no_leading_period
- && (n == string
- || (n[-1] == '/'
- && (flags
- & FNM_FILE_NAME)))),
- flags2) == 0))
- return 0;
- }
- }
-
- /* If we come here no match is possible with the wildcard. */
- return FNM_NOMATCH;
-
- case '[':
- {
- /* Nonzero if the sense of the character class is inverted. */
- static int posixly_correct;
- register int not;
- char cold;
-
- if (posixly_correct == 0)
- posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
-
- if (*n == '\0')
- return FNM_NOMATCH;
-
- if (*n == '.' && no_leading_period && (n == string
- || (n[-1] == '/'
- && (flags
- & FNM_FILE_NAME))))
- return FNM_NOMATCH;
-
- if (*n == '/' && (flags & FNM_FILE_NAME))
- /* `/' cannot be matched. */
- return FNM_NOMATCH;
-
- not = (*p == '!' || (posixly_correct < 0 && *p == '^'));
- if (not)
- ++p;
-
- c = *p++;
- for (;;)
- {
- unsigned char fn = FOLD ((unsigned char) *n);
-
- if (!(flags & FNM_NOESCAPE) && c == '\\')
- {
- if (*p == '\0')
- return FNM_NOMATCH;
- c = FOLD ((unsigned char) *p);
- ++p;
-
- if (c == fn)
- goto matched;
- }
- else if (c == '[' && *p == ':')
- {
- /* Leave room for the null. */
- char str[CHAR_CLASS_MAX_LENGTH + 1];
- size_t c1 = 0;
-# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
- wctype_t wt;
-# endif
- const char *startp = p;
-
- for (;;)
- {
- if (c1 > CHAR_CLASS_MAX_LENGTH)
- /* The name is too long and therefore the pattern
- is ill-formed. */
- return FNM_NOMATCH;
-
- c = *++p;
- if (c == ':' && p[1] == ']')
- {
- p += 2;
- break;
- }
- if (c < 'a' || c >= 'z')
- {
- /* This cannot possibly be a character class name.
- Match it as a normal range. */
- p = startp;
- c = '[';
- goto normal_bracket;
- }
- str[c1++] = c;
- }
- str[c1] = '\0';
-
-# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
- wt = IS_CHAR_CLASS (str);
- if (wt == 0)
- /* Invalid character class name. */
- return FNM_NOMATCH;
-
- if (__iswctype (__btowc ((unsigned char) *n), wt))
- goto matched;
-# else
- if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n))
- || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n))
- || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n))
- || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n))
- || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n))
- || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n))
- || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n))
- || (STREQ (str, "print") && ISPRINT ((unsigned char) *n))
- || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n))
- || (STREQ (str, "space") && ISSPACE ((unsigned char) *n))
- || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n))
- || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n)))
- goto matched;
-# endif
- }
- else if (c == '\0')
- /* [ (unterminated) loses. */
- return FNM_NOMATCH;
- else
- {
- normal_bracket:
- if (FOLD (c) == fn)
- goto matched;
-
- cold = c;
- c = *p++;
-
- if (c == '-' && *p != ']')
- {
- /* It is a range. */
- unsigned char cend = *p++;
- if (!(flags & FNM_NOESCAPE) && cend == '\\')
- cend = *p++;
- if (cend == '\0')
- return FNM_NOMATCH;
-
- if (cold <= fn && fn <= FOLD (cend))
- goto matched;
-
- c = *p++;
- }
- }
-
- if (c == ']')
- break;
- }
-
- if (!not)
- return FNM_NOMATCH;
- break;
-
- matched:
- /* Skip the rest of the [...] that already matched. */
- while (c != ']')
- {
- if (c == '\0')
- /* [... (unterminated) loses. */
- return FNM_NOMATCH;
-
- c = *p++;
- if (!(flags & FNM_NOESCAPE) && c == '\\')
- {
- if (*p == '\0')
- return FNM_NOMATCH;
- /* XXX 1003.2d11 is unclear if this is right. */
- ++p;
- }
- else if (c == '[' && *p == ':')
- {
- do
- if (*++p == '\0')
- return FNM_NOMATCH;
- while (*p != ':' || p[1] == ']');
- p += 2;
- c = *p;
- }
- }
- if (not)
- return FNM_NOMATCH;
- }
- break;
-
- default:
- if (c != FOLD ((unsigned char) *n))
- return FNM_NOMATCH;
- }
-
- ++n;
- }
-
- if (*n == '\0')
- return 0;
-
- if ((flags & FNM_LEADING_DIR) && *n == '/')
- /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
- return 0;
-
- return FNM_NOMATCH;
-
-# undef FOLD
-}
-
-
-int
-fnmatch (const char *pattern, const char *string, int flags)
-
-
-
-{
- return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
-}
-
-#endif /* _LIBC or not __GNU_LIBRARY__. */
diff --git a/compat/fnmatch/fnmatch.h b/compat/fnmatch/fnmatch.h
deleted file mode 100644
index cc3ec37940..0000000000
--- a/compat/fnmatch/fnmatch.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-#ifndef _FNMATCH_H
-#define _FNMATCH_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
-# if !defined __GLIBC__ || !defined __P
-# undef __P
-# define __P(protos) protos
-# endif
-#else /* Not C++ or ANSI C. */
-# undef __P
-# define __P(protos) ()
-/* We can get away without defining `const' here only because in this file
- it is used only inside the prototype for `fnmatch', which is elided in
- non-ANSI C where `const' is problematical. */
-#endif /* C++ or ANSI C. */
-
-#ifndef const
-# if (defined __STDC__ && __STDC__) || defined __cplusplus
-# define __const const
-# else
-# define __const
-# endif
-#endif
-
-/* We #undef these before defining them because some losing systems
- (HP-UX A.08.07 for example) define these in <unistd.h>. */
-#undef FNM_PATHNAME
-#undef FNM_NOESCAPE
-#undef FNM_PERIOD
-
-/* Bits set in the FLAGS argument to `fnmatch'. */
-#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
-#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */
-#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */
-
-#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE
-# define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */
-# define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */
-# define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
-#endif
-
-/* Value returned by `fnmatch' if STRING does not match PATTERN. */
-#define FNM_NOMATCH 1
-
-/* This value is returned if the implementation does not support
- `fnmatch'. Since this is not the case here it will never be
- returned but the conformance test suites still require the symbol
- to be defined. */
-#ifdef _XOPEN_SOURCE
-# define FNM_NOSYS (-1)
-#endif
-
-/* Match NAME against the filename pattern PATTERN,
- returning zero if it matches, FNM_NOMATCH if not. */
-extern int fnmatch __P ((__const char *__pattern, __const char *__name,
- int __flags));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* fnmatch.h */
diff --git a/compat/vcbuild/scripts/clink.pl b/compat/vcbuild/scripts/clink.pl
index 4374771df2..a87d0da512 100755
--- a/compat/vcbuild/scripts/clink.pl
+++ b/compat/vcbuild/scripts/clink.pl
@@ -33,6 +33,8 @@ while (@ARGV) {
push(@args, "libeay32.lib");
} elsif ("$arg" eq "-lssl") {
push(@args, "ssleay32.lib");
+ } elsif ("$arg" eq "-lcurl") {
+ push(@args, "libcurl.lib");
} elsif ("$arg" =~ /^-L/ && "$arg" ne "-LTCG") {
$arg =~ s/^-L/-LIBPATH:/;
push(@args, $arg);
diff --git a/config.c b/config.c
index 7f5b800ff3..6821cef00a 100644
--- a/config.c
+++ b/config.c
@@ -21,6 +21,7 @@ struct config_source {
} buf;
} u;
const char *name;
+ const char *path;
int die_on_error;
int linenr;
int eof;
@@ -101,12 +102,12 @@ static int handle_path_include(const char *path, struct config_include_data *inc
if (!is_absolute_path(path)) {
char *slash;
- if (!cf || !cf->name)
+ if (!cf || !cf->path)
return error("relative config includes must come from files");
- slash = find_last_dir_sep(cf->name);
+ slash = find_last_dir_sep(cf->path);
if (slash)
- strbuf_add(&buf, cf->name, slash - cf->name + 1);
+ strbuf_add(&buf, cf->path, slash - cf->path + 1);
strbuf_addstr(&buf, path);
path = buf.buf;
}
@@ -1021,24 +1022,35 @@ static int do_config_from(struct config_source *top, config_fn_t fn, void *data)
return ret;
}
-int git_config_from_file(config_fn_t fn, const char *filename, void *data)
+static int do_config_from_file(config_fn_t fn,
+ const char *name, const char *path, FILE *f, void *data)
{
- int ret;
- FILE *f = fopen(filename, "r");
+ struct config_source top;
- ret = -1;
- if (f) {
- struct config_source top;
+ top.u.file = f;
+ top.name = name;
+ top.path = path;
+ top.die_on_error = 1;
+ top.do_fgetc = config_file_fgetc;
+ top.do_ungetc = config_file_ungetc;
+ top.do_ftell = config_file_ftell;
- top.u.file = f;
- top.name = filename;
- top.die_on_error = 1;
- top.do_fgetc = config_file_fgetc;
- top.do_ungetc = config_file_ungetc;
- top.do_ftell = config_file_ftell;
+ return do_config_from(&top, fn, data);
+}
- ret = do_config_from(&top, fn, data);
+static int git_config_from_stdin(config_fn_t fn, void *data)
+{
+ return do_config_from_file(fn, "<stdin>", NULL, stdin, data);
+}
+
+int git_config_from_file(config_fn_t fn, const char *filename, void *data)
+{
+ int ret = -1;
+ FILE *f;
+ f = fopen(filename, "r");
+ if (f) {
+ ret = do_config_from_file(fn, filename, filename, f, data);
fclose(f);
}
return ret;
@@ -1053,6 +1065,7 @@ int git_config_from_buf(config_fn_t fn, const char *name, const char *buf,
top.u.buf.len = len;
top.u.buf.pos = 0;
top.name = name;
+ top.path = NULL;
top.die_on_error = 0;
top.do_fgetc = config_buf_fgetc;
top.do_ungetc = config_buf_ungetc;
@@ -1161,8 +1174,7 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config)
}
int git_config_with_options(config_fn_t fn, void *data,
- const char *filename,
- const char *blob_ref,
+ struct git_config_source *config_source,
int respect_includes)
{
char *repo_config = NULL;
@@ -1180,10 +1192,12 @@ int git_config_with_options(config_fn_t fn, void *data,
* If we have a specific filename, use it. Otherwise, follow the
* regular lookup sequence.
*/
- if (filename)
- return git_config_from_file(fn, filename, data);
- else if (blob_ref)
- return git_config_from_blob_ref(fn, blob_ref, data);
+ if (config_source && config_source->use_stdin)
+ return git_config_from_stdin(fn, data);
+ else if (config_source && config_source->file)
+ return git_config_from_file(fn, config_source->file, data);
+ else if (config_source && config_source->blob)
+ return git_config_from_blob_ref(fn, config_source->blob, data);
repo_config = git_pathdup("config");
ret = git_config_early(fn, data, repo_config);
@@ -1194,7 +1208,7 @@ int git_config_with_options(config_fn_t fn, void *data,
int git_config(config_fn_t fn, void *data)
{
- return git_config_with_options(fn, data, NULL, NULL, 1);
+ return git_config_with_options(fn, data, NULL, 1);
}
/*
diff --git a/config.mak.uname b/config.mak.uname
index 7d31fad241..cfc2a9323f 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -108,7 +108,6 @@ ifeq ($(uname_S),SunOS)
NO_MKDTEMP = YesPlease
NO_MKSTEMPS = YesPlease
NO_REGEX = YesPlease
- NO_FNMATCH_CASEFOLD = YesPlease
NO_MSGFMT_EXTENDED_OPTIONS = YesPlease
HAVE_DEV_TTY = YesPlease
ifeq ($(uname_R),5.6)
@@ -259,7 +258,6 @@ ifeq ($(uname_S),IRIX)
# issue, comment out the NO_MMAP statement.
NO_MMAP = YesPlease
NO_REGEX = YesPlease
- NO_FNMATCH_CASEFOLD = YesPlease
SNPRINTF_RETURNS_BOGUS = YesPlease
SHELL_PATH = /usr/gnu/bin/bash
NEEDS_LIBGEN = YesPlease
@@ -279,7 +277,6 @@ ifeq ($(uname_S),IRIX64)
# issue, comment out the NO_MMAP statement.
NO_MMAP = YesPlease
NO_REGEX = YesPlease
- NO_FNMATCH_CASEFOLD = YesPlease
SNPRINTF_RETURNS_BOGUS = YesPlease
SHELL_PATH = /usr/gnu/bin/bash
NEEDS_LIBGEN = YesPlease
@@ -296,7 +293,6 @@ ifeq ($(uname_S),HP-UX)
NO_UNSETENV = YesPlease
NO_HSTRERROR = YesPlease
NO_SYS_SELECT_H = YesPlease
- NO_FNMATCH_CASEFOLD = YesPlease
SNPRINTF_RETURNS_BOGUS = YesPlease
NO_NSEC = YesPlease
ifeq ($(uname_R),B.11.00)
@@ -327,7 +323,6 @@ ifeq ($(uname_S),Windows)
NO_UNSETENV = YesPlease
NO_STRCASESTR = YesPlease
NO_STRLCPY = YesPlease
- NO_FNMATCH = YesPlease
NO_MEMMEM = YesPlease
# NEEDS_LIBICONV = YesPlease
NO_ICONV = YesPlease
@@ -345,7 +340,6 @@ ifeq ($(uname_S),Windows)
UNRELIABLE_FSTAT = UnfortunatelyYes
OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
NO_REGEX = YesPlease
- NO_CURL = YesPlease
NO_GETTEXT = YesPlease
NO_PYTHON = YesPlease
BLK_SHA1 = YesPlease
@@ -389,13 +383,11 @@ ifeq ($(uname_S),Interix)
NO_INET_NTOP = YesPlease
NO_INET_PTON = YesPlease
NO_SOCKADDR_STORAGE = YesPlease
- NO_FNMATCH_CASEFOLD = YesPlease
endif
ifeq ($(uname_R),5.2)
NO_INET_NTOP = YesPlease
NO_INET_PTON = YesPlease
NO_SOCKADDR_STORAGE = YesPlease
- NO_FNMATCH_CASEFOLD = YesPlease
endif
endif
ifeq ($(uname_S),Minix)
@@ -440,7 +432,6 @@ ifeq ($(uname_S),NONSTOP_KERNEL)
NO_D_TYPE_IN_DIRENT = YesPlease
NO_HSTRERROR = YesPlease
NO_STRCASESTR = YesPlease
- NO_FNMATCH_CASEFOLD = YesPlease
NO_MEMMEM = YesPlease
NO_STRLCPY = YesPlease
NO_SETENV = YesPlease
@@ -484,7 +475,6 @@ ifneq (,$(findstring MINGW,$(uname_S)))
NO_UNSETENV = YesPlease
NO_STRCASESTR = YesPlease
NO_STRLCPY = YesPlease
- NO_FNMATCH = YesPlease
NO_MEMMEM = YesPlease
NEEDS_LIBICONV = YesPlease
NO_STRTOUMAX = YesPlease
@@ -538,7 +528,6 @@ ifeq ($(uname_S),QNX)
EXPAT_NEEDS_XMLPARSE_H = YesPlease
HAVE_STRINGS_H = YesPlease
NEEDS_SOCKET = YesPlease
- NO_FNMATCH_CASEFOLD = YesPlease
NO_GETPAGESIZE = YesPlease
NO_ICONV = YesPlease
NO_MEMMEM = YesPlease
diff --git a/configure.ac b/configure.ac
index 2f433939dc..b7112542b4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -890,7 +890,7 @@ GIT_CONF_SUBST([HAVE_STRINGS_H])
# and libcharset does
CHARSET_LIB=
AC_CHECK_LIB([iconv], [locale_charset],
- [],
+ [CHARSET_LIB=-liconv],
[AC_CHECK_LIB([charset], [locale_charset],
[CHARSET_LIB=-lcharset])])
GIT_CONF_SUBST([CHARSET_LIB])
@@ -901,34 +901,6 @@ GIT_CHECK_FUNC(strcasestr,
[NO_STRCASESTR=YesPlease])
GIT_CONF_SUBST([NO_STRCASESTR])
#
-# Define NO_FNMATCH if you don't have fnmatch
-GIT_CHECK_FUNC(fnmatch,
-[NO_FNMATCH=],
-[NO_FNMATCH=YesPlease])
-GIT_CONF_SUBST([NO_FNMATCH])
-#
-# Define NO_FNMATCH_CASEFOLD if your fnmatch function doesn't have the
-# FNM_CASEFOLD GNU extension.
-AC_CACHE_CHECK([whether the fnmatch function supports the FNMATCH_CASEFOLD GNU extension],
- [ac_cv_c_excellent_fnmatch], [
-AC_EGREP_CPP(yippeeyeswehaveit,
- AC_LANG_PROGRAM([
-#include <fnmatch.h>
-],
-[#ifdef FNM_CASEFOLD
-yippeeyeswehaveit
-#endif
-]),
- [ac_cv_c_excellent_fnmatch=yes],
- [ac_cv_c_excellent_fnmatch=no])
-])
-if test $ac_cv_c_excellent_fnmatch = yes; then
- NO_FNMATCH_CASEFOLD=
-else
- NO_FNMATCH_CASEFOLD=YesPlease
-fi
-GIT_CONF_SUBST([NO_FNMATCH_CASEFOLD])
-#
# Define NO_MEMMEM if you don't have memmem.
GIT_CHECK_FUNC(memmem,
[NO_MEMMEM=],
diff --git a/connect.c b/connect.c
index 4150412e2c..a983d061a9 100644
--- a/connect.c
+++ b/connect.c
@@ -727,7 +727,7 @@ struct child_process *git_connect(int fd[2], const char *url,
*arg++ = port;
}
*arg++ = ssh_host;
- } else {
+ } else {
/* remove repo-local variables from the environment */
conn->env = local_repo_env;
conn->use_shell = 1;
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 9525343fcd..87de809d23 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1221,14 +1221,20 @@ _git_difftool ()
__git_complete_revlist_file
}
+__git_fetch_recurse_submodules="yes on-demand no"
+
__git_fetch_options="
--quiet --verbose --append --upload-pack --force --keep --depth=
- --tags --no-tags --all --prune --dry-run
+ --tags --no-tags --all --prune --dry-run --recurse-submodules=
"
_git_fetch ()
{
case "$cur" in
+ --recurse-submodules=*)
+ __gitcomp "$__git_fetch_recurse_submodules" "" "${cur##--recurse-submodules=}"
+ return
+ ;;
--*)
__gitcomp "$__git_fetch_options"
return
@@ -1583,6 +1589,10 @@ _git_pull ()
__git_complete_strategy && return
case "$cur" in
+ --recurse-submodules=*)
+ __gitcomp "$__git_fetch_recurse_submodules" "" "${cur##--recurse-submodules=}"
+ return
+ ;;
--*)
__gitcomp "
--rebase --no-rebase
@@ -1595,6 +1605,8 @@ _git_pull ()
__git_complete_remote_or_refspec
}
+__git_push_recurse_submodules="check on-demand"
+
_git_push ()
{
case "$prev" in
@@ -1607,10 +1619,15 @@ _git_push ()
__gitcomp_nl "$(__git_remotes)" "" "${cur##--repo=}"
return
;;
+ --recurse-submodules=*)
+ __gitcomp "$__git_push_recurse_submodules" "" "${cur##--recurse-submodules=}"
+ return
+ ;;
--*)
__gitcomp "
--all --mirror --tags --dry-run --force --verbose
--receive-pack= --repo= --set-upstream
+ --recurse-submodules=
"
return
;;
diff --git a/contrib/contacts/git-contacts b/contrib/contacts/git-contacts
index 428cc1a9a1..dbe2abf277 100755
--- a/contrib/contacts/git-contacts
+++ b/contrib/contacts/git-contacts
@@ -96,8 +96,6 @@ sub scan_patches {
next unless $id;
if (m{^--- (?:a/(.+)|/dev/null)$}) {
$source = $1;
- } elsif (/^--- /) {
- die "Cannot parse hunk source: $_\n";
} elsif (/^@@ -(\d+)(?:,(\d+))?/ && $source) {
my $len = defined($2) ? $2 : 1;
push @{$sources->{$source}{$id}}, [$1, $len] if $len;
diff --git a/contrib/remote-helpers/git-remote-bzr b/contrib/remote-helpers/git-remote-bzr
index 332aba784b..5f4b2e3e16 100755
--- a/contrib/remote-helpers/git-remote-bzr
+++ b/contrib/remote-helpers/git-remote-bzr
@@ -684,7 +684,8 @@ def do_export(parser):
peer = bzrlib.branch.Branch.open(peers[name],
possible_transports=transports)
try:
- peer.bzrdir.push_branch(branch, revision_id=revid)
+ peer.bzrdir.push_branch(branch, revision_id=revid,
+ overwrite=force)
except bzrlib.errors.DivergedBranches:
print "error %s non-fast forward" % ref
continue
@@ -718,8 +719,32 @@ def do_capabilities(parser):
print "*import-marks %s" % path
print "*export-marks %s" % path
+ print "option"
print
+class InvalidOptionValue(Exception):
+ pass
+
+def get_bool_option(val):
+ if val == 'true':
+ return True
+ elif val == 'false':
+ return False
+ else:
+ raise InvalidOptionValue()
+
+def do_option(parser):
+ global force
+ opt, val = parser[1:3]
+ try:
+ if opt == 'force':
+ force = get_bool_option(val)
+ print 'ok'
+ else:
+ print 'unsupported'
+ except InvalidOptionValue:
+ print "error '%s' is not a valid value for option '%s'" % (val, opt)
+
def ref_is_valid(name):
return not True in [c in name for c in '~^: \\']
@@ -882,6 +907,7 @@ def main(args):
global is_tmp
global branches, peers
global transports
+ global force
marks = None
is_tmp = False
@@ -904,6 +930,7 @@ def main(args):
branches = {}
peers = {}
transports = []
+ force = False
if alias[5:] == url:
is_tmp = True
@@ -936,6 +963,8 @@ def main(args):
do_import(parser)
elif parser.check('export'):
do_export(parser)
+ elif parser.check('option'):
+ do_option(parser)
else:
die('unhandled command: %s' % line)
sys.stdout.flush()
diff --git a/contrib/remote-helpers/test-bzr.sh b/contrib/remote-helpers/test-bzr.sh
index 1e53ff9a58..4f379c2ab4 100755
--- a/contrib/remote-helpers/test-bzr.sh
+++ b/contrib/remote-helpers/test-bzr.sh
@@ -66,13 +66,33 @@ test_expect_success 'pushing' '
test_cmp expected actual
'
+test_expect_success 'forced pushing' '
+ (
+ cd gitrepo &&
+ echo three-new >content &&
+ git commit -a --amend -m three-new &&
+ git push -f
+ ) &&
+
+ (
+ cd bzrrepo &&
+ # the forced update overwrites the bzr branch but not the bzr
+ # working directory (it tries to merge instead)
+ bzr revert
+ ) &&
+
+ echo three-new >expected &&
+ cat bzrrepo/content >actual &&
+ test_cmp expected actual
+'
+
test_expect_success 'roundtrip' '
(
cd gitrepo &&
git pull &&
git log --format="%s" -1 origin/master >actual
) &&
- echo three >expected &&
+ echo three-new >expected &&
test_cmp expected actual &&
(cd gitrepo && git push && git pull) &&
diff --git a/contrib/remote-helpers/test-hg.sh b/contrib/remote-helpers/test-hg.sh
index 5d128a5da9..a933b1e30c 100755
--- a/contrib/remote-helpers/test-hg.sh
+++ b/contrib/remote-helpers/test-hg.sh
@@ -680,7 +680,7 @@ test_expect_success 'remote big push fetch first' '
)
'
-test_expect_failure 'remote big push force' '
+test_expect_success 'remote big push force' '
test_when_finished "rm -rf hgrepo gitrepo*" &&
setup_big_push
@@ -710,7 +710,7 @@ test_expect_failure 'remote big push force' '
check_bookmark hgrepo new_bmark six
'
-test_expect_failure 'remote big push dry-run' '
+test_expect_success 'remote big push dry-run' '
test_when_finished "rm -rf hgrepo gitrepo*" &&
setup_big_push
diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
index dc59a91031..db925ca769 100755
--- a/contrib/subtree/git-subtree.sh
+++ b/contrib/subtree/git-subtree.sh
@@ -46,6 +46,7 @@ ignore_joins=
annotate=
squash=
message=
+prefix=
debug()
{
diff --git a/date.c b/date.c
index 83b4166344..e1a2cee568 100644
--- a/date.c
+++ b/date.c
@@ -184,8 +184,10 @@ const char *show_date(unsigned long time, int tz, enum date_mode mode)
tz = local_tzoffset(time);
tm = time_to_tm(time, tz);
- if (!tm)
- return NULL;
+ if (!tm) {
+ tm = time_to_tm(0, 0);
+ tz = 0;
+ }
strbuf_reset(&timebuf);
if (mode == DATE_SHORT)
@@ -1113,3 +1115,20 @@ unsigned long approxidate_careful(const char *date, int *error_ret)
gettimeofday(&tv, NULL);
return approxidate_str(date, &tv, error_ret);
}
+
+int date_overflows(unsigned long t)
+{
+ time_t sys;
+
+ /* If we overflowed our unsigned long, that's bad... */
+ if (t == ULONG_MAX)
+ return 1;
+
+ /*
+ * ...but we also are going to feed the result to system
+ * functions that expect time_t, which is often "signed long".
+ * Make sure that we fit into time_t, as well.
+ */
+ sys = t;
+ return t != sys || (t < 1) != (sys < 1);
+}
diff --git a/diff-no-index.c b/diff-no-index.c
index 8e10bff30e..c554691df0 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -15,8 +15,9 @@
#include "log-tree.h"
#include "builtin.h"
#include "string-list.h"
+#include "dir.h"
-static int read_directory(const char *path, struct string_list *list)
+static int read_directory_contents(const char *path, struct string_list *list)
{
DIR *dir;
struct dirent *e;
@@ -25,7 +26,7 @@ static int read_directory(const char *path, struct string_list *list)
return error("Could not open directory %s", path);
while ((e = readdir(dir)))
- if (strcmp(".", e->d_name) && strcmp("..", e->d_name))
+ if (!is_dot_or_dotdot(e->d_name))
string_list_insert(list, e->d_name);
closedir(dir);
@@ -107,9 +108,9 @@ static int queue_diff(struct diff_options *o,
int i1, i2, ret = 0;
size_t len1 = 0, len2 = 0;
- if (name1 && read_directory(name1, &p1))
+ if (name1 && read_directory_contents(name1, &p1))
return -1;
- if (name2 && read_directory(name2, &p2)) {
+ if (name2 && read_directory_contents(name2, &p2)) {
string_list_clear(&p1, 0);
return -1;
}
diff --git a/diff.c b/diff.c
index 7c59bfe2d0..e343191bda 100644
--- a/diff.c
+++ b/diff.c
@@ -1361,11 +1361,7 @@ static struct diffstat_file *diffstat_add(struct diffstat_t *diffstat,
{
struct diffstat_file *x;
x = xcalloc(sizeof (*x), 1);
- if (diffstat->nr == diffstat->alloc) {
- diffstat->alloc = alloc_nr(diffstat->alloc);
- diffstat->files = xrealloc(diffstat->files,
- diffstat->alloc * sizeof(x));
- }
+ ALLOC_GROW(diffstat->files, diffstat->nr + 1, diffstat->alloc);
diffstat->files[diffstat->nr++] = x;
if (name_b) {
x->from_name = xstrdup(name_a);
@@ -2845,8 +2841,9 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
remove_tempfile_installed = 1;
}
- if (!one->sha1_valid ||
- reuse_worktree_file(name, one->sha1, 1)) {
+ if (!S_ISGITLINK(one->mode) &&
+ (!one->sha1_valid ||
+ reuse_worktree_file(name, one->sha1, 1))) {
struct stat st;
if (lstat(name, &st) < 0) {
if (errno == ENOENT)
@@ -3365,14 +3362,11 @@ static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *va
if (c != '-')
return 0;
arg++;
- eq = strchr(arg, '=');
- if (eq)
- len = eq - arg;
- else
- len = strlen(arg);
+ eq = strchrnul(arg, '=');
+ len = eq - arg;
if (!len || strncmp(arg, arg_long, len))
return 0;
- if (eq) {
+ if (*eq) {
int n;
char *end;
if (!isdigit(*++eq))
@@ -3957,11 +3951,7 @@ struct diff_queue_struct diff_queued_diff;
void diff_q(struct diff_queue_struct *queue, struct diff_filepair *dp)
{
- if (queue->alloc <= queue->nr) {
- queue->alloc = alloc_nr(queue->alloc);
- queue->queue = xrealloc(queue->queue,
- sizeof(dp) * queue->alloc);
- }
+ ALLOC_GROW(queue->queue, queue->nr + 1, queue->alloc);
queue->queue[queue->nr++] = dp;
}
diff --git a/diffcore-order.c b/diffcore-order.c
index 1bfcc39f90..97dd3d0095 100644
--- a/diffcore-order.c
+++ b/diffcore-order.c
@@ -67,7 +67,7 @@ static int match_order(const char *path)
strbuf_addstr(&p, path);
while (p.buf[0]) {
char *cp;
- if (!fnmatch(order[i], p.buf, 0))
+ if (!wildmatch(order[i], p.buf, 0, NULL))
return i;
cp = strrchr(p.buf, '/');
if (!cp)
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 9b4f068eb3..749a35d2c2 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -38,11 +38,7 @@ static struct diff_rename_dst *locate_rename_dst(struct diff_filespec *two,
if (!insert_ok)
return NULL;
/* insert to make it at "first" */
- if (rename_dst_alloc <= rename_dst_nr) {
- rename_dst_alloc = alloc_nr(rename_dst_alloc);
- rename_dst = xrealloc(rename_dst,
- rename_dst_alloc * sizeof(*rename_dst));
- }
+ ALLOC_GROW(rename_dst, rename_dst_nr + 1, rename_dst_alloc);
rename_dst_nr++;
if (first < rename_dst_nr)
memmove(rename_dst + first + 1, rename_dst + first,
@@ -82,11 +78,7 @@ static struct diff_rename_src *register_rename_src(struct diff_filepair *p)
}
/* insert to make it at "first" */
- if (rename_src_alloc <= rename_src_nr) {
- rename_src_alloc = alloc_nr(rename_src_alloc);
- rename_src = xrealloc(rename_src,
- rename_src_alloc * sizeof(*rename_src));
- }
+ ALLOC_GROW(rename_src, rename_src_nr + 1, rename_src_alloc);
rename_src_nr++;
if (first < rename_src_nr)
memmove(rename_src + first + 1, rename_src + first,
@@ -522,7 +514,7 @@ void diffcore_rename(struct diff_options *options)
if (options->show_rename_progress) {
progress = start_progress_delay(
- "Performing inexact rename detection",
+ _("Performing inexact rename detection"),
rename_dst_nr * rename_src_nr, 50, 1);
}
diff --git a/diffcore.h b/diffcore.h
index 92788ee4de..c876dac71a 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -46,7 +46,7 @@ struct diff_filespec {
unsigned is_stdin : 1;
unsigned has_more_entries : 1; /* only appear in combined diff */
/* data should be considered "binary"; -1 means "don't know yet" */
- int is_binary : 2;
+ signed int is_binary : 2;
struct userdiff_driver *driver;
};
diff --git a/dir.c b/dir.c
index 98bb50fbab..99f53033ba 100644
--- a/dir.c
+++ b/dir.c
@@ -49,7 +49,9 @@ int strncmp_icase(const char *a, const char *b, size_t count)
int fnmatch_icase(const char *pattern, const char *string, int flags)
{
- return fnmatch(pattern, string, flags | (ignore_case ? FNM_CASEFOLD : 0));
+ return wildmatch(pattern, string,
+ flags | (ignore_case ? WM_CASEFOLD : 0),
+ NULL);
}
inline int git_fnmatch(const struct pathspec_item *item,
@@ -58,7 +60,7 @@ inline int git_fnmatch(const struct pathspec_item *item,
{
if (prefix > 0) {
if (ps_strncmp(item, pattern, string, prefix))
- return FNM_NOMATCH;
+ return WM_NOMATCH;
pattern += prefix;
string += prefix;
}
@@ -76,8 +78,9 @@ inline int git_fnmatch(const struct pathspec_item *item,
NULL);
else
/* wildmatch has not learned no FNM_PATHNAME mode yet */
- return fnmatch(pattern, string,
- item->magic & PATHSPEC_ICASE ? FNM_CASEFOLD : 0);
+ return wildmatch(pattern, string,
+ item->magic & PATHSPEC_ICASE ? WM_CASEFOLD : 0,
+ NULL);
}
static int fnmatch_icase_mem(const char *pattern, int patternlen,
@@ -503,6 +506,25 @@ void clear_exclude_list(struct exclude_list *el)
el->filebuf = NULL;
}
+static void trim_trailing_spaces(char *buf)
+{
+ int i, last_space = -1, nr_spaces, len = strlen(buf);
+ for (i = 0; i < len; i++)
+ if (buf[i] == '\\')
+ i++;
+ else if (buf[i] == ' ') {
+ if (last_space == -1) {
+ last_space = i;
+ nr_spaces = 1;
+ } else
+ nr_spaces++;
+ } else
+ last_space = -1;
+
+ if (last_space != -1 && last_space + nr_spaces == len)
+ buf[last_space] = '\0';
+}
+
int add_excludes_from_file_to_list(const char *fname,
const char *base,
int baselen,
@@ -554,6 +576,7 @@ int add_excludes_from_file_to_list(const char *fname,
if (buf[i] == '\n') {
if (entry != buf + i && entry[0] != '#') {
buf[i - (i && buf[i-1] == '\r')] = 0;
+ trim_trailing_spaces(entry);
add_exclude(entry, base, baselen, el, lineno);
}
lineno++;
@@ -1341,10 +1364,7 @@ static struct path_simplify *create_simplify(const char **pathspec)
for (nr = 0 ; ; nr++) {
const char *match;
- if (nr >= alloc) {
- alloc = alloc_nr(alloc);
- simplify = xrealloc(simplify, alloc * sizeof(*simplify));
- }
+ ALLOC_GROW(simplify, nr + 1, alloc);
match = *pathspec++;
if (!match)
break;
diff --git a/entry.c b/entry.c
index 7b7aa8167a..77c6882624 100644
--- a/entry.c
+++ b/entry.c
@@ -44,33 +44,33 @@ static void create_directories(const char *path, int path_len,
free(buf);
}
-static void remove_subtree(const char *path)
+static void remove_subtree(struct strbuf *path)
{
- DIR *dir = opendir(path);
+ DIR *dir = opendir(path->buf);
struct dirent *de;
- char pathbuf[PATH_MAX];
- char *name;
+ int origlen = path->len;
if (!dir)
- die_errno("cannot opendir '%s'", path);
- strcpy(pathbuf, path);
- name = pathbuf + strlen(path);
- *name++ = '/';
+ die_errno("cannot opendir '%s'", path->buf);
while ((de = readdir(dir)) != NULL) {
struct stat st;
+
if (is_dot_or_dotdot(de->d_name))
continue;
- strcpy(name, de->d_name);
- if (lstat(pathbuf, &st))
- die_errno("cannot lstat '%s'", pathbuf);
+
+ strbuf_addch(path, '/');
+ strbuf_addstr(path, de->d_name);
+ if (lstat(path->buf, &st))
+ die_errno("cannot lstat '%s'", path->buf);
if (S_ISDIR(st.st_mode))
- remove_subtree(pathbuf);
- else if (unlink(pathbuf))
- die_errno("cannot unlink '%s'", pathbuf);
+ remove_subtree(path);
+ else if (unlink(path->buf))
+ die_errno("cannot unlink '%s'", path->buf);
+ strbuf_setlen(path, origlen);
}
closedir(dir);
- if (rmdir(path))
- die_errno("cannot rmdir '%s'", path);
+ if (rmdir(path->buf))
+ die_errno("cannot rmdir '%s'", path->buf);
}
static int create_file(const char *path, unsigned int mode)
@@ -245,27 +245,25 @@ static int check_path(const char *path, int len, struct stat *st, int skiplen)
int checkout_entry(struct cache_entry *ce,
const struct checkout *state, char *topath)
{
- static struct strbuf path_buf = STRBUF_INIT;
- char *path;
+ static struct strbuf path = STRBUF_INIT;
struct stat st;
- int len;
if (topath)
return write_entry(ce, topath, state, 1);
- strbuf_reset(&path_buf);
- strbuf_add(&path_buf, state->base_dir, state->base_dir_len);
- strbuf_add(&path_buf, ce->name, ce_namelen(ce));
- path = path_buf.buf;
- len = path_buf.len;
+ strbuf_reset(&path);
+ strbuf_add(&path, state->base_dir, state->base_dir_len);
+ strbuf_add(&path, ce->name, ce_namelen(ce));
- if (!check_path(path, len, &st, state->base_dir_len)) {
+ if (!check_path(path.buf, path.len, &st, state->base_dir_len)) {
unsigned changed = ce_match_stat(ce, &st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE);
if (!changed)
return 0;
if (!state->force) {
if (!state->quiet)
- fprintf(stderr, "%s already exists, no checkout\n", path);
+ fprintf(stderr,
+ "%s already exists, no checkout\n",
+ path.buf);
return -1;
}
@@ -280,12 +278,14 @@ int checkout_entry(struct cache_entry *ce,
if (S_ISGITLINK(ce->ce_mode))
return 0;
if (!state->force)
- return error("%s is a directory", path);
- remove_subtree(path);
- } else if (unlink(path))
- return error("unable to unlink old '%s' (%s)", path, strerror(errno));
+ return error("%s is a directory", path.buf);
+ remove_subtree(&path);
+ } else if (unlink(path.buf))
+ return error("unable to unlink old '%s' (%s)",
+ path.buf, strerror(errno));
} else if (state->not_new)
return 0;
- create_directories(path, len, state);
- return write_entry(ce, path, state, 0);
+
+ create_directories(path.buf, path.len, state);
+ return write_entry(ce, path.buf, state, 0);
}
diff --git a/environment.c b/environment.c
index 4a3437d8a6..c3c860603d 100644
--- a/environment.c
+++ b/environment.c
@@ -45,7 +45,7 @@ const char *editor_program;
const char *askpass_program;
const char *excludes_file;
enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;
-int read_replace_refs = 1; /* NEEDSWORK: rename to use_replace_refs */
+int check_replace_refs = 1;
enum eol core_eol = EOL_UNSET;
enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
@@ -147,7 +147,7 @@ static void setup_git_env(void)
if (!git_graft_file)
git_graft_file = git_pathdup("info/grafts");
if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
- read_replace_refs = 0;
+ check_replace_refs = 0;
namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));
namespace_len = strlen(namespace);
shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);
diff --git a/fast-import.c b/fast-import.c
index 4fd18a3574..fb4738d373 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1485,14 +1485,11 @@ static int tree_content_set(
unsigned int i, n;
struct tree_entry *e;
- slash1 = strchr(p, '/');
- if (slash1)
- n = slash1 - p;
- else
- n = strlen(p);
+ slash1 = strchrnul(p, '/');
+ n = slash1 - p;
if (!n)
die("Empty path component found in input");
- if (!slash1 && !S_ISDIR(mode) && subtree)
+ if (!*slash1 && !S_ISDIR(mode) && subtree)
die("Non-directories cannot have subtrees");
if (!root->tree)
@@ -1501,7 +1498,7 @@ static int tree_content_set(
for (i = 0; i < t->entry_count; i++) {
e = t->entries[i];
if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
- if (!slash1) {
+ if (!*slash1) {
if (!S_ISDIR(mode)
&& e->versions[1].mode == mode
&& !hashcmp(e->versions[1].sha1, sha1))
@@ -1552,7 +1549,7 @@ static int tree_content_set(
e->versions[0].mode = 0;
hashclr(e->versions[0].sha1);
t->entries[t->entry_count++] = e;
- if (slash1) {
+ if (*slash1) {
e->tree = new_tree_content(8);
e->versions[1].mode = S_IFDIR;
tree_content_set(e, slash1 + 1, sha1, mode, subtree);
@@ -1576,11 +1573,8 @@ static int tree_content_remove(
unsigned int i, n;
struct tree_entry *e;
- slash1 = strchr(p, '/');
- if (slash1)
- n = slash1 - p;
- else
- n = strlen(p);
+ slash1 = strchrnul(p, '/');
+ n = slash1 - p;
if (!root->tree)
load_tree(root);
@@ -1594,7 +1588,7 @@ static int tree_content_remove(
for (i = 0; i < t->entry_count; i++) {
e = t->entries[i];
if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
- if (slash1 && !S_ISDIR(e->versions[1].mode))
+ if (*slash1 && !S_ISDIR(e->versions[1].mode))
/*
* If p names a file in some subdirectory, and a
* file or symlink matching the name of the
@@ -1602,7 +1596,7 @@ static int tree_content_remove(
* exist and need not be deleted.
*/
return 1;
- if (!slash1 || !S_ISDIR(e->versions[1].mode))
+ if (!*slash1 || !S_ISDIR(e->versions[1].mode))
goto del_entry;
if (!e->tree)
load_tree(e);
@@ -1644,11 +1638,8 @@ static int tree_content_get(
unsigned int i, n;
struct tree_entry *e;
- slash1 = strchr(p, '/');
- if (slash1)
- n = slash1 - p;
- else
- n = strlen(p);
+ slash1 = strchrnul(p, '/');
+ n = slash1 - p;
if (!n && !allow_root)
die("Empty path component found in input");
@@ -1664,7 +1655,7 @@ static int tree_content_get(
for (i = 0; i < t->entry_count; i++) {
e = t->entries[i];
if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
- if (!slash1)
+ if (!*slash1)
goto found_entry;
if (!S_ISDIR(e->versions[1].mode))
return 0;
diff --git a/fetch-pack.c b/fetch-pack.c
index f061f1fe85..90d47da8a9 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -948,17 +948,6 @@ static void update_shallow(struct fetch_pack_args *args,
if (!si->shallow || !si->shallow->nr)
return;
- if (alternate_shallow_file) {
- /*
- * The temporary shallow file is only useful for
- * index-pack and unpack-objects because it may
- * contain more roots than we want. Delete it.
- */
- if (*alternate_shallow_file)
- unlink(alternate_shallow_file);
- free((char *)alternate_shallow_file);
- }
-
if (args->cloning) {
/*
* remote is shallow, but this is a clone, there are
diff --git a/fsck.c b/fsck.c
index 99c0497674..abed62bac7 100644
--- a/fsck.c
+++ b/fsck.c
@@ -165,18 +165,12 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
sha1 = tree_entry_extract(&desc, &name, &mode);
- if (is_null_sha1(sha1))
- has_null_sha1 = 1;
- if (strchr(name, '/'))
- has_full_path = 1;
- if (!*name)
- has_empty_name = 1;
- if (!strcmp(name, "."))
- has_dot = 1;
- if (!strcmp(name, ".."))
- has_dotdot = 1;
- if (!strcmp(name, ".git"))
- has_dotgit = 1;
+ has_null_sha1 |= is_null_sha1(sha1);
+ has_full_path |= !!strchr(name, '/');
+ has_empty_name |= !*name;
+ has_dot |= !strcmp(name, ".");
+ has_dotdot |= !strcmp(name, "..");
+ has_dotgit |= !strcmp(name, ".git");
has_zero_pad |= *(char *)desc.buffer == '0';
update_tree_entry(&desc);
@@ -243,8 +237,10 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
return retval;
}
-static int fsck_ident(char **ident, struct object *obj, fsck_error error_func)
+static int fsck_ident(const char **ident, struct object *obj, fsck_error error_func)
{
+ char *end;
+
if (**ident == '<')
return error_func(obj, FSCK_ERROR, "invalid author/committer line - missing space before email");
*ident += strcspn(*ident, "<>\n");
@@ -264,10 +260,11 @@ static int fsck_ident(char **ident, struct object *obj, fsck_error error_func)
(*ident)++;
if (**ident == '0' && (*ident)[1] != ' ')
return error_func(obj, FSCK_ERROR, "invalid author/committer line - zero-padded date");
- *ident += strspn(*ident, "0123456789");
- if (**ident != ' ')
+ if (date_overflows(strtoul(*ident, &end, 10)))
+ return error_func(obj, FSCK_ERROR, "invalid author/committer line - date causes integer overflow");
+ if (end == *ident || *end != ' ')
return error_func(obj, FSCK_ERROR, "invalid author/committer line - bad date");
- (*ident)++;
+ *ident = end + 1;
if ((**ident != '+' && **ident != '-') ||
!isdigit((*ident)[1]) ||
!isdigit((*ident)[2]) ||
@@ -281,24 +278,23 @@ static int fsck_ident(char **ident, struct object *obj, fsck_error error_func)
static int fsck_commit(struct commit *commit, fsck_error error_func)
{
- char *buffer = commit->buffer;
+ const char *buffer = commit->buffer, *tmp;
unsigned char tree_sha1[20], sha1[20];
struct commit_graft *graft;
int parents = 0;
int err;
- if (commit->date == ULONG_MAX)
- return error_func(&commit->object, FSCK_ERROR, "invalid author/committer line");
-
- if (memcmp(buffer, "tree ", 5))
+ buffer = skip_prefix(buffer, "tree ");
+ if (!buffer)
return error_func(&commit->object, FSCK_ERROR, "invalid format - expected 'tree' line");
- if (get_sha1_hex(buffer+5, tree_sha1) || buffer[45] != '\n')
+ if (get_sha1_hex(buffer, tree_sha1) || buffer[40] != '\n')
return error_func(&commit->object, FSCK_ERROR, "invalid 'tree' line format - bad sha1");
- buffer += 46;
- while (!memcmp(buffer, "parent ", 7)) {
- if (get_sha1_hex(buffer+7, sha1) || buffer[47] != '\n')
+ buffer += 41;
+ while ((tmp = skip_prefix(buffer, "parent "))) {
+ buffer = tmp;
+ if (get_sha1_hex(buffer, sha1) || buffer[40] != '\n')
return error_func(&commit->object, FSCK_ERROR, "invalid 'parent' line format - bad sha1");
- buffer += 48;
+ buffer += 41;
parents++;
}
graft = lookup_commit_graft(commit->object.sha1);
@@ -322,15 +318,15 @@ static int fsck_commit(struct commit *commit, fsck_error error_func)
if (p || parents)
return error_func(&commit->object, FSCK_ERROR, "parent objects missing");
}
- if (memcmp(buffer, "author ", 7))
+ buffer = skip_prefix(buffer, "author ");
+ if (!buffer)
return error_func(&commit->object, FSCK_ERROR, "invalid format - expected 'author' line");
- buffer += 7;
err = fsck_ident(&buffer, &commit->object, error_func);
if (err)
return err;
- if (memcmp(buffer, "committer ", strlen("committer ")))
+ buffer = skip_prefix(buffer, "committer ");
+ if (!buffer)
return error_func(&commit->object, FSCK_ERROR, "invalid format - expected 'committer' line");
- buffer += strlen("committer ");
err = fsck_ident(&buffer, &commit->object, error_func);
if (err)
return err;
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 24bb1ab992..d3bca12611 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -58,6 +58,9 @@ if ($repo->config_bool("interactive.singlekey")) {
Term::ReadKey->import;
$use_readkey = 1;
};
+ if (!$use_readkey) {
+ print STDERR "missing Term::ReadKey, disabling interactive.singlekey\n";
+ }
eval {
require Term::Cap;
my $termcap = Term::Cap->Tgetent;
diff --git a/git-bisect.sh b/git-bisect.sh
index 73b4c14d4f..af4d04c3be 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -365,7 +365,7 @@ bisect_reset() {
}
case "$#" in
0) branch=$(cat "$GIT_DIR/BISECT_START") ;;
- 1) git rev-parse --quiet --verify "$1^{commit}" > /dev/null || {
+ 1) git rev-parse --quiet --verify "$1^{commit}" >/dev/null || {
invalid="$1"
die "$(eval_gettext "'\$invalid' is not a valid commit")"
}
@@ -458,13 +458,13 @@ exit code \$res from '\$command' is < 0 or >= 128" >&2
fi
# We have to use a subshell because "bisect_state" can exit.
- ( bisect_state $state > "$GIT_DIR/BISECT_RUN" )
+ ( bisect_state $state >"$GIT_DIR/BISECT_RUN" )
res=$?
cat "$GIT_DIR/BISECT_RUN"
if sane_grep "first bad commit could be any of" "$GIT_DIR/BISECT_RUN" \
- > /dev/null
+ >/dev/null
then
gettextln "bisect run cannot continue any more" >&2
exit $res
@@ -477,7 +477,7 @@ exit code \$res from '\$command' is < 0 or >= 128" >&2
exit $res
fi
- if sane_grep "is the first bad commit" "$GIT_DIR/BISECT_RUN" > /dev/null
+ if sane_grep "is the first bad commit" "$GIT_DIR/BISECT_RUN" >/dev/null
then
gettextln "bisect run success"
exit 0;
diff --git a/git-compat-util.h b/git-compat-util.h
index 082eb0d1b7..892032bc79 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -116,9 +116,6 @@
#include <sys/time.h>
#include <time.h>
#include <signal.h>
-#ifndef USE_WILDMATCH
-#include <fnmatch.h>
-#endif
#include <assert.h>
#include <regex.h>
#include <utime.h>
@@ -304,16 +301,7 @@ extern char *gitbasename(char *);
#include "compat/bswap.h"
-#ifdef USE_WILDMATCH
#include "wildmatch.h"
-#define FNM_PATHNAME WM_PATHNAME
-#define FNM_CASEFOLD WM_CASEFOLD
-#define FNM_NOMATCH WM_NOMATCH
-static inline int fnmatch(const char *pattern, const char *string, int flags)
-{
- return wildmatch(pattern, string, flags, NULL);
-}
-#endif
/* General helper functions */
extern void vreportf(const char *prefix, const char *err, va_list params);
@@ -355,8 +343,11 @@ extern int ends_with(const char *str, const char *suffix);
static inline const char *skip_prefix(const char *str, const char *prefix)
{
- size_t len = strlen(prefix);
- return strncmp(str, prefix, len) ? NULL : str + len;
+ do {
+ if (!*prefix)
+ return str;
+ } while (*str++ == *prefix++);
+ return NULL;
}
#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
diff --git a/git-difftool.perl b/git-difftool.perl
index e57d3d1295..18ca61e8d0 100755
--- a/git-difftool.perl
+++ b/git-difftool.perl
@@ -39,24 +39,10 @@ USAGE
sub find_worktree
{
- my ($repo) = @_;
-
# Git->repository->wc_path() does not honor changes to the working
# tree location made by $ENV{GIT_WORK_TREE} or the 'core.worktree'
# config variable.
- my $worktree;
- my $env_worktree = $ENV{GIT_WORK_TREE};
- my $core_worktree = Git::config('core.worktree');
-
- if (defined($env_worktree) and (length($env_worktree) > 0)) {
- $worktree = $env_worktree;
- } elsif (defined($core_worktree) and (length($core_worktree) > 0)) {
- $worktree = $core_worktree;
- } else {
- $worktree = $repo->wc_path();
- }
-
- return $worktree;
+ return Git::command_oneline('rev-parse', '--show-toplevel');
}
sub print_tool_help
@@ -418,7 +404,7 @@ sub dir_diff
my $rc;
my $error = 0;
my $repo = Git->repository();
- my $workdir = find_worktree($repo);
+ my $workdir = find_worktree();
my ($a, $b, $tmpdir, @worktree) =
setup_dir_diff($repo, $workdir, $symlinks);
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index a1adae8313..1c41cbd66c 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -749,7 +749,7 @@ rearrange_squash () {
;;
esac
done
- echo "$sha1 $action $prefix $rest"
+ printf '%s %s %s %s\n' "$sha1" "$action" "$prefix" "$rest"
# if it's a single word, try to resolve to a full sha1 and
# emit a second copy. This allows us to match on both message
# and on sha1 prefix
diff --git a/git-rebase.sh b/git-rebase.sh
index 5f6732bf3d..2c75e9fa0f 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -453,6 +453,10 @@ then
test "$fork_point" = auto && fork_point=t
;;
*) upstream_name="$1"
+ if test "$upstream_name" = "-"
+ then
+ upstream_name="@{-1}"
+ fi
shift
;;
esac
diff --git a/git-remote-testgit.sh b/git-remote-testgit.sh
index 6d2f282d32..1c006a0518 100755
--- a/git-remote-testgit.sh
+++ b/git-remote-testgit.sh
@@ -15,6 +15,8 @@ test -z "$refspec" && prefix="refs"
export GIT_DIR="$url/.git"
+force=
+
mkdir -p "$dir"
if test -z "$GIT_REMOTE_TESTGIT_NO_MARKS"
@@ -39,6 +41,7 @@ do
fi
test -n "$GIT_REMOTE_TESTGIT_SIGNED_TAGS" && echo "signed-tags"
test -n "$GIT_REMOTE_TESTGIT_NO_PRIVATE_UPDATE" && echo "no-private-update"
+ echo 'option'
echo
;;
list)
@@ -93,6 +96,7 @@ do
before=$(git for-each-ref --format=' %(refname) %(objectname) ')
git fast-import \
+ ${force:+--force} \
${testgitmarks:+"--import-marks=$testgitmarks"} \
${testgitmarks:+"--export-marks=$testgitmarks"} \
--quiet
@@ -115,6 +119,20 @@ do
echo
;;
+ option\ *)
+ read cmd opt val <<-EOF
+ $line
+ EOF
+ case $opt in
+ force)
+ test $val = "true" && force="true" || force=
+ echo "ok"
+ ;;
+ *)
+ echo "unsupported"
+ ;;
+ esac
+ ;;
'')
exit
;;
diff --git a/git-request-pull.sh b/git-request-pull.sh
index cf4f1505a5..5c15997523 100755
--- a/git-request-pull.sh
+++ b/git-request-pull.sh
@@ -36,20 +36,7 @@ do
shift
done
-base=$1 url=$2 head=${3-HEAD} status=0 branch_name=
-
-headref=$(git symbolic-ref -q "$head")
-if git show-ref -q --verify "$headref"
-then
- branch_name=${headref#refs/heads/}
- if test "z$branch_name" = "z$headref" ||
- ! git config "branch.$branch_name.description" >/dev/null
- then
- branch_name=
- fi
-fi
-
-tag_name=$(git describe --exact "$head^0" 2>/dev/null)
+base=$1 url=$2 status=0
test -n "$base" && test -n "$url" || usage
@@ -59,55 +46,78 @@ then
die "fatal: Not a valid revision: $base"
fi
+#
+# $3 must be a symbolic ref, a unique ref, or
+# a SHA object expression. It can also be of
+# the format 'local-name:remote-name'.
+#
+local=${3%:*}
+local=${local:-HEAD}
+remote=${3#*:}
+pretty_remote=${remote#refs/}
+pretty_remote=${pretty_remote#heads/}
+head=$(git symbolic-ref -q "$local")
+head=${head:-$(git show-ref --heads --tags "$local" | cut -d' ' -f2)}
+head=${head:-$(git rev-parse --quiet --verify "$local")}
+
+# None of the above? Bad.
+test -z "$head" && die "fatal: Not a valid revision: $local"
+
+# This also verifies that the resulting head is unique:
+# "git show-ref" could have shown multiple matching refs..
headrev=$(git rev-parse --verify --quiet "$head"^0)
-if test -z "$headrev"
+test -z "$headrev" && die "fatal: Ambiguous revision: $local"
+
+# Was it a branch with a description?
+branch_name=${head#refs/heads/}
+if test "z$branch_name" = "z$headref" ||
+ ! git config "branch.$branch_name.description" >/dev/null
then
- die "fatal: Not a valid revision: $head"
+ branch_name=
fi
merge_base=$(git merge-base $baserev $headrev) ||
die "fatal: No commits in common between $base and $head"
-# $head is the token given from the command line, and $tag_name, if
-# exists, is the tag we are going to show the commit information for.
-# If that tag exists at the remote and it points at the commit, use it.
-# Otherwise, if a branch with the same name as $head exists at the remote
-# and their values match, use that instead.
+# $head is the refname from the command line.
+# If a ref with the same name as $head exists at the remote
+# and their values match, use that.
#
# Otherwise find a random ref that matches $headrev.
find_matching_ref='
- sub abbr {
- my $ref = shift;
- if ($ref =~ s|^refs/heads/|| || $ref =~ s|^refs/tags/|tags/|) {
- return $ref;
- } else {
- return $ref;
- }
- }
+ my ($head,$headrev) = (@ARGV);
+ my ($found);
- my ($tagged, $branch, $found);
while (<STDIN>) {
- my ($sha1, $ref, $deref) = /^(\S+)\s+(\S+?)(\^\{\})?$/;
- next unless ($sha1 eq $ARGV[1]);
- $found = abbr($ref);
- if ($deref && $ref eq "tags/$ARGV[2]") {
- $tagged = $found;
- last;
+ chomp;
+ my ($sha1, $ref, $deref) = /^(\S+)\s+([^^]+)(\S*)$/;
+ my ($pattern);
+ next unless ($sha1 eq $headrev);
+
+ $pattern="/$head\$";
+ if ($ref eq $head) {
+ $found = $ref;
+ }
+ if ($ref =~ /$pattern/) {
+ $found = $ref;
}
- if ($ref =~ m|/\Q$ARGV[0]\E$|) {
- $exact = $found;
+ if ($sha1 eq $head) {
+ $found = $sha1;
}
}
- if ($tagged) {
- print "$tagged\n";
- } elsif ($exact) {
- print "$exact\n";
- } elsif ($found) {
+ if ($found) {
print "$found\n";
}
'
-ref=$(git ls-remote "$url" | @@PERL@@ -e "$find_matching_ref" "$head" "$headrev" "$tag_name")
+ref=$(git ls-remote "$url" | @@PERL@@ -e "$find_matching_ref" "${remote:-HEAD}" "$headrev")
+
+if test -z "$ref"
+then
+ echo "warn: No match for commit $headrev found at $url" >&2
+ echo "warn: Are you sure you pushed '${remote:-HEAD}' there?" >&2
+ status=1
+fi
url=$(git ls-remote --get-url "$url")
@@ -117,7 +127,7 @@ git show -s --format='The following changes since commit %H:
are available in the git repository at:
' $merge_base &&
-echo " $url${ref+ $ref}" &&
+echo " $url $pretty_remote" &&
git show -s --format='
for you to fetch changes up to %H:
@@ -125,39 +135,23 @@ for you to fetch changes up to %H:
----------------------------------------------------------------' $headrev &&
-if test -n "$branch_name"
+if test $(git cat-file -t "$head") = tag
then
- echo "(from the branch description for $branch_name local branch)"
- echo
- git config "branch.$branch_name.description"
-fi &&
-
-if test -n "$tag_name"
-then
- if test -z "$ref" || test "$ref" != "tags/$tag_name"
- then
- echo >&2 "warn: You locally have $tag_name but it does not (yet)"
- echo >&2 "warn: appear to be at $url"
- echo >&2 "warn: Do you want to push it there, perhaps?"
- fi
- git cat-file tag "$tag_name" |
+ git cat-file tag "$head" |
sed -n -e '1,/^$/d' -e '/^-----BEGIN PGP /q' -e p
echo
+ echo "----------------------------------------------------------------"
fi &&
-if test -n "$branch_name" || test -n "$tag_name"
+if test -n "$branch_name"
then
+ echo "(from the branch description for $branch_name local branch)"
+ echo
+ git config "branch.$branch_name.description"
echo "----------------------------------------------------------------"
fi &&
git shortlog ^$baserev $headrev &&
git diff -M --stat --summary $patch $merge_base..$headrev || status=1
-if test -z "$ref"
-then
- echo "warn: No branch of $url is at:" >&2
- git show -s --format='warn: %h: %s' $headrev >&2
- echo "warn: Are you sure you pushed '$head' there?" >&2
- status=1
-fi
exit $status
diff --git a/git-stash.sh b/git-stash.sh
index f0a94abf14..4798bcf0e5 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -512,8 +512,14 @@ apply_stash () {
pop_stash() {
assert_stash_ref "$@"
- apply_stash "$@" &&
- drop_stash "$@"
+ if apply_stash "$@"
+ then
+ drop_stash "$@"
+ else
+ status=$?
+ say "The stash is kept in case you need it again."
+ exit $status
+ fi
}
drop_stash () {
diff --git a/git-submodule.sh b/git-submodule.sh
index a33f68d27c..6135cfa912 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -9,7 +9,7 @@ USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <re
or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
or: $dashless [--quiet] init [--] [<path>...]
or: $dashless [--quiet] deinit [-f|--force] [--] <path>...
- or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
+ or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--reference <repository>] [--recursive] [--] [<path>...]
or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
or: $dashless [--quiet] foreach [--recursive] <command>
or: $dashless [--quiet] sync [--recursive] [--] [<path>...]"
diff --git a/git.c b/git.c
index 7cf2953eff..9efd1a3ec1 100644
--- a/git.c
+++ b/git.c
@@ -78,7 +78,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
if (envchanged)
*envchanged = 1;
} else if (!strcmp(cmd, "--no-replace-objects")) {
- read_replace_refs = 0;
+ check_replace_refs = 0;
setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
if (envchanged)
*envchanged = 1;
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 3bc0f0b5ca..79057b7d0e 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -7094,7 +7094,7 @@ sub git_blob {
git_print_page_path($file_name, "blob", $hash_base);
print "<div class=\"page_body\">\n";
if ($mimetype =~ m!^image/!) {
- print qq!<img type="!.esc_attr($mimetype).qq!"!;
+ print qq!<img class="blob" type="!.esc_attr($mimetype).qq!"!;
if ($file_name) {
print qq! alt="!.esc_attr($file_name).qq!" title="!.esc_attr($file_name).qq!"!;
}
diff --git a/gitweb/static/gitweb.css b/gitweb/static/gitweb.css
index 3b4d833823..3212601032 100644
--- a/gitweb/static/gitweb.css
+++ b/gitweb/static/gitweb.css
@@ -32,6 +32,11 @@ img.avatar {
vertical-align: middle;
}
+img.blob {
+ max-height: 100%;
+ max-width: 100%;
+}
+
a.list img.avatar {
border-style: none;
}
diff --git a/grep.c b/grep.c
index c668034739..4aef0a69d0 100644
--- a/grep.c
+++ b/grep.c
@@ -1562,8 +1562,11 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
*/
if (opt->count && count) {
char buf[32];
- output_color(opt, gs->name, strlen(gs->name), opt->color_filename);
- output_sep(opt, ':');
+ if (opt->pathname) {
+ output_color(opt, gs->name, strlen(gs->name),
+ opt->color_filename);
+ output_sep(opt, ':');
+ }
snprintf(buf, sizeof(buf), "%u\n", count);
opt->output(opt, buf, strlen(buf));
return 1;
@@ -1650,7 +1653,7 @@ void grep_source_init(struct grep_source *gs, enum grep_source_type type,
break;
case GREP_SOURCE_SHA1:
gs->identifier = xmalloc(20);
- memcpy(gs->identifier, identifier, 20);
+ hashcpy(gs->identifier, identifier);
break;
case GREP_SOURCE_BUF:
gs->identifier = NULL;
diff --git a/help.c b/help.c
index df7d16d7ce..b266b09320 100644
--- a/help.c
+++ b/help.c
@@ -78,8 +78,7 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
cmds->cnt = cj;
}
-static void pretty_print_string_list(struct cmdnames *cmds,
- unsigned int colopts)
+static void pretty_print_cmdnames(struct cmdnames *cmds, unsigned int colopts)
{
struct string_list list = STRING_LIST_INIT_NODUP;
struct column_options copts;
@@ -209,14 +208,14 @@ void list_commands(unsigned int colopts,
const char *exec_path = git_exec_path();
printf_ln(_("available git commands in '%s'"), exec_path);
putchar('\n');
- pretty_print_string_list(main_cmds, colopts);
+ pretty_print_cmdnames(main_cmds, colopts);
putchar('\n');
}
if (other_cmds->cnt) {
printf_ln(_("git commands available from elsewhere on your $PATH"));
putchar('\n');
- pretty_print_string_list(other_cmds, colopts);
+ pretty_print_cmdnames(other_cmds, colopts);
putchar('\n');
}
}
diff --git a/http.c b/http.c
index 70eaa26e88..94e1afdee7 100644
--- a/http.c
+++ b/http.c
@@ -880,6 +880,20 @@ int handle_curl_result(struct slot_results *results)
}
}
+int run_one_slot(struct active_request_slot *slot,
+ struct slot_results *results)
+{
+ slot->results = results;
+ if (!start_active_slot(slot)) {
+ snprintf(curl_errorstr, sizeof(curl_errorstr),
+ "failed to start HTTP request");
+ return HTTP_START_FAILED;
+ }
+
+ run_active_slot(slot);
+ return handle_curl_result(results);
+}
+
static CURLcode curlinfo_strbuf(CURL *curl, CURLINFO info, struct strbuf *buf)
{
char *ptr;
@@ -907,7 +921,6 @@ static int http_request(const char *url,
int ret;
slot = get_active_slot();
- slot->results = &results;
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
if (result == NULL) {
@@ -942,14 +955,7 @@ static int http_request(const char *url,
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "gzip");
- if (start_active_slot(slot)) {
- run_active_slot(slot);
- ret = handle_curl_result(&results);
- } else {
- snprintf(curl_errorstr, sizeof(curl_errorstr),
- "failed to start HTTP request");
- ret = HTTP_START_FAILED;
- }
+ ret = run_one_slot(slot, &results);
if (options && options->content_type)
curlinfo_strbuf(slot->curl, CURLINFO_CONTENT_TYPE,
@@ -1384,7 +1390,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
unsigned char *sha1)
{
char *hex = sha1_to_hex(sha1);
- char *filename;
+ const char *filename;
char prevfile[PATH_MAX];
int prevlocal;
char prev_buf[PREV_BUF_SIZE];
diff --git a/http.h b/http.h
index cd37d5881c..a82888445e 100644
--- a/http.h
+++ b/http.h
@@ -90,6 +90,15 @@ extern void finish_active_slot(struct active_request_slot *slot);
extern void finish_all_active_slots(void);
extern int handle_curl_result(struct slot_results *results);
+/*
+ * This will run one slot to completion in a blocking manner, similar to how
+ * curl_easy_perform would work (but we don't want to use that, because
+ * we do not want to intermingle calls to curl_multi and curl_easy).
+ *
+ */
+int run_one_slot(struct active_request_slot *slot,
+ struct slot_results *results);
+
#ifdef USE_CURL_MULTI
extern void fill_active_slots(void);
extern void add_fill_function(void *data, int (*fill)(void *));
diff --git a/log-tree.c b/log-tree.c
index 08970bf46e..5ce217d5eb 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -100,7 +100,7 @@ static int add_ref_decoration(const char *refname, const unsigned char *sha1, in
if (starts_with(refname, "refs/replace/")) {
unsigned char original_sha1[20];
- if (!read_replace_refs)
+ if (!check_replace_refs)
return 0;
if (get_sha1_hex(refname + 13, original_sha1)) {
warning("invalid replace ref %s", refname);
diff --git a/match-trees.c b/match-trees.c
index 7873cdec58..e80b4af354 100644
--- a/match-trees.c
+++ b/match-trees.c
@@ -182,13 +182,10 @@ static int splice_tree(const unsigned char *hash1,
enum object_type type;
int status;
- subpath = strchr(prefix, '/');
- if (!subpath)
- toplen = strlen(prefix);
- else {
- toplen = subpath - prefix;
+ subpath = strchrnul(prefix, '/');
+ toplen = subpath - prefix;
+ if (*subpath)
subpath++;
- }
buf = read_sha1_file(hash1, &type, &sz);
if (!buf)
@@ -215,7 +212,7 @@ static int splice_tree(const unsigned char *hash1,
if (!rewrite_here)
die("entry %.*s not found in tree %s",
toplen, prefix, sha1_to_hex(hash1));
- if (subpath) {
+ if (*subpath) {
status = splice_tree(rewrite_here, subpath, hash2, subtree);
if (status)
return status;
diff --git a/notes-utils.c b/notes-utils.c
index 2975dcd581..4aa7023903 100644
--- a/notes-utils.c
+++ b/notes-utils.c
@@ -75,7 +75,7 @@ static int notes_rewrite_config(const char *k, const char *v, void *cb)
return 0;
} else if (!c->mode_from_env && !strcmp(k, "notes.rewritemode")) {
if (!v)
- config_error_nonbool(k);
+ return config_error_nonbool(k);
c->combine = parse_combine_notes_fn(v);
if (!c->combine) {
error(_("Bad notes.rewriteMode value: '%s'"), v);
diff --git a/object.c b/object.c
index 584f7acb36..57a0890a87 100644
--- a/object.c
+++ b/object.c
@@ -43,14 +43,32 @@ int type_from_string(const char *str)
die("invalid object type \"%s\"", str);
}
+/*
+ * Return a numerical hash value between 0 and n-1 for the object with
+ * the specified sha1. n must be a power of 2. Please note that the
+ * return value is *not* consistent across computer architectures.
+ */
static unsigned int hash_obj(const unsigned char *sha1, unsigned int n)
{
unsigned int hash;
+
+ /*
+ * Since the sha1 is essentially random, we just take the
+ * required number of bits directly from the first
+ * sizeof(unsigned int) bytes of sha1. First we have to copy
+ * the bytes into a properly aligned integer. If we cared
+ * about getting consistent results across architectures, we
+ * would have to call ntohl() here, too.
+ */
memcpy(&hash, sha1, sizeof(unsigned int));
- /* Assumes power-of-2 hash sizes in grow_object_hash */
return hash & (n - 1);
}
+/*
+ * Insert obj into the hash table hash, which has length size (which
+ * must be a power of 2). On collisions, simply overflow to the next
+ * empty bucket.
+ */
static void insert_obj_hash(struct object *obj, struct object **hash, unsigned int size)
{
unsigned int j = hash_obj(obj->sha1, size);
@@ -63,6 +81,10 @@ static void insert_obj_hash(struct object *obj, struct object **hash, unsigned i
hash[j] = obj;
}
+/*
+ * Look up the record for the given sha1 in the hash map stored in
+ * obj_hash. Return NULL if it was not found.
+ */
struct object *lookup_object(const unsigned char *sha1)
{
unsigned int i, first;
@@ -92,6 +114,11 @@ struct object *lookup_object(const unsigned char *sha1)
return obj;
}
+/*
+ * Increase the size of the hash map stored in obj_hash to the next
+ * power of 2 (but at least 32). Copy the existing values to the new
+ * hash map.
+ */
static void grow_object_hash(void)
{
int i;
diff --git a/object.h b/object.h
index dc5df8ce1d..732bf4d7e7 100644
--- a/object.h
+++ b/object.h
@@ -42,7 +42,14 @@ struct object {
extern const char *typename(unsigned int type);
extern int type_from_string(const char *str);
+/*
+ * Return the current number of buckets in the object hashmap.
+ */
extern unsigned int get_max_object_index(void);
+
+/*
+ * Return the object from the specified bucket in the object hashmap.
+ */
extern struct object *get_indexed_object(unsigned int);
/*
diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c
index 1218befaf2..5f1791a59c 100644
--- a/pack-bitmap-write.c
+++ b/pack-bitmap-write.c
@@ -530,7 +530,7 @@ void bitmap_writer_finish(struct pack_idx_entry **index,
header.version = htons(default_version);
header.options = htons(flags | options);
header.entry_count = htonl(writer.selected_nr);
- memcpy(header.checksum, writer.pack_checksum, 20);
+ hashcpy(header.checksum, writer.pack_checksum);
sha1write(f, &header, sizeof(header));
dump_bitmap(f, writer.commits);
diff --git a/pack-write.c b/pack-write.c
index 9b8308b759..9ccf80419b 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -336,7 +336,7 @@ struct sha1file *create_tmp_packfile(char **pack_tmp_name)
return sha1fd(fd, *pack_tmp_name);
}
-void finish_tmp_packfile(char *name_buffer,
+void finish_tmp_packfile(struct strbuf *name_buffer,
const char *pack_tmp_name,
struct pack_idx_entry **written_list,
uint32_t nr_written,
@@ -344,7 +344,7 @@ void finish_tmp_packfile(char *name_buffer,
unsigned char sha1[])
{
const char *idx_tmp_name;
- char *end_of_name_prefix = strrchr(name_buffer, 0);
+ int basename_len = name_buffer->len;
if (adjust_shared_perm(pack_tmp_name))
die_errno("unable to make temporary pack file readable");
@@ -354,17 +354,19 @@ void finish_tmp_packfile(char *name_buffer,
if (adjust_shared_perm(idx_tmp_name))
die_errno("unable to make temporary index file readable");
- sprintf(end_of_name_prefix, "%s.pack", sha1_to_hex(sha1));
- free_pack_by_name(name_buffer);
+ strbuf_addf(name_buffer, "%s.pack", sha1_to_hex(sha1));
+ free_pack_by_name(name_buffer->buf);
- if (rename(pack_tmp_name, name_buffer))
+ if (rename(pack_tmp_name, name_buffer->buf))
die_errno("unable to rename temporary pack file");
- sprintf(end_of_name_prefix, "%s.idx", sha1_to_hex(sha1));
- if (rename(idx_tmp_name, name_buffer))
+ strbuf_setlen(name_buffer, basename_len);
+
+ strbuf_addf(name_buffer, "%s.idx", sha1_to_hex(sha1));
+ if (rename(idx_tmp_name, name_buffer->buf))
die_errno("unable to rename temporary index file");
- *end_of_name_prefix = '\0';
+ strbuf_setlen(name_buffer, basename_len);
free((void *)idx_tmp_name);
}
diff --git a/pack.h b/pack.h
index 12d951659c..3223f5a038 100644
--- a/pack.h
+++ b/pack.h
@@ -91,6 +91,6 @@ extern int encode_in_pack_object_header(enum object_type, uintmax_t, unsigned ch
extern int read_pack_header(int fd, struct pack_header *);
extern struct sha1file *create_tmp_packfile(char **pack_tmp_name);
-extern void finish_tmp_packfile(char *name_buffer, const char *pack_tmp_name, struct pack_idx_entry **written_list, uint32_t nr_written, struct pack_idx_option *pack_idx_opts, unsigned char sha1[]);
+extern void finish_tmp_packfile(struct strbuf *name_buffer, const char *pack_tmp_name, struct pack_idx_entry **written_list, uint32_t nr_written, struct pack_idx_option *pack_idx_opts, unsigned char sha1[]);
#endif
diff --git a/parse-options.c b/parse-options.c
index 7b8d3faa17..a5fa0b8938 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -223,13 +223,10 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
const struct option *options)
{
const struct option *all_opts = options;
- const char *arg_end = strchr(arg, '=');
+ const char *arg_end = strchrnul(arg, '=');
const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
int abbrev_flags = 0, ambiguous_flags = 0;
- if (!arg_end)
- arg_end = arg + strlen(arg);
-
for (; options->type != OPTION_END; options++) {
const char *rest, *long_name = options->long_name;
int flags = 0, opt_flags = 0;
diff --git a/patch-ids.c b/patch-ids.c
index bc8a28fdd7..bf81b92361 100644
--- a/patch-ids.c
+++ b/patch-ids.c
@@ -83,10 +83,7 @@ static struct patch_id *add_commit(struct commit *commit,
ent = &bucket->bucket[bucket->nr++];
hashcpy(ent->patch_id, sha1);
- if (ids->alloc <= ids->nr) {
- ids->alloc = alloc_nr(ids->nr);
- ids->table = xrealloc(ids->table, sizeof(ent) * ids->alloc);
- }
+ ALLOC_GROW(ids->table, ids->nr + 1, ids->alloc);
if (pos < ids->nr)
memmove(ids->table + pos + 1, ids->table + pos,
sizeof(ent) * (ids->nr - pos));
diff --git a/pretty.c b/pretty.c
index 87db08bd74..3c43db558a 100644
--- a/pretty.c
+++ b/pretty.c
@@ -397,12 +397,18 @@ static const char *show_ident_date(const struct ident_split *ident,
enum date_mode mode)
{
unsigned long date = 0;
- int tz = 0;
+ long tz = 0;
if (ident->date_begin && ident->date_end)
date = strtoul(ident->date_begin, NULL, 10);
- if (ident->tz_begin && ident->tz_end)
- tz = strtol(ident->tz_begin, NULL, 10);
+ if (date_overflows(date))
+ date = 0;
+ else {
+ if (ident->tz_begin && ident->tz_end)
+ tz = strtol(ident->tz_begin, NULL, 10);
+ if (tz >= INT_MAX || tz <= INT_MIN)
+ tz = 0;
+ }
return show_date(date, tz, mode);
}
@@ -549,14 +555,13 @@ static char *get_header(const struct commit *commit, const char *msg,
const char *line = msg;
while (line) {
- const char *eol = strchr(line, '\n'), *next;
+ const char *eol = strchrnul(line, '\n'), *next;
if (line == eol)
return NULL;
- if (!eol) {
+ if (!*eol) {
warning("malformed commit (header is missing newline): %s",
sha1_to_hex(commit->object.sha1));
- eol = line + strlen(line);
next = NULL;
} else
next = eol + 1;
diff --git a/progress.c b/progress.c
index 10652b174d..261314ef3c 100644
--- a/progress.c
+++ b/progress.c
@@ -9,6 +9,7 @@
*/
#include "git-compat-util.h"
+#include "gettext.h"
#include "progress.h"
#include "strbuf.h"
@@ -220,7 +221,7 @@ struct progress *start_progress(const char *title, unsigned total)
void stop_progress(struct progress **p_progress)
{
- stop_progress_msg(p_progress, "done");
+ stop_progress_msg(p_progress, _("done"));
}
void stop_progress_msg(struct progress **p_progress, const char *msg)
diff --git a/read-cache.c b/read-cache.c
index fb440b4d9d..ba13353b37 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -990,11 +990,7 @@ int add_index_entry(struct index_state *istate, struct cache_entry *ce, int opti
}
/* Make sure the array is big enough .. */
- if (istate->cache_nr == istate->cache_alloc) {
- istate->cache_alloc = alloc_nr(istate->cache_alloc);
- istate->cache = xrealloc(istate->cache,
- istate->cache_alloc * sizeof(*istate->cache));
- }
+ ALLOC_GROW(istate->cache, istate->cache_nr + 1, istate->cache_alloc);
/* Add it in.. */
istate->cache_nr++;
@@ -1220,6 +1216,42 @@ static struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
#define INDEX_FORMAT_DEFAULT 3
+static int index_format_config(const char *var, const char *value, void *cb)
+{
+ unsigned int *version = cb;
+ if (!strcmp(var, "index.version")) {
+ *version = git_config_int(var, value);
+ return 0;
+ }
+ return 1;
+}
+
+static unsigned int get_index_format_default(void)
+{
+ char *envversion = getenv("GIT_INDEX_VERSION");
+ char *endp;
+ unsigned int version = INDEX_FORMAT_DEFAULT;
+
+ if (!envversion) {
+ git_config(index_format_config, &version);
+ if (version < INDEX_FORMAT_LB || INDEX_FORMAT_UB < version) {
+ warning(_("index.version set, but the value is invalid.\n"
+ "Using version %i"), INDEX_FORMAT_DEFAULT);
+ return INDEX_FORMAT_DEFAULT;
+ }
+ return version;
+ }
+
+ version = strtoul(envversion, &endp, 10);
+ if (*endp ||
+ version < INDEX_FORMAT_LB || INDEX_FORMAT_UB < version) {
+ warning(_("GIT_INDEX_VERSION set, but the value is invalid.\n"
+ "Using version %i"), INDEX_FORMAT_DEFAULT);
+ version = INDEX_FORMAT_DEFAULT;
+ }
+ return version;
+}
+
/*
* dev/ino/uid/gid/size are also just tracked to the low 32 bits
* Again - this is just a (very strong in practice) heuristic that
@@ -1776,7 +1808,7 @@ int write_index(struct index_state *istate, int newfd)
}
if (!istate->version)
- istate->version = INDEX_FORMAT_DEFAULT;
+ istate->version = get_index_format_default();
/* demote version 3 to version 2 when the latter suffices */
if (istate->version == 3 || istate->version == 2)
diff --git a/reflog-walk.c b/reflog-walk.c
index b2fbdb2392..0dd5084fe5 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -26,14 +26,10 @@ static int read_one_reflog(unsigned char *osha1, unsigned char *nsha1,
struct complete_reflogs *array = cb_data;
struct reflog_info *item;
- if (array->nr >= array->alloc) {
- array->alloc = alloc_nr(array->nr + 1);
- array->items = xrealloc(array->items, array->alloc *
- sizeof(struct reflog_info));
- }
+ ALLOC_GROW(array->items, array->nr + 1, array->alloc);
item = array->items + array->nr;
- memcpy(item->osha1, osha1, 20);
- memcpy(item->nsha1, nsha1, 20);
+ hashcpy(item->osha1, osha1);
+ hashcpy(item->nsha1, nsha1);
item->email = xstrdup(email);
item->timestamp = timestamp;
item->tz = tz;
@@ -114,11 +110,7 @@ static void add_commit_info(struct commit *commit, void *util,
struct commit_info_lifo *lifo)
{
struct commit_info *info;
- if (lifo->nr >= lifo->alloc) {
- lifo->alloc = alloc_nr(lifo->nr + 1);
- lifo->items = xrealloc(lifo->items,
- lifo->alloc * sizeof(struct commit_info));
- }
+ ALLOC_GROW(lifo->items, lifo->nr + 1, lifo->alloc);
info = lifo->items + lifo->nr;
info->commit = commit;
info->util = util;
diff --git a/refs.c b/refs.c
index 89228e2373..28d5eca8ea 100644
--- a/refs.c
+++ b/refs.c
@@ -1222,7 +1222,7 @@ static int resolve_gitlink_packed_ref(struct ref_cache *refs,
if (ref == NULL)
return -1;
- memcpy(sha1, ref->u.value.sha1, 20);
+ hashcpy(sha1, ref->u.value.sha1);
return 0;
}
@@ -1477,7 +1477,7 @@ static int filter_refs(const char *refname, const unsigned char *sha1, int flags
void *data)
{
struct ref_filter *filter = (struct ref_filter *)data;
- if (fnmatch(filter->pattern, refname, 0))
+ if (wildmatch(filter->pattern, refname, 0, NULL))
return 0;
return filter->fn(refname, sha1, flags, filter->cb_data);
}
diff --git a/remote-curl.c b/remote-curl.c
index 10cb0114ea..52c2d96ce6 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -423,11 +423,8 @@ static int run_slot(struct active_request_slot *slot,
if (!results)
results = &results_buf;
- slot->results = results;
- slot->curl_result = curl_easy_perform(slot->curl);
- finish_active_slot(slot);
+ err = run_one_slot(slot, results);
- err = handle_curl_result(results);
if (err != HTTP_OK && err != HTTP_REAUTH) {
error("RPC failed; result=%d, HTTP code = %ld",
results->curl_result, results->http_code);
diff --git a/remote-testsvn.c b/remote-testsvn.c
index 078f1ffa41..6be55cbe9e 100644
--- a/remote-testsvn.c
+++ b/remote-testsvn.c
@@ -78,8 +78,8 @@ static int parse_rev_note(const char *msg, struct rev_note *res)
size_t len;
while (*msg) {
- end = strchr(msg, '\n');
- len = end ? end - msg : strlen(msg);
+ end = strchrnul(msg, '\n');
+ len = end - msg;
key = "Revision-number: ";
if (starts_with(msg, key)) {
diff --git a/remote.c b/remote.c
index e41251ee77..21b096932e 100644
--- a/remote.c
+++ b/remote.c
@@ -49,6 +49,7 @@ static int branches_nr;
static struct branch *current_branch;
static const char *default_remote_name;
+static const char *branch_pushremote_name;
static const char *pushremote_name;
static int explicit_default_remote_name;
@@ -352,7 +353,7 @@ static int handle_config(const char *key, const char *value, void *cb)
}
} else if (!strcmp(subkey, ".pushremote")) {
if (branch == current_branch)
- if (git_config_string(&pushremote_name, key, value))
+ if (git_config_string(&branch_pushremote_name, key, value))
return -1;
} else if (!strcmp(subkey, ".merge")) {
if (!value)
@@ -492,6 +493,10 @@ static void read_config(void)
make_branch(head_ref + strlen("refs/heads/"), 0);
}
git_config(handle_config, NULL);
+ if (branch_pushremote_name) {
+ free((char *)pushremote_name);
+ pushremote_name = branch_pushremote_name;
+ }
alias_all_urls();
}
@@ -1031,11 +1036,13 @@ int count_refspec_match(const char *pattern,
}
}
if (!matched) {
- *matched_ref = matched_weak;
+ if (matched_ref)
+ *matched_ref = matched_weak;
return weak_match;
}
else {
- *matched_ref = matched;
+ if (matched_ref)
+ *matched_ref = matched;
return match;
}
}
@@ -1055,18 +1062,25 @@ static struct ref *alloc_delete_ref(void)
return ref;
}
-static struct ref *try_explicit_object_name(const char *name)
+static int try_explicit_object_name(const char *name,
+ struct ref **match)
{
unsigned char sha1[20];
- struct ref *ref;
- if (!*name)
- return alloc_delete_ref();
+ if (!*name) {
+ if (match)
+ *match = alloc_delete_ref();
+ return 0;
+ }
+
if (get_sha1(name, sha1))
- return NULL;
- ref = alloc_ref(name);
- hashcpy(ref->new_sha1, sha1);
- return ref;
+ return -1;
+
+ if (match) {
+ *match = alloc_ref(name);
+ hashcpy((*match)->new_sha1, sha1);
+ }
+ return 0;
}
static struct ref *make_linked_ref(const char *name, struct ref ***tail)
@@ -1096,12 +1110,37 @@ static char *guess_ref(const char *name, struct ref *peer)
return strbuf_detach(&buf, NULL);
}
+static int match_explicit_lhs(struct ref *src,
+ struct refspec *rs,
+ struct ref **match,
+ int *allocated_match)
+{
+ switch (count_refspec_match(rs->src, src, match)) {
+ case 1:
+ if (allocated_match)
+ *allocated_match = 0;
+ return 0;
+ case 0:
+ /* The source could be in the get_sha1() format
+ * not a reference name. :refs/other is a
+ * way to delete 'other' ref at the remote end.
+ */
+ if (try_explicit_object_name(rs->src, match) < 0)
+ return error("src refspec %s does not match any.", rs->src);
+ if (allocated_match)
+ *allocated_match = 1;
+ return 0;
+ default:
+ return error("src refspec %s matches more than one.", rs->src);
+ }
+}
+
static int match_explicit(struct ref *src, struct ref *dst,
struct ref ***dst_tail,
struct refspec *rs)
{
struct ref *matched_src, *matched_dst;
- int copy_src;
+ int allocated_src;
const char *dst_value = rs->dst;
char *dst_guess;
@@ -1110,23 +1149,8 @@ static int match_explicit(struct ref *src, struct ref *dst,
return 0;
matched_src = matched_dst = NULL;
- switch (count_refspec_match(rs->src, src, &matched_src)) {
- case 1:
- copy_src = 1;
- break;
- case 0:
- /* The source could be in the get_sha1() format
- * not a reference name. :refs/other is a
- * way to delete 'other' ref at the remote end.
- */
- matched_src = try_explicit_object_name(rs->src);
- if (!matched_src)
- return error("src refspec %s does not match any.", rs->src);
- copy_src = 0;
- break;
- default:
- return error("src refspec %s matches more than one.", rs->src);
- }
+ if (match_explicit_lhs(src, rs, &matched_src, &allocated_src) < 0)
+ return -1;
if (!dst_value) {
unsigned char sha1[20];
@@ -1171,7 +1195,9 @@ static int match_explicit(struct ref *src, struct ref *dst,
return error("dst ref %s receives from more than one src.",
matched_dst->name);
else {
- matched_dst->peer_ref = copy_src ? copy_ref(matched_src) : matched_src;
+ matched_dst->peer_ref = allocated_src ?
+ matched_src :
+ copy_ref(matched_src);
matched_dst->force = rs->force;
}
return 0;
@@ -1353,6 +1379,31 @@ static void prepare_ref_index(struct string_list *ref_index, struct ref *ref)
}
/*
+ * Given only the set of local refs, sanity-check the set of push
+ * refspecs. We can't catch all errors that match_push_refs would,
+ * but we can catch some errors early before even talking to the
+ * remote side.
+ */
+int check_push_refs(struct ref *src, int nr_refspec, const char **refspec_names)
+{
+ struct refspec *refspec = parse_push_refspec(nr_refspec, refspec_names);
+ int ret = 0;
+ int i;
+
+ for (i = 0; i < nr_refspec; i++) {
+ struct refspec *rs = refspec + i;
+
+ if (rs->pattern || rs->matching)
+ continue;
+
+ ret |= match_explicit_lhs(src, rs, NULL, NULL);
+ }
+
+ free_refspec(nr_refspec, refspec);
+ return ret;
+}
+
+/*
* Given the set of refs the local repository has, the set of refs the
* remote repository has, and the refspec used for push, determine
* what remote refs we will update and with what value by setting
diff --git a/remote.h b/remote.h
index fb7647fab9..917d383a80 100644
--- a/remote.h
+++ b/remote.h
@@ -166,6 +166,7 @@ extern int query_refspecs(struct refspec *specs, int nr, struct refspec *query);
char *apply_refspecs(struct refspec *refspecs, int nr_refspec,
const char *name);
+int check_push_refs(struct ref *src, int nr_refspec, const char **refspec);
int match_push_refs(struct ref *src, struct ref **dst,
int nr_refspec, const char **refspec, int all);
void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
diff --git a/replace_object.c b/replace_object.c
index cdcaf8cbe2..0ab2dc1374 100644
--- a/replace_object.c
+++ b/replace_object.c
@@ -3,8 +3,13 @@
#include "refs.h"
#include "commit.h"
+/*
+ * An array of replacements. The array is kept sorted by the original
+ * sha1.
+ */
static struct replace_object {
- unsigned char sha1[2][20];
+ unsigned char original[20];
+ unsigned char replacement[20];
} **replace_object;
static int replace_object_alloc, replace_object_nr;
@@ -12,7 +17,7 @@ static int replace_object_alloc, replace_object_nr;
static const unsigned char *replace_sha1_access(size_t index, void *table)
{
struct replace_object **replace = table;
- return replace[index]->sha1[0];
+ return replace[index]->original;
}
static int replace_object_pos(const unsigned char *sha1)
@@ -24,7 +29,7 @@ static int replace_object_pos(const unsigned char *sha1)
static int register_replace_object(struct replace_object *replace,
int ignore_dups)
{
- int pos = replace_object_pos(replace->sha1[0]);
+ int pos = replace_object_pos(replace->original);
if (0 <= pos) {
if (ignore_dups)
@@ -36,12 +41,8 @@ static int register_replace_object(struct replace_object *replace,
return 1;
}
pos = -pos - 1;
- if (replace_object_alloc <= ++replace_object_nr) {
- replace_object_alloc = alloc_nr(replace_object_alloc);
- replace_object = xrealloc(replace_object,
- sizeof(*replace_object) *
- replace_object_alloc);
- }
+ ALLOC_GROW(replace_object, replace_object_nr + 1, replace_object_alloc);
+ replace_object_nr++;
if (pos < replace_object_nr)
memmove(replace_object + pos + 1,
replace_object + pos,
@@ -60,14 +61,14 @@ static int register_replace_ref(const char *refname,
const char *hash = slash ? slash + 1 : refname;
struct replace_object *repl_obj = xmalloc(sizeof(*repl_obj));
- if (strlen(hash) != 40 || get_sha1_hex(hash, repl_obj->sha1[0])) {
+ if (strlen(hash) != 40 || get_sha1_hex(hash, repl_obj->original)) {
free(repl_obj);
warning("bad replace ref name: %s", refname);
return 0;
}
/* Copy sha1 from the read ref */
- hashcpy(repl_obj->sha1[1], sha1);
+ hashcpy(repl_obj->replacement, sha1);
/* Register new object */
if (register_replace_object(repl_obj, 1))
@@ -86,12 +87,19 @@ static void prepare_replace_object(void)
for_each_replace_ref(register_replace_ref, NULL);
replace_object_prepared = 1;
if (!replace_object_nr)
- read_replace_refs = 0;
+ check_replace_refs = 0;
}
/* We allow "recursive" replacement. Only within reason, though */
#define MAXREPLACEDEPTH 5
+/*
+ * If a replacement for object sha1 has been set up, return the
+ * replacement object's name (replaced recursively, if necessary).
+ * The return value is either sha1 or a pointer to a
+ * permanently-allocated value. This function always respects replace
+ * references, regardless of the value of check_replace_refs.
+ */
const unsigned char *do_lookup_replace_object(const unsigned char *sha1)
{
int pos, depth = MAXREPLACEDEPTH;
@@ -107,7 +115,7 @@ const unsigned char *do_lookup_replace_object(const unsigned char *sha1)
pos = replace_object_pos(cur);
if (0 <= pos)
- cur = replace_object[pos]->sha1[1];
+ cur = replace_object[pos]->replacement;
} while (0 <= pos);
return cur;
diff --git a/revision.c b/revision.c
index bd027bc015..85085501f6 100644
--- a/revision.c
+++ b/revision.c
@@ -1186,7 +1186,7 @@ int ref_excluded(struct string_list *ref_excludes, const char *path)
if (!ref_excludes)
return 0;
for_each_string_list_item(item, ref_excludes) {
- if (!fnmatch(item->string, path, 0))
+ if (!wildmatch(item->string, path, 0, NULL))
return 1;
}
return 0;
@@ -1575,6 +1575,10 @@ static void read_revisions_from_stdin(struct rev_info *revs,
{
struct strbuf sb;
int seen_dashdash = 0;
+ int save_warning;
+
+ save_warning = warn_on_object_refname_ambiguity;
+ warn_on_object_refname_ambiguity = 0;
strbuf_init(&sb, 1000);
while (strbuf_getwholeline(&sb, stdin, '\n') != EOF) {
@@ -1596,7 +1600,9 @@ static void read_revisions_from_stdin(struct rev_info *revs,
}
if (seen_dashdash)
read_pathspec_from_stdin(revs, &sb, prune);
+
strbuf_release(&sb);
+ warn_on_object_refname_ambiguity = save_warning;
}
static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what)
diff --git a/run-command.c b/run-command.c
index 3914d9c511..75abc478c6 100644
--- a/run-command.c
+++ b/run-command.c
@@ -760,13 +760,11 @@ char *find_hook(const char *name)
return path;
}
-int run_hook(const char *index_file, const char *name, ...)
+int run_hook_ve(const char *const *env, const char *name, va_list args)
{
struct child_process hook;
struct argv_array argv = ARGV_ARRAY_INIT;
- const char *p, *env[2];
- char index[PATH_MAX];
- va_list args;
+ const char *p;
int ret;
p = find_hook(name);
@@ -775,23 +773,45 @@ int run_hook(const char *index_file, const char *name, ...)
argv_array_push(&argv, p);
- va_start(args, name);
while ((p = va_arg(args, const char *)))
argv_array_push(&argv, p);
- va_end(args);
memset(&hook, 0, sizeof(hook));
hook.argv = argv.argv;
+ hook.env = env;
hook.no_stdin = 1;
hook.stdout_to_stderr = 1;
- if (index_file) {
- snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
- env[0] = index;
- env[1] = NULL;
- hook.env = env;
- }
ret = run_command(&hook);
argv_array_clear(&argv);
return ret;
}
+
+int run_hook_le(const char *const *env, const char *name, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, name);
+ ret = run_hook_ve(env, name, args);
+ va_end(args);
+
+ return ret;
+}
+
+int run_hook_with_custom_index(const char *index_file, const char *name, ...)
+{
+ const char *hook_env[3] = { NULL };
+ char index[PATH_MAX];
+ va_list args;
+ int ret;
+
+ snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
+ hook_env[0] = index;
+
+ va_start(args, name);
+ ret = run_hook_ve(hook_env, name, args);
+ va_end(args);
+
+ return ret;
+}
diff --git a/run-command.h b/run-command.h
index 6b985afd07..3653bfa6e1 100644
--- a/run-command.h
+++ b/run-command.h
@@ -47,7 +47,12 @@ int run_command(struct child_process *);
extern char *find_hook(const char *name);
LAST_ARG_MUST_BE_NULL
-extern int run_hook(const char *index_file, const char *name, ...);
+extern int run_hook_le(const char *const *env, const char *name, ...);
+extern int run_hook_ve(const char *const *env, const char *name, va_list args);
+
+LAST_ARG_MUST_BE_NULL
+__attribute__((deprecated))
+extern int run_hook_with_custom_index(const char *index_file, const char *name, ...);
#define RUN_COMMAND_NO_STDIN 1
#define RUN_GIT_CMD 2 /*If this is to be git sub-command */
diff --git a/sh-i18n--envsubst.c b/sh-i18n--envsubst.c
index 5ddd6886c8..855d28cf94 100644
--- a/sh-i18n--envsubst.c
+++ b/sh-i18n--envsubst.c
@@ -237,18 +237,6 @@ string_list_sort (string_list_ty *slp)
qsort (slp->item, slp->nitems, sizeof (slp->item[0]), cmp_string);
}
-/* Test whether a string list contains a given string. */
-static inline int
-string_list_member (const string_list_ty *slp, const char *s)
-{
- size_t j;
-
- for (j = 0; j < slp->nitems; ++j)
- if (strcmp (slp->item[j], s) == 0)
- return 1;
- return 0;
-}
-
/* Test whether a sorted string list contains a given string. */
static int
sorted_string_list_member (const string_list_ty *slp, const char *s)
diff --git a/sha1_file.c b/sha1_file.c
index 019628add5..400aa463a4 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -60,6 +60,12 @@ static struct cached_object empty_tree = {
0
};
+/*
+ * A pointer to the last packed_git in which an object was found.
+ * When an object is sought, we look in this packfile first, because
+ * objects that are looked up at similar times are often in the same
+ * packfile as one another.
+ */
static struct packed_git *last_found_pack;
static struct cached_object *find_cached_object(const unsigned char *sha1)
@@ -178,17 +184,7 @@ static void fill_sha1_path(char *pathbuf, const unsigned char *sha1)
}
}
-/*
- * NOTE! This returns a statically allocated buffer, so you have to be
- * careful about using it. Do an "xstrdup()" if you need to save the
- * filename.
- *
- * Also note that this returns the location for creating. Reading
- * SHA1 file can happen from any alternate directory listed in the
- * DB_ENVIRONMENT environment variable if it is not found in
- * the primary object database.
- */
-char *sha1_file_name(const unsigned char *sha1)
+const char *sha1_file_name(const unsigned char *sha1)
{
static char buf[PATH_MAX];
const char *objdir;
@@ -208,6 +204,11 @@ char *sha1_file_name(const unsigned char *sha1)
return buf;
}
+/*
+ * Return the name of the pack or index file with the specified sha1
+ * in its filename. *base and *name are scratch space that must be
+ * provided by the caller. which should be "pack" or "idx".
+ */
static char *sha1_get_pack_name(const unsigned char *sha1,
char **name, char **base, const char *which)
{
@@ -436,8 +437,7 @@ void prepare_alt_odb(void)
static int has_loose_object_local(const unsigned char *sha1)
{
- char *name = sha1_file_name(sha1);
- return !access(name, F_OK);
+ return !access(sha1_file_name(sha1), F_OK);
}
int has_loose_object_nonlocal(const unsigned char *sha1)
@@ -489,7 +489,12 @@ void pack_report(void)
sz_fmt(pack_mapped), sz_fmt(peak_pack_mapped));
}
-static int check_packed_git_idx(const char *path, struct packed_git *p)
+/*
+ * Open and mmap the index file at path, perform a couple of
+ * consistency checks, then record its information to p. Return 0 on
+ * success.
+ */
+static int check_packed_git_idx(const char *path, struct packed_git *p)
{
void *idx_map;
struct pack_idx_header *hdr;
@@ -1412,17 +1417,15 @@ int git_open_noatime(const char *name)
static int stat_sha1_file(const unsigned char *sha1, struct stat *st)
{
- char *name = sha1_file_name(sha1);
struct alternate_object_database *alt;
- if (!lstat(name, st))
+ if (!lstat(sha1_file_name(sha1), st))
return 0;
prepare_alt_odb();
errno = ENOENT;
for (alt = alt_odb_list; alt; alt = alt->next) {
- name = alt->name;
- fill_sha1_path(name, sha1);
+ fill_sha1_path(alt->name, sha1);
if (!lstat(alt->base, st))
return 0;
}
@@ -1433,18 +1436,16 @@ static int stat_sha1_file(const unsigned char *sha1, struct stat *st)
static int open_sha1_file(const unsigned char *sha1)
{
int fd;
- char *name = sha1_file_name(sha1);
struct alternate_object_database *alt;
- fd = git_open_noatime(name);
+ fd = git_open_noatime(sha1_file_name(sha1));
if (fd >= 0)
return fd;
prepare_alt_odb();
errno = ENOENT;
for (alt = alt_odb_list; alt; alt = alt->next) {
- name = alt->name;
- fill_sha1_path(name, sha1);
+ fill_sha1_path(alt->name, sha1);
fd = git_open_noatime(alt->base);
if (fd >= 0)
return fd;
@@ -2287,6 +2288,10 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset,
*final_size = size;
unuse_pack(&w_curs);
+
+ if (delta_stack != small_delta_stack)
+ free(delta_stack);
+
return data;
}
@@ -2446,6 +2451,10 @@ static int fill_pack_entry(const unsigned char *sha1,
return 1;
}
+/*
+ * Iff a pack file contains the object named by sha1, return true and
+ * store its location to e.
+ */
static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
{
struct packed_git *p;
@@ -2458,11 +2467,13 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
return 1;
for (p = packed_git; p; p = p->next) {
- if (p == last_found_pack || !fill_pack_entry(sha1, e, p))
- continue;
+ if (p == last_found_pack)
+ continue; /* we already checked this one */
- last_found_pack = p;
- return 1;
+ if (fill_pack_entry(sha1, e, p)) {
+ last_found_pack = p;
+ return 1;
+ }
}
return 0;
}
@@ -2624,12 +2635,7 @@ int pretend_sha1_file(void *buf, unsigned long len, enum object_type type,
hash_sha1_file(buf, len, typename(type), sha1);
if (has_sha1_file(sha1) || find_cached_object(sha1))
return 0;
- if (cached_object_alloc <= cached_object_nr) {
- cached_object_alloc = alloc_nr(cached_object_alloc);
- cached_objects = xrealloc(cached_objects,
- sizeof(*cached_objects) *
- cached_object_alloc);
- }
+ ALLOC_GROW(cached_objects, cached_object_nr + 1, cached_object_alloc);
co = &cached_objects[cached_object_nr++];
co->size = len;
co->type = type;
@@ -2677,7 +2683,6 @@ void *read_sha1_file_extended(const unsigned char *sha1,
unsigned flag)
{
void *data;
- char *path;
const struct packed_git *p;
const unsigned char *repl = lookup_replace_object_extended(sha1, flag);
@@ -2695,7 +2700,8 @@ void *read_sha1_file_extended(const unsigned char *sha1,
sha1_to_hex(repl), sha1_to_hex(sha1));
if (has_loose_object(repl)) {
- path = sha1_file_name(sha1);
+ const char *path = sha1_file_name(sha1);
+
die("loose object %s (stored in %s) is corrupt",
sha1_to_hex(repl), path);
}
@@ -2893,10 +2899,9 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
git_zstream stream;
git_SHA_CTX c;
unsigned char parano_sha1[20];
- char *filename;
static char tmp_file[PATH_MAX];
+ const char *filename = sha1_file_name(sha1);
- filename = sha1_file_name(sha1);
fd = create_tmpfile(tmp_file, sizeof(tmp_file), filename);
if (fd < 0) {
if (errno == EACCES)
diff --git a/shallow.c b/shallow.c
index bbc98b55c0..0b267b6411 100644
--- a/shallow.c
+++ b/shallow.c
@@ -8,9 +8,10 @@
#include "diff.h"
#include "revision.h"
#include "commit-slab.h"
+#include "sigchain.h"
static int is_shallow = -1;
-static struct stat shallow_stat;
+static struct stat_validity shallow_stat;
static char *alternate_shallow_file;
void set_alternate_shallow_file(const char *path, int override)
@@ -52,12 +53,12 @@ int is_repository_shallow(void)
* shallow file should be used. We could just open it and it
* will likely fail. But let's do an explicit check instead.
*/
- if (!*path ||
- stat(path, &shallow_stat) ||
- (fp = fopen(path, "r")) == NULL) {
+ if (!*path || (fp = fopen(path, "r")) == NULL) {
+ stat_validity_clear(&shallow_stat);
is_shallow = 0;
return is_shallow;
}
+ stat_validity_update(&shallow_stat, fileno(fp));
is_shallow = 1;
while (fgets(buf, sizeof(buf), fp)) {
@@ -137,21 +138,11 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
void check_shallow_file_for_update(void)
{
- struct stat st;
-
- if (!is_shallow)
- return;
- else if (is_shallow == -1)
+ if (is_shallow == -1)
die("BUG: shallow must be initialized by now");
- if (stat(git_path("shallow"), &st))
- die("shallow file was removed during fetch");
- else if (st.st_mtime != shallow_stat.st_mtime
-#ifdef USE_NSEC
- || ST_MTIME_NSEC(st) != ST_MTIME_NSEC(shallow_stat)
-#endif
- )
- die("shallow file was changed during fetch");
+ if (!stat_validity_check(&shallow_stat, git_path("shallow")))
+ die("shallow file has changed since we read it");
}
#define SEEN_ONLY 1
@@ -216,27 +207,53 @@ int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
return write_shallow_commits_1(out, use_pack_protocol, extra, 0);
}
-char *setup_temporary_shallow(const struct sha1_array *extra)
+static struct strbuf temporary_shallow = STRBUF_INIT;
+
+static void remove_temporary_shallow(void)
+{
+ if (temporary_shallow.len) {
+ unlink_or_warn(temporary_shallow.buf);
+ strbuf_reset(&temporary_shallow);
+ }
+}
+
+static void remove_temporary_shallow_on_signal(int signo)
+{
+ remove_temporary_shallow();
+ sigchain_pop(signo);
+ raise(signo);
+}
+
+const char *setup_temporary_shallow(const struct sha1_array *extra)
{
+ static int installed_handler;
struct strbuf sb = STRBUF_INIT;
int fd;
+ if (temporary_shallow.len)
+ die("BUG: attempt to create two temporary shallow files");
+
if (write_shallow_commits(&sb, 0, extra)) {
- struct strbuf path = STRBUF_INIT;
- strbuf_addstr(&path, git_path("shallow_XXXXXX"));
- fd = xmkstemp(path.buf);
+ strbuf_addstr(&temporary_shallow, git_path("shallow_XXXXXX"));
+ fd = xmkstemp(temporary_shallow.buf);
+
+ if (!installed_handler) {
+ atexit(remove_temporary_shallow);
+ sigchain_push_common(remove_temporary_shallow_on_signal);
+ }
+
if (write_in_full(fd, sb.buf, sb.len) != sb.len)
die_errno("failed to write to %s",
- path.buf);
+ temporary_shallow.buf);
close(fd);
strbuf_release(&sb);
- return strbuf_detach(&path, NULL);
+ return temporary_shallow.buf;
}
/*
* is_repository_shallow() sees empty string as "no shallow
* file".
*/
- return xstrdup("");
+ return temporary_shallow.buf;
}
void setup_alternate_shallow(struct lock_file *shallow_lock,
@@ -246,9 +263,9 @@ void setup_alternate_shallow(struct lock_file *shallow_lock,
struct strbuf sb = STRBUF_INIT;
int fd;
- check_shallow_file_for_update();
fd = hold_lock_file_for_update(shallow_lock, git_path("shallow"),
LOCK_DIE_ON_ERROR);
+ check_shallow_file_for_update();
if (write_shallow_commits(&sb, 0, extra)) {
if (write_in_full(fd, sb.buf, sb.len) != sb.len)
die_errno("failed to write to %s",
@@ -293,9 +310,9 @@ void prune_shallow(int show_only)
strbuf_release(&sb);
return;
}
- check_shallow_file_for_update();
fd = hold_lock_file_for_update(&shallow_lock, git_path("shallow"),
LOCK_DIE_ON_ERROR);
+ check_shallow_file_for_update();
if (write_shallow_commits_1(&sb, 0, NULL, SEEN_ONLY)) {
if (write_in_full(fd, sb.buf, sb.len) != sb.len)
die_errno("failed to write to %s",
diff --git a/strbuf.h b/strbuf.h
index 73e80cea69..39c14cfa38 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -17,20 +17,23 @@ extern void strbuf_init(struct strbuf *, size_t);
extern void strbuf_release(struct strbuf *);
extern char *strbuf_detach(struct strbuf *, size_t *);
extern void strbuf_attach(struct strbuf *, void *, size_t, size_t);
-static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) {
+static inline void strbuf_swap(struct strbuf *a, struct strbuf *b)
+{
struct strbuf tmp = *a;
*a = *b;
*b = tmp;
}
/*----- strbuf size related -----*/
-static inline size_t strbuf_avail(const struct strbuf *sb) {
+static inline size_t strbuf_avail(const struct strbuf *sb)
+{
return sb->alloc ? sb->alloc - sb->len - 1 : 0;
}
extern void strbuf_grow(struct strbuf *, size_t);
-static inline void strbuf_setlen(struct strbuf *sb, size_t len) {
+static inline void strbuf_setlen(struct strbuf *sb, size_t len)
+{
if (len > (sb->alloc ? sb->alloc - 1 : 0))
die("BUG: strbuf_setlen() beyond buffer");
sb->len = len;
@@ -97,7 +100,8 @@ static inline struct strbuf **strbuf_split(const struct strbuf *sb,
extern void strbuf_list_free(struct strbuf **);
/*----- add data in your buffer -----*/
-static inline void strbuf_addch(struct strbuf *sb, int c) {
+static inline void strbuf_addch(struct strbuf *sb, int c)
+{
strbuf_grow(sb, 1);
sb->buf[sb->len++] = c;
sb->buf[sb->len] = '\0';
@@ -113,10 +117,12 @@ extern void strbuf_splice(struct strbuf *, size_t pos, size_t len,
extern void strbuf_add_commented_lines(struct strbuf *out, const char *buf, size_t size);
extern void strbuf_add(struct strbuf *, const void *, size_t);
-static inline void strbuf_addstr(struct strbuf *sb, const char *s) {
+static inline void strbuf_addstr(struct strbuf *sb, const char *s)
+{
strbuf_add(sb, s, strlen(s));
}
-static inline void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2) {
+static inline void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2)
+{
strbuf_grow(sb, sb2->len);
strbuf_add(sb, sb2->buf, sb2->len);
}
diff --git a/streaming.c b/streaming.c
index d7c9f32f0c..2ff036a0fa 100644
--- a/streaming.c
+++ b/streaming.c
@@ -152,8 +152,10 @@ struct git_istream *open_istream(const unsigned char *sha1,
if (filter) {
/* Add "&& !is_null_stream_filter(filter)" for performance */
struct git_istream *nst = attach_stream_filter(st, filter);
- if (!nst)
+ if (!nst) {
close_istream(st);
+ return NULL;
+ }
st = nst;
}
diff --git a/t/Makefile b/t/Makefile
index 2373a04f7a..8fd1a72357 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -36,11 +36,11 @@ test: pre-clean $(TEST_LINT)
$(MAKE) aggregate-results-and-cleanup
prove: pre-clean $(TEST_LINT)
- @echo "*** prove ***"; GIT_CONFIG=.git/config $(PROVE) --exec '$(SHELL_PATH_SQ)' $(GIT_PROVE_OPTS) $(T) :: $(GIT_TEST_OPTS)
+ @echo "*** prove ***"; $(PROVE) --exec '$(SHELL_PATH_SQ)' $(GIT_PROVE_OPTS) $(T) :: $(GIT_TEST_OPTS)
$(MAKE) clean-except-prove-cache
$(T):
- @echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
+ @echo "*** $@ ***"; '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
pre-clean:
$(RM) -r '$(TEST_RESULTS_DIRECTORY_SQ)'
diff --git a/t/lib-terminal.sh b/t/lib-terminal.sh
index 9a2dca506a..51845491bb 100644
--- a/t/lib-terminal.sh
+++ b/t/lib-terminal.sh
@@ -1,6 +1,20 @@
# Helpers for terminal output tests.
-test_expect_success PERL 'set up terminal for tests' '
+# Catch tests which should depend on TTY but forgot to. There's no need
+# to aditionally check that the TTY prereq is set here. If the test declared
+# it and we are running the test, then it must have been set.
+test_terminal () {
+ if ! test_declared_prereq TTY
+ then
+ echo >&4 "test_terminal: need to declare TTY prerequisite"
+ return 127
+ fi
+ perl "$TEST_DIRECTORY"/test-terminal.perl "$@"
+}
+
+test_lazy_prereq TTY '
+ test_have_prereq PERL &&
+
# Reading from the pty master seems to get stuck _sometimes_
# on Mac OS X 10.5.0, using Perl 5.10.0 or 5.8.9.
#
@@ -15,21 +29,8 @@ test_expect_success PERL 'set up terminal for tests' '
# After 2000 iterations or so it hangs.
# https://rt.cpan.org/Ticket/Display.html?id=65692
#
- if test "$(uname -s)" = Darwin
- then
- :
- elif
- perl "$TEST_DIRECTORY"/test-terminal.perl \
- sh -c "test -t 1 && test -t 2"
- then
- test_set_prereq TTY &&
- test_terminal () {
- if ! test_declared_prereq TTY
- then
- echo >&4 "test_terminal: need to declare TTY prerequisite"
- return 127
- fi
- perl "$TEST_DIRECTORY"/test-terminal.perl "$@"
- }
- fi
+ test "$(uname -s)" != Darwin &&
+
+ perl "$TEST_DIRECTORY"/test-terminal.perl \
+ sh -c "test -t 1 && test -t 2"
'
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 9fb582b192..bbc9cb60dd 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -12,8 +12,8 @@ check_config () {
echo "expected a directory $1, a file $1/config and $1/refs"
return 1
fi
- bare=$(GIT_CONFIG="$1/config" git config --bool core.bare)
- worktree=$(GIT_CONFIG="$1/config" git config core.worktree) ||
+ bare=$(cd "$1" && git config --bool core.bare)
+ worktree=$(cd "$1" && git config core.worktree) ||
worktree=unset
test "$bare" = "$2" && test "$worktree" = "$3" || {
@@ -24,18 +24,12 @@ check_config () {
}
test_expect_success 'plain' '
- (
- sane_unset GIT_DIR GIT_WORK_TREE &&
- mkdir plain &&
- cd plain &&
- git init
- ) &&
+ git init plain &&
check_config plain/.git false unset
'
test_expect_success 'plain nested in bare' '
(
- sane_unset GIT_DIR GIT_WORK_TREE &&
git init --bare bare-ancestor.git &&
cd bare-ancestor.git &&
mkdir plain-nested &&
@@ -47,7 +41,6 @@ test_expect_success 'plain nested in bare' '
test_expect_success 'plain through aliased command, outside any git repo' '
(
- sane_unset GIT_DIR GIT_WORK_TREE &&
HOME=$(pwd)/alias-config &&
export HOME &&
mkdir alias-config &&
@@ -65,7 +58,6 @@ test_expect_success 'plain through aliased command, outside any git repo' '
test_expect_failure 'plain nested through aliased command' '
(
- sane_unset GIT_DIR GIT_WORK_TREE &&
git init plain-ancestor-aliased &&
cd plain-ancestor-aliased &&
echo "[alias] aliasedinit = init" >>.git/config &&
@@ -78,7 +70,6 @@ test_expect_failure 'plain nested through aliased command' '
test_expect_failure 'plain nested in bare through aliased command' '
(
- sane_unset GIT_DIR GIT_WORK_TREE &&
git init --bare bare-ancestor-aliased.git &&
cd bare-ancestor-aliased.git &&
echo "[alias] aliasedinit = init" >>config &&
@@ -90,66 +81,36 @@ test_expect_failure 'plain nested in bare through aliased command' '
'
test_expect_success 'plain with GIT_WORK_TREE' '
- if (
- sane_unset GIT_DIR &&
- mkdir plain-wt &&
- cd plain-wt &&
- GIT_WORK_TREE=$(pwd) git init
- )
- then
- echo Should have failed -- GIT_WORK_TREE should not be used
- false
- fi
+ mkdir plain-wt &&
+ test_must_fail env GIT_WORK_TREE="$(pwd)/plain-wt" git init plain-wt
'
test_expect_success 'plain bare' '
- (
- sane_unset GIT_DIR GIT_WORK_TREE GIT_CONFIG &&
- mkdir plain-bare-1 &&
- cd plain-bare-1 &&
- git --bare init
- ) &&
+ git --bare init plain-bare-1 &&
check_config plain-bare-1 true unset
'
test_expect_success 'plain bare with GIT_WORK_TREE' '
- if (
- sane_unset GIT_DIR GIT_CONFIG &&
- mkdir plain-bare-2 &&
- cd plain-bare-2 &&
- GIT_WORK_TREE=$(pwd) git --bare init
- )
- then
- echo Should have failed -- GIT_WORK_TREE should not be used
- false
- fi
+ mkdir plain-bare-2 &&
+ test_must_fail \
+ env GIT_WORK_TREE="$(pwd)/plain-bare-2" \
+ git --bare init plain-bare-2
'
test_expect_success 'GIT_DIR bare' '
-
- (
- sane_unset GIT_CONFIG &&
- mkdir git-dir-bare.git &&
- GIT_DIR=git-dir-bare.git git init
- ) &&
+ mkdir git-dir-bare.git &&
+ GIT_DIR=git-dir-bare.git git init &&
check_config git-dir-bare.git true unset
'
test_expect_success 'init --bare' '
-
- (
- sane_unset GIT_DIR GIT_WORK_TREE GIT_CONFIG &&
- mkdir init-bare.git &&
- cd init-bare.git &&
- git init --bare
- ) &&
+ git init --bare init-bare.git &&
check_config init-bare.git true unset
'
test_expect_success 'GIT_DIR non-bare' '
(
- sane_unset GIT_CONFIG &&
mkdir non-bare &&
cd non-bare &&
GIT_DIR=.git git init
@@ -160,7 +121,6 @@ test_expect_success 'GIT_DIR non-bare' '
test_expect_success 'GIT_DIR & GIT_WORK_TREE (1)' '
(
- sane_unset GIT_CONFIG &&
mkdir git-dir-wt-1.git &&
GIT_WORK_TREE=$(pwd) GIT_DIR=git-dir-wt-1.git git init
) &&
@@ -168,23 +128,16 @@ test_expect_success 'GIT_DIR & GIT_WORK_TREE (1)' '
'
test_expect_success 'GIT_DIR & GIT_WORK_TREE (2)' '
-
- if (
- sane_unset GIT_CONFIG &&
- mkdir git-dir-wt-2.git &&
- GIT_WORK_TREE=$(pwd) GIT_DIR=git-dir-wt-2.git git --bare init
- )
- then
- echo Should have failed -- --bare should not be used
- false
- fi
+ mkdir git-dir-wt-2.git &&
+ test_must_fail env \
+ GIT_WORK_TREE="$(pwd)" \
+ GIT_DIR=git-dir-wt-2.git \
+ git --bare init
'
test_expect_success 'reinit' '
(
- sane_unset GIT_CONFIG GIT_WORK_TREE GIT_CONFIG &&
-
mkdir again &&
cd again &&
git init >out1 2>err1 &&
@@ -200,35 +153,22 @@ test_expect_success 'reinit' '
test_expect_success 'init with --template' '
mkdir template-source &&
echo content >template-source/file &&
- (
- mkdir template-custom &&
- cd template-custom &&
- git init --template=../template-source
- ) &&
+ git init --template=../template-source template-custom &&
test_cmp template-source/file template-custom/.git/file
'
test_expect_success 'init with --template (blank)' '
- (
- mkdir template-plain &&
- cd template-plain &&
- git init
- ) &&
- test -f template-plain/.git/info/exclude &&
- (
- mkdir template-blank &&
- cd template-blank &&
- git init --template=
- ) &&
- ! test -f template-blank/.git/info/exclude
+ git init template-plain &&
+ test_path_is_file template-plain/.git/info/exclude &&
+ git init --template= template-blank &&
+ test_path_is_missing template-blank/.git/info/exclude
'
test_expect_success 'init with init.templatedir set' '
mkdir templatedir-source &&
echo Content >templatedir-source/file &&
+ test_config_global init.templatedir "${HOME}/templatedir-source" &&
(
- test_config="${HOME}/.gitconfig" &&
- git config -f "$test_config" init.templatedir "${HOME}/templatedir-source" &&
mkdir templatedir-set &&
cd templatedir-set &&
sane_unset GIT_TEMPLATE_DIR &&
@@ -240,78 +180,55 @@ test_expect_success 'init with init.templatedir set' '
'
test_expect_success 'init --bare/--shared overrides system/global config' '
- (
- test_config="$HOME"/.gitconfig &&
- git config -f "$test_config" core.bare false &&
- git config -f "$test_config" core.sharedRepository 0640 &&
- mkdir init-bare-shared-override &&
- cd init-bare-shared-override &&
- git init --bare --shared=0666
- ) &&
+ test_config_global core.bare false &&
+ test_config_global core.sharedRepository 0640 &&
+ git init --bare --shared=0666 init-bare-shared-override &&
check_config init-bare-shared-override true unset &&
test x0666 = \
x`git config -f init-bare-shared-override/config core.sharedRepository`
'
test_expect_success 'init honors global core.sharedRepository' '
- (
- test_config="$HOME"/.gitconfig &&
- git config -f "$test_config" core.sharedRepository 0666 &&
- mkdir shared-honor-global &&
- cd shared-honor-global &&
- git init
- ) &&
+ test_config_global core.sharedRepository 0666 &&
+ git init shared-honor-global &&
test x0666 = \
x`git config -f shared-honor-global/.git/config core.sharedRepository`
'
test_expect_success 'init rejects insanely long --template' '
- (
- insane=$(printf "x%09999dx" 1) &&
- mkdir test &&
- cd test &&
- test_must_fail git init --template=$insane
- )
+ test_must_fail git init --template=$(printf "x%09999dx" 1) test
'
test_expect_success 'init creates a new directory' '
rm -fr newdir &&
- (
- git init newdir &&
- test -d newdir/.git/refs
- )
+ git init newdir &&
+ test_path_is_dir newdir/.git/refs
'
test_expect_success 'init creates a new bare directory' '
rm -fr newdir &&
- (
- git init --bare newdir &&
- test -d newdir/refs
- )
+ git init --bare newdir &&
+ test_path_is_dir newdir/refs
'
test_expect_success 'init recreates a directory' '
rm -fr newdir &&
- (
- mkdir newdir &&
- git init newdir &&
- test -d newdir/.git/refs
- )
+ mkdir newdir &&
+ git init newdir &&
+ test_path_is_dir newdir/.git/refs
'
test_expect_success 'init recreates a new bare directory' '
rm -fr newdir &&
- (
- mkdir newdir &&
- git init --bare newdir &&
- test -d newdir/refs
- )
+ mkdir newdir &&
+ git init --bare newdir &&
+ test_path_is_dir newdir/refs
'
test_expect_success 'init creates a new deep directory' '
rm -fr newdir &&
git init newdir/a/b/c &&
- test -d newdir/a/b/c/.git/refs
+ test_path_is_dir newdir/a/b/c/.git/refs
'
test_expect_success POSIXPERM 'init creates a new deep directory (umask vs. shared)' '
@@ -321,7 +238,7 @@ test_expect_success POSIXPERM 'init creates a new deep directory (umask vs. shar
# the repository itself should follow "shared"
umask 002 &&
git init --bare --shared=0660 newdir/a/b/c &&
- test -d newdir/a/b/c/refs &&
+ test_path_is_dir newdir/a/b/c/refs &&
ls -ld newdir/a newdir/a/b > lsab.out &&
! grep -v "^drwxrw[sx]r-x" lsab.out &&
ls -ld newdir/a/b/c > lsc.out &&
@@ -331,44 +248,38 @@ test_expect_success POSIXPERM 'init creates a new deep directory (umask vs. shar
test_expect_success 'init notices EEXIST (1)' '
rm -fr newdir &&
- (
- >newdir &&
- test_must_fail git init newdir &&
- test -f newdir
- )
+ >newdir &&
+ test_must_fail git init newdir &&
+ test_path_is_file newdir
'
test_expect_success 'init notices EEXIST (2)' '
rm -fr newdir &&
- (
- mkdir newdir &&
- >newdir/a
- test_must_fail git init newdir/a/b &&
- test -f newdir/a
- )
+ mkdir newdir &&
+ >newdir/a &&
+ test_must_fail git init newdir/a/b &&
+ test_path_is_file newdir/a
'
test_expect_success POSIXPERM,SANITY 'init notices EPERM' '
rm -fr newdir &&
- (
- mkdir newdir &&
- chmod -w newdir &&
- test_must_fail git init newdir/a/b
- )
+ mkdir newdir &&
+ chmod -w newdir &&
+ test_must_fail git init newdir/a/b
'
test_expect_success 'init creates a new bare directory with global --bare' '
rm -rf newdir &&
git --bare init newdir &&
- test -d newdir/refs
+ test_path_is_dir newdir/refs
'
test_expect_success 'init prefers command line to GIT_DIR' '
rm -rf newdir &&
mkdir otherdir &&
GIT_DIR=otherdir git --bare init newdir &&
- test -d newdir/refs &&
- ! test -d otherdir/refs
+ test_path_is_dir newdir/refs &&
+ test_path_is_missing otherdir/refs
'
test_expect_success 'init with separate gitdir' '
@@ -376,7 +287,7 @@ test_expect_success 'init with separate gitdir' '
git init --separate-git-dir realgitdir newdir &&
echo "gitdir: `pwd`/realgitdir" >expected &&
test_cmp expected newdir/.git &&
- test -d realgitdir/refs
+ test_path_is_dir realgitdir/refs
'
test_expect_success 're-init on .git file' '
@@ -390,8 +301,8 @@ test_expect_success 're-init to update git link' '
) &&
echo "gitdir: `pwd`/surrealgitdir" >expected &&
test_cmp expected newdir/.git &&
- test -d surrealgitdir/refs &&
- ! test -d realgitdir/refs
+ test_path_is_dir surrealgitdir/refs &&
+ test_path_is_missing realgitdir/refs
'
test_expect_success 're-init to move gitdir' '
@@ -403,7 +314,7 @@ test_expect_success 're-init to move gitdir' '
) &&
echo "gitdir: `pwd`/realgitdir" >expected &&
test_cmp expected newdir/.git &&
- test -d realgitdir/refs
+ test_path_is_dir realgitdir/refs
'
test_expect_success SYMLINKS 're-init to move gitdir symlink' '
@@ -417,8 +328,8 @@ test_expect_success SYMLINKS 're-init to move gitdir symlink' '
) &&
echo "gitdir: `pwd`/realgitdir" >expected &&
test_cmp expected newdir/.git &&
- test -d realgitdir/refs &&
- ! test -d newdir/here
+ test_cmp expected newdir/here &&
+ test_path_is_dir realgitdir/refs
'
test_done
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh
index b9d79476e2..f0fbb42554 100755
--- a/t/t0003-attributes.sh
+++ b/t/t0003-attributes.sh
@@ -243,40 +243,58 @@ EOF
test_line_count = 0 err
'
+test_expect_success 'using --git-dir and --work-tree' '
+ mkdir unreal real &&
+ git init real &&
+ echo "file test=in-real" >real/.gitattributes &&
+ (
+ cd unreal &&
+ attr_check file in-real "--git-dir ../real/.git --work-tree ../real"
+ )
+'
+
test_expect_success 'setup bare' '
- git clone --bare . bare.git &&
- cd bare.git
+ git clone --bare . bare.git
'
test_expect_success 'bare repository: check that .gitattribute is ignored' '
(
- echo "f test=f"
- echo "a/i test=a/i"
- ) >.gitattributes &&
- attr_check f unspecified &&
- attr_check a/f unspecified &&
- attr_check a/c/f unspecified &&
- attr_check a/i unspecified &&
- attr_check subdir/a/i unspecified
+ cd bare.git &&
+ (
+ echo "f test=f"
+ echo "a/i test=a/i"
+ ) >.gitattributes &&
+ attr_check f unspecified &&
+ attr_check a/f unspecified &&
+ attr_check a/c/f unspecified &&
+ attr_check a/i unspecified &&
+ attr_check subdir/a/i unspecified
+ )
'
test_expect_success 'bare repository: check that --cached honors index' '
- GIT_INDEX_FILE=../.git/index \
- git check-attr --cached --stdin --all <../stdin-all |
- sort >actual &&
- test_cmp ../specified-all actual
+ (
+ cd bare.git &&
+ GIT_INDEX_FILE=../.git/index \
+ git check-attr --cached --stdin --all <../stdin-all |
+ sort >actual &&
+ test_cmp ../specified-all actual
+ )
'
test_expect_success 'bare repository: test info/attributes' '
(
- echo "f test=f"
- echo "a/i test=a/i"
- ) >info/attributes &&
- attr_check f f &&
- attr_check a/f f &&
- attr_check a/c/f f &&
- attr_check a/i a/i &&
- attr_check subdir/a/i unspecified
+ cd bare.git &&
+ (
+ echo "f test=f"
+ echo "a/i test=a/i"
+ ) >info/attributes &&
+ attr_check f f &&
+ attr_check a/f f &&
+ attr_check a/c/f f &&
+ attr_check a/i a/i &&
+ attr_check subdir/a/i unspecified
+ )
'
test_done
diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh
index b4d98e602f..63beb99828 100755
--- a/t/t0008-ignores.sh
+++ b/t/t0008-ignores.sh
@@ -775,4 +775,35 @@ test_expect_success PIPE 'streaming support for --stdin' '
echo "$response" | grep "^:: two"
'
+############################################################################
+#
+# test whitespace handling
+
+test_expect_success 'trailing whitespace is ignored' '
+ mkdir whitespace &&
+ >whitespace/trailing &&
+ >whitespace/untracked &&
+ echo "whitespace/trailing " >ignore &&
+ cat >expect <<EOF &&
+whitespace/untracked
+EOF
+ : >err.expect &&
+ git ls-files -o -X ignore whitespace >actual 2>err &&
+ test_cmp expect actual &&
+ test_cmp err.expect err
+'
+
+test_expect_success !MINGW 'quoting allows trailing whitespace' '
+ rm -rf whitespace &&
+ mkdir whitespace &&
+ >"whitespace/trailing " &&
+ >whitespace/untracked &&
+ echo "whitespace/trailing\\ \\ " >ignore &&
+ echo whitespace/untracked >expect &&
+ : >err.expect &&
+ git ls-files -o -X ignore whitespace >actual 2>err &&
+ test_cmp expect actual &&
+ test_cmp err.expect err
+'
+
test_done
diff --git a/t/t1020-subdirectory.sh b/t/t1020-subdirectory.sh
index 1e2945ec7e..6902320e81 100755
--- a/t/t1020-subdirectory.sh
+++ b/t/t1020-subdirectory.sh
@@ -148,7 +148,7 @@ test_expect_success 'GIT_PREFIX for built-ins' '
(
cd dir &&
printf "change" >two &&
- env GIT_EXTERNAL_DIFF=./diff git diff >../actual
+ GIT_EXTERNAL_DIFF=./diff git diff >../actual
git checkout -- two
) &&
test_cmp expect actual
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index 967359344d..58cd5435be 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -461,7 +461,7 @@ test_expect_success 'new variable inserts into proper section' '
test_cmp expect .git/config
'
-test_expect_success 'alternative GIT_CONFIG (non-existing file should fail)' '
+test_expect_success 'alternative --file (non-existing file should fail)' '
test_must_fail git config --file non-existing-config -l
'
@@ -475,15 +475,28 @@ ein.bahn=strasse
EOF
test_expect_success 'alternative GIT_CONFIG' '
- GIT_CONFIG=other-config git config -l >output &&
+ GIT_CONFIG=other-config git config --list >output &&
test_cmp expect output
'
test_expect_success 'alternative GIT_CONFIG (--file)' '
- git config --file other-config -l > output &&
+ git config --file other-config --list >output &&
test_cmp expect output
'
+test_expect_success 'alternative GIT_CONFIG (--file=-)' '
+ git config --file - --list <other-config >output &&
+ test_cmp expect output
+'
+
+test_expect_success 'setting a value in stdin is an error' '
+ test_must_fail git config --file - some.value foo
+'
+
+test_expect_success 'editing stdin is an error' '
+ test_must_fail git config --file - --edit
+'
+
test_expect_success 'refer config from subdirectory' '
mkdir x &&
(
@@ -495,10 +508,10 @@ test_expect_success 'refer config from subdirectory' '
'
-test_expect_success 'refer config from subdirectory via GIT_CONFIG' '
+test_expect_success 'refer config from subdirectory via --file' '
(
cd x &&
- GIT_CONFIG=../other-config git config --get ein.bahn >actual &&
+ git config --file=../other-config --get ein.bahn >actual &&
test_cmp expect actual
)
'
@@ -510,8 +523,8 @@ cat > expect << EOF
park = ausweis
EOF
-test_expect_success '--set in alternative GIT_CONFIG' '
- GIT_CONFIG=other-config git config anwohner.park ausweis &&
+test_expect_success '--set in alternative file' '
+ git config --file=other-config anwohner.park ausweis &&
test_cmp expect other-config
'
@@ -942,11 +955,11 @@ test_expect_success 'inner whitespace kept verbatim' '
test_expect_success SYMLINKS 'symlinked configuration' '
ln -s notyet myconfig &&
- GIT_CONFIG=myconfig git config test.frotz nitfol &&
+ git config --file=myconfig test.frotz nitfol &&
test -h myconfig &&
test -f notyet &&
- test "z$(GIT_CONFIG=notyet git config test.frotz)" = znitfol &&
- GIT_CONFIG=myconfig git config test.xyzzy rezrov &&
+ test "z$(git config --file=notyet test.frotz)" = znitfol &&
+ git config --file=myconfig test.xyzzy rezrov &&
test -h myconfig &&
test -f notyet &&
cat >expect <<-\EOF &&
@@ -954,31 +967,22 @@ test_expect_success SYMLINKS 'symlinked configuration' '
rezrov
EOF
{
- GIT_CONFIG=notyet git config test.frotz &&
- GIT_CONFIG=notyet git config test.xyzzy
+ git config --file=notyet test.frotz &&
+ git config --file=notyet test.xyzzy
} >actual &&
test_cmp expect actual
'
test_expect_success 'nonexistent configuration' '
- (
- GIT_CONFIG=doesnotexist &&
- export GIT_CONFIG &&
- test_must_fail git config --list &&
- test_must_fail git config test.xyzzy
- )
+ test_must_fail git config --file=doesnotexist --list &&
+ test_must_fail git config --file=doesnotexist test.xyzzy
'
test_expect_success SYMLINKS 'symlink to nonexistent configuration' '
ln -s doesnotexist linktonada &&
ln -s linktonada linktolinktonada &&
- (
- GIT_CONFIG=linktonada &&
- export GIT_CONFIG &&
- test_must_fail git config --list &&
- GIT_CONFIG=linktolinktonada &&
- test_must_fail git config --list
- )
+ test_must_fail git config --file=linktonada --list &&
+ test_must_fail git config --file=linktolinktonada --list
'
test_expect_success 'check split_cmdline return' "
diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
index 0e47662406..0d9388afc4 100755
--- a/t/t1302-repo-version.sh
+++ b/t/t1302-repo-version.sh
@@ -19,7 +19,7 @@ test_expect_success 'setup' '
test_create_repo "test" &&
test_create_repo "test2" &&
- GIT_CONFIG=test2/.git/config git config core.repositoryformatversion 99
+ git config --file=test2/.git/config core.repositoryformatversion 99
'
test_expect_success 'gitdir selection on normal repos' '
diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh
index a70707620f..9ba2ba11c3 100755
--- a/t/t1305-config-include.sh
+++ b/t/t1305-config-include.sh
@@ -113,7 +113,7 @@ test_expect_success 'missing include files are ignored' '
test_expect_success 'absolute includes from command line work' '
echo "[test]one = 1" >one &&
echo 1 >expect &&
- git -c include.path="$PWD/one" config test.one >actual &&
+ git -c include.path="$(pwd)/one" config test.one >actual &&
test_cmp expect actual
'
@@ -122,6 +122,36 @@ test_expect_success 'relative includes from command line fail' '
test_must_fail git -c include.path=one config test.one
'
+test_expect_success 'absolute includes from blobs work' '
+ echo "[test]one = 1" >one &&
+ echo "[include]path=$(pwd)/one" >blob &&
+ blob=$(git hash-object -w blob) &&
+ echo 1 >expect &&
+ git config --blob=$blob test.one >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'relative includes from blobs fail' '
+ echo "[test]one = 1" >one &&
+ echo "[include]path=one" >blob &&
+ blob=$(git hash-object -w blob) &&
+ test_must_fail git config --blob=$blob test.one
+'
+
+test_expect_success 'absolute includes from stdin work' '
+ echo "[test]one = 1" >one &&
+ echo 1 >expect &&
+ echo "[include]path=\"$(pwd)/one\"" |
+ git config --file - test.one >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'relative includes from stdin line fail' '
+ echo "[test]one = 1" >one &&
+ echo "[include]path=one" |
+ test_must_fail git config --file - test.one
+'
+
test_expect_success 'include cycles are detected' '
cat >.gitconfig <<-\EOF &&
[test]value = gitconfig
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index d730734fde..8c739c9613 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -142,6 +142,20 @@ test_expect_success '> in name is reported' '
grep "error in commit $new" out
'
+# date is 2^64 + 1
+test_expect_success 'integer overflow in timestamps is reported' '
+ git cat-file commit HEAD >basis &&
+ sed "s/^\\(author .*>\\) [0-9]*/\\1 18446744073709551617/" \
+ <basis >bad-timestamp &&
+ new=$(git hash-object -t commit -w --stdin <bad-timestamp) &&
+ test_when_finished "remove_object $new" &&
+ git update-ref refs/heads/bogus "$new" &&
+ test_when_finished "git update-ref -d refs/heads/bogus" &&
+ git fsck 2>out &&
+ cat out &&
+ grep "error in commit $new.*integer overflow" out
+'
+
test_expect_success 'tag pointing to nonexistent' '
cat >invalid-tag <<-\EOF &&
object ffffffffffffffffffffffffffffffffffffffff
diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh
index 83b1300cef..922423e7d0 100755
--- a/t/t1502-rev-parse-parseopt.sh
+++ b/t/t1502-rev-parse-parseopt.sh
@@ -3,44 +3,64 @@
test_description='test git rev-parse --parseopt'
. ./test-lib.sh
-cat > expect <<\END_EXPECT
-cat <<\EOF
-usage: some-command [options] <args>...
-
- some-command does foo and bar!
-
- -h, --help show the help
- --foo some nifty option --foo
- --bar ... some cool option --bar with an argument
- -b, --baz a short and long option
-
-An option group Header
- -C[...] option C with an optional argument
- -d, --data[=...] short and long option with an optional argument
-
-Extras
- --extra1 line above used to cause a segfault but no longer does
-
-EOF
+sed -e 's/^|//' >expect <<\END_EXPECT
+|cat <<\EOF
+|usage: some-command [options] <args>...
+|
+| some-command does foo and bar!
+|
+| -h, --help show the help
+| --foo some nifty option --foo
+| --bar ... some cool option --bar with an argument
+| -b, --baz a short and long option
+|
+|An option group Header
+| -C[...] option C with an optional argument
+| -d, --data[=...] short and long option with an optional argument
+|
+|Argument hints
+| -b <arg> short option required argument
+| --bar2 <arg> long option required argument
+| -e, --fuz <with-space>
+| short and long option required argument
+| -s[<some>] short option optional argument
+| --long[=<data>] long option optional argument
+| -g, --fluf[=<path>] short and long option optional argument
+| --longest <very-long-argument-hint>
+| a very long argument hint
+|
+|Extras
+| --extra1 line above used to cause a segfault but no longer does
+|
+|EOF
END_EXPECT
-cat > optionspec << EOF
-some-command [options] <args>...
-
-some-command does foo and bar!
---
-h,help show the help
-
-foo some nifty option --foo
-bar= some cool option --bar with an argument
-b,baz a short and long option
-
- An option group Header
-C? option C with an optional argument
-d,data? short and long option with an optional argument
-
-Extras
-extra1 line above used to cause a segfault but no longer does
+sed -e 's/^|//' >optionspec <<\EOF
+|some-command [options] <args>...
+|
+|some-command does foo and bar!
+|--
+|h,help show the help
+|
+|foo some nifty option --foo
+|bar= some cool option --bar with an argument
+|b,baz a short and long option
+|
+| An option group Header
+|C? option C with an optional argument
+|d,data? short and long option with an optional argument
+|
+| Argument hints
+|b=arg short option required argument
+|bar2=arg long option required argument
+|e,fuz=with-space short and long option required argument
+|s?some short option optional argument
+|long?data long option optional argument
+|g,fluf?path short and long option optional argument
+|longest=very-long-argument-hint a very long argument hint
+|
+|Extras
+|extra1 line above used to cause a segfault but no longer does
EOF
test_expect_success 'test --parseopt help output' '
diff --git a/t/t1510-repo-setup.sh b/t/t1510-repo-setup.sh
index cf2ee7885a..e1b2a99f10 100755
--- a/t/t1510-repo-setup.sh
+++ b/t/t1510-repo-setup.sh
@@ -777,9 +777,7 @@ test_expect_success '#30: core.worktree and core.bare conflict (gitfile version)
setup_repo 30 "$here/30" gitfile true &&
(
cd 30 &&
- GIT_DIR=.git &&
- export GIT_DIR &&
- test_must_fail git symbolic-ref HEAD 2>result
+ test_must_fail env GIT_DIR=.git git symbolic-ref HEAD 2>result
) &&
grep "core.bare and core.worktree" 30/result
'
diff --git a/t/t1600-index.sh b/t/t1600-index.sh
new file mode 100755
index 0000000000..079d241145
--- /dev/null
+++ b/t/t1600-index.sh
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+test_description='index file specific tests'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo 1 >a
+'
+
+test_expect_success 'bogus GIT_INDEX_VERSION issues warning' '
+ (
+ rm -f .git/index &&
+ GIT_INDEX_VERSION=2bogus &&
+ export GIT_INDEX_VERSION &&
+ git add a 2>&1 | sed "s/[0-9]//" >actual.err &&
+ sed -e "s/ Z$/ /" <<-\EOF >expect.err &&
+ warning: GIT_INDEX_VERSION set, but the value is invalid.
+ Using version Z
+ EOF
+ test_i18ncmp expect.err actual.err
+ )
+'
+
+test_expect_success 'out of bounds GIT_INDEX_VERSION issues warning' '
+ (
+ rm -f .git/index &&
+ GIT_INDEX_VERSION=1 &&
+ export GIT_INDEX_VERSION &&
+ git add a 2>&1 | sed "s/[0-9]//" >actual.err &&
+ sed -e "s/ Z$/ /" <<-\EOF >expect.err &&
+ warning: GIT_INDEX_VERSION set, but the value is invalid.
+ Using version Z
+ EOF
+ test_i18ncmp expect.err actual.err
+ )
+'
+
+test_expect_success 'no warning with bogus GIT_INDEX_VERSION and existing index' '
+ (
+ GIT_INDEX_VERSION=1 &&
+ export GIT_INDEX_VERSION &&
+ git add a 2>actual.err &&
+ >expect.err &&
+ test_i18ncmp expect.err actual.err
+ )
+'
+
+test_expect_success 'out of bounds index.version issues warning' '
+ (
+ sane_unset GIT_INDEX_VERSION &&
+ rm -f .git/index &&
+ git config --add index.version 1 &&
+ git add a 2>&1 | sed "s/[0-9]//" >actual.err &&
+ sed -e "s/ Z$/ /" <<-\EOF >expect.err &&
+ warning: index.version set, but the value is invalid.
+ Using version Z
+ EOF
+ test_i18ncmp expect.err actual.err
+ )
+'
+
+test_expect_success 'GIT_INDEX_VERSION takes precedence over config' '
+ (
+ rm -f .git/index &&
+ GIT_INDEX_VERSION=4 &&
+ export GIT_INDEX_VERSION &&
+ git config --add index.version 2 &&
+ git add a 2>&1 &&
+ echo 4 >expect &&
+ test-index-version <.git/index >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_done
diff --git a/t/t2104-update-index-skip-worktree.sh b/t/t2104-update-index-skip-worktree.sh
index 1d0879be06..29c1fb10ca 100755
--- a/t/t2104-update-index-skip-worktree.sh
+++ b/t/t2104-update-index-skip-worktree.sh
@@ -7,6 +7,8 @@ test_description='skip-worktree bit test'
. ./test-lib.sh
+test_set_index_version 3
+
cat >expect.full <<EOF
H 1
H 2
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 38446a0e87..ef509df351 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -14,19 +14,6 @@ match() {
! test-wildmatch wildmatch '$3' '$4'
"
fi
- if [ $2 = 1 ]; then
- test_expect_success "fnmatch: match '$3' '$4'" "
- test-wildmatch fnmatch '$3' '$4'
- "
- elif [ $2 = 0 ]; then
- test_expect_success "fnmatch: no match '$3' '$4'" "
- ! test-wildmatch fnmatch '$3' '$4'
- "
-# else
-# test_expect_success BROKEN_FNMATCH "fnmatch: '$3' '$4'" "
-# ! test-wildmatch fnmatch '$3' '$4'
-# "
- fi
}
imatch() {
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index fcdb867748..ac31b711f2 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -507,6 +507,16 @@ EOF
test_cmp expected actual
'
+test_expect_success '--set-upstream-to notices an error to set branch as own upstream' '
+ git branch --set-upstream-to refs/heads/my13 my13 2>actual &&
+ cat >expected <<-\EOF &&
+ warning: Not setting branch my13 as its own upstream.
+ EOF
+ test_expect_code 1 git config branch.my13.remote &&
+ test_expect_code 1 git config branch.my13.merge &&
+ test_i18ncmp expected actual
+'
+
# Keep this test last, as it changes the current branch
cat >expect <<EOF
$_z40 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 branch: Created from master
@@ -849,11 +859,7 @@ test_expect_success 'detect typo in branch name when using --edit-description' '
write_script editor <<-\EOF &&
echo "New contents" >"$1"
EOF
- (
- EDITOR=./editor &&
- export EDITOR &&
- test_must_fail git branch --edit-description no-such-branch
- )
+ test_must_fail env EDITOR=./editor git branch --edit-description no-such-branch
'
test_expect_success 'refuse --edit-description on unborn branch for now' '
@@ -861,11 +867,7 @@ test_expect_success 'refuse --edit-description on unborn branch for now' '
echo "New contents" >"$1"
EOF
git checkout --orphan unborn &&
- (
- EDITOR=./editor &&
- export EDITOR &&
- test_must_fail git branch --edit-description
- )
+ test_must_fail env EDITOR=./editor git branch --edit-description
'
test_expect_success '--merged catches invalid object names' '
diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh
index 16de05aff9..cfd67ff3df 100755
--- a/t/t3301-notes.sh
+++ b/t/t3301-notes.sh
@@ -17,7 +17,7 @@ GIT_EDITOR=./fake_editor.sh
export GIT_EDITOR
test_expect_success 'cannot annotate non-existing HEAD' '
- (MSG=3 && export MSG && test_must_fail git notes add)
+ test_must_fail env MSG=3 git notes add
'
test_expect_success setup '
@@ -32,22 +32,16 @@ test_expect_success setup '
'
test_expect_success 'need valid notes ref' '
- (MSG=1 GIT_NOTES_REF=/ && export MSG GIT_NOTES_REF &&
- test_must_fail git notes add) &&
- (MSG=2 GIT_NOTES_REF=/ && export MSG GIT_NOTES_REF &&
- test_must_fail git notes show)
+ test_must_fail env MSG=1 GIT_NOTES_REF=/ git notes show &&
+ test_must_fail env MSG=2 GIT_NOTES_REF=/ git notes show
'
test_expect_success 'refusing to add notes in refs/heads/' '
- (MSG=1 GIT_NOTES_REF=refs/heads/bogus &&
- export MSG GIT_NOTES_REF &&
- test_must_fail git notes add)
+ test_must_fail env MSG=1 GIT_NOTES_REF=refs/heads/bogus git notes add
'
test_expect_success 'refusing to edit notes in refs/remotes/' '
- (MSG=1 GIT_NOTES_REF=refs/remotes/bogus &&
- export MSG GIT_NOTES_REF &&
- test_must_fail git notes edit)
+ test_must_fail env MSG=1 GIT_NOTES_REF=refs/heads/bogus git notes edit
'
# 1 indicates caught gracefully by die, 128 means git-show barked
@@ -812,6 +806,33 @@ test_expect_success 'create note from non-existing note with "git notes add -C"
test_must_fail git notes list HEAD
'
+test_expect_success 'create note from non-blob with "git notes add -C" fails' '
+ commit=$(git rev-parse --verify HEAD) &&
+ tree=$(git rev-parse --verify HEAD:) &&
+ test_must_fail git notes add -C $commit &&
+ test_must_fail git notes add -C $tree &&
+ test_must_fail git notes list HEAD
+'
+
+cat > expect << EOF
+commit 80d796defacd5db327b7a4e50099663902fbdc5c
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:20:13 2005 -0700
+
+ 8th
+
+Notes (other):
+ This is a blob object
+EOF
+
+test_expect_success 'create note from blob with "git notes add -C" reuses blob id' '
+ blob=$(echo "This is a blob object" | git hash-object -w --stdin) &&
+ git notes add -C $blob &&
+ git log -1 > actual &&
+ test_cmp expect actual &&
+ test "$(git notes list HEAD)" = "$blob"
+'
+
cat > expect << EOF
commit 016e982bad97eacdbda0fcbd7ce5b0ba87c81f1b
Author: A U Thor <author@example.com>
@@ -838,11 +859,7 @@ test_expect_success 'create note from non-existing note with "git notes add -c"
git add a10 &&
test_tick &&
git commit -m 10th &&
- (
- MSG="yet another note" &&
- export MSG &&
- test_must_fail git notes add -c deadbeef
- ) &&
+ test_must_fail env MSG="yet another note" git notes add -c deadbeef &&
test_must_fail git notes list HEAD
'
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index 6d94b1fcd9..80e0a951ea 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -88,6 +88,23 @@ test_expect_success 'rebase from ambiguous branch name' '
git rebase master
'
+test_expect_success 'rebase off of the previous branch using "-"' '
+ git checkout master &&
+ git checkout HEAD^ &&
+ git rebase @{-1} >expect.messages &&
+ git merge-base master HEAD >expect.forkpoint &&
+
+ git checkout master &&
+ git checkout HEAD^ &&
+ git rebase - >actual.messages &&
+ git merge-base master HEAD >actual.forkpoint &&
+
+ test_cmp expect.forkpoint actual.forkpoint &&
+ # the next one is dubious---we may want to say "-",
+ # instead of @{-1}, in the message
+ test_i18ncmp expect.messages actual.messages
+'
+
test_expect_success 'rebase a single mode change' '
git checkout master &&
git branch -D topic &&
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 50e22b1cad..c0023a5b4f 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -102,12 +102,8 @@ test_expect_success 'rebase -i with the exec command runs from tree root' '
test_expect_success 'rebase -i with the exec command checks tree cleanness' '
git checkout master &&
- (
set_fake_editor &&
- FAKE_LINES="exec_echo_foo_>file1 1" &&
- export FAKE_LINES &&
- test_must_fail git rebase -i HEAD^
- ) &&
+ test_must_fail env FAKE_LINES="exec_echo_foo_>file1 1" git rebase -i HEAD^ &&
test_cmp_rev master^ HEAD &&
git reset --hard &&
git rebase --continue
@@ -116,12 +112,9 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '
test_expect_success 'rebase -i with exec of inexistent command' '
git checkout master &&
test_when_finished "git rebase --abort" &&
- (
set_fake_editor &&
- FAKE_LINES="exec_this-command-does-not-exist 1" &&
- export FAKE_LINES &&
- test_must_fail git rebase -i HEAD^ >actual 2>&1
- ) &&
+ test_must_fail env FAKE_LINES="exec_this-command-does-not-exist 1" \
+ git rebase -i HEAD^ >actual 2>&1 &&
! grep "Maybe git-rebase is broken" actual
'
@@ -375,11 +368,7 @@ test_expect_success 'commit message used after conflict' '
git checkout -b conflict-fixup conflict-branch &&
base=$(git rev-parse HEAD~4) &&
set_fake_editor &&
- (
- FAKE_LINES="1 fixup 3 fixup 4" &&
- export FAKE_LINES &&
- test_must_fail git rebase -i $base
- ) &&
+ test_must_fail env FAKE_LINES="1 fixup 3 fixup 4" git rebase -i $base &&
echo three > conflict &&
git add conflict &&
FAKE_COMMIT_AMEND="ONCE" EXPECT_HEADER_COUNT=2 \
@@ -394,11 +383,7 @@ test_expect_success 'commit message retained after conflict' '
git checkout -b conflict-squash conflict-branch &&
base=$(git rev-parse HEAD~4) &&
set_fake_editor &&
- (
- FAKE_LINES="1 fixup 3 squash 4" &&
- export FAKE_LINES &&
- test_must_fail git rebase -i $base
- ) &&
+ test_must_fail env FAKE_LINES="1 fixup 3 squash 4" git rebase -i $base &&
echo three > conflict &&
git add conflict &&
FAKE_COMMIT_AMEND="TWICE" EXPECT_HEADER_COUNT=2 \
@@ -469,11 +454,7 @@ test_expect_success 'interrupted squash works as expected' '
git checkout -b interrupted-squash conflict-branch &&
one=$(git rev-parse HEAD~3) &&
set_fake_editor &&
- (
- FAKE_LINES="1 squash 3 2" &&
- export FAKE_LINES &&
- test_must_fail git rebase -i HEAD~3
- ) &&
+ test_must_fail env FAKE_LINES="1 squash 3 2" git rebase -i HEAD~3 &&
(echo one; echo two; echo four) > conflict &&
git add conflict &&
test_must_fail git rebase --continue &&
@@ -487,11 +468,7 @@ test_expect_success 'interrupted squash works as expected (case 2)' '
git checkout -b interrupted-squash2 conflict-branch &&
one=$(git rev-parse HEAD~3) &&
set_fake_editor &&
- (
- FAKE_LINES="3 squash 1 2" &&
- export FAKE_LINES &&
- test_must_fail git rebase -i HEAD~3
- ) &&
+ test_must_fail env FAKE_LINES="3 squash 1 2" git rebase -i HEAD~3 &&
(echo one; echo four) > conflict &&
git add conflict &&
test_must_fail git rebase --continue &&
@@ -528,11 +505,7 @@ test_expect_success 'aborted --continue does not squash commits after "edit"' '
FAKE_LINES="edit 1" git rebase -i HEAD^ &&
echo "edited again" > file7 &&
git add file7 &&
- (
- FAKE_COMMIT_MESSAGE=" " &&
- export FAKE_COMMIT_MESSAGE &&
- test_must_fail git rebase --continue
- ) &&
+ test_must_fail env FAKE_COMMIT_MESSAGE=" " git rebase --continue &&
test $old = $(git rev-parse HEAD) &&
git rebase --abort
'
@@ -547,11 +520,7 @@ test_expect_success 'auto-amend only edited commits after "edit"' '
echo "and again" > file7 &&
git add file7 &&
test_tick &&
- (
- FAKE_COMMIT_MESSAGE="and again" &&
- export FAKE_COMMIT_MESSAGE &&
- test_must_fail git rebase --continue
- ) &&
+ test_must_fail env FAKE_COMMIT_MESSAGE="and again" git rebase --continue &&
git rebase --abort
'
@@ -559,11 +528,7 @@ test_expect_success 'clean error after failed "exec"' '
test_tick &&
test_when_finished "git rebase --abort || :" &&
set_fake_editor &&
- (
- FAKE_LINES="1 exec_false" &&
- export FAKE_LINES &&
- test_must_fail git rebase -i HEAD^
- ) &&
+ test_must_fail env FAKE_LINES="1 exec_false" git rebase -i HEAD^ &&
echo "edited again" > file7 &&
git add file7 &&
test_must_fail git rebase --continue 2>error &&
@@ -947,12 +912,8 @@ test_expect_success 'rebase -i --root retain root commit author and message' '
test_expect_success 'rebase -i --root temporary sentinel commit' '
git checkout B &&
- (
- set_fake_editor &&
- FAKE_LINES="2" &&
- export FAKE_LINES &&
- test_must_fail git rebase -i --root
- ) &&
+ set_fake_editor &&
+ test_must_fail env FAKE_LINES="2" git rebase -i --root &&
git cat-file commit HEAD | grep "^tree 4b825dc642cb" &&
git rebase --abort
'
@@ -1042,11 +1003,7 @@ test_expect_success 'rebase -i error on commits with \ in message' '
test_when_finished "git rebase --abort; git reset --hard $current_head; rm -f error" &&
test_commit TO-REMOVE will-conflict old-content &&
test_commit "\temp" will-conflict new-content dummy &&
- (
- EDITOR=true &&
- export EDITOR &&
- test_must_fail git rebase -i HEAD^ --onto HEAD^^ 2>error
- ) &&
+ test_must_fail env EDITOR=true git rebase -i HEAD^ --onto HEAD^^ 2>error &&
test_expect_code 1 grep " emp" error
'
diff --git a/t/t3413-rebase-hook.sh b/t/t3413-rebase-hook.sh
index 098b75507b..b6833e9a5f 100755
--- a/t/t3413-rebase-hook.sh
+++ b/t/t3413-rebase-hook.sh
@@ -118,11 +118,7 @@ test_expect_success 'pre-rebase hook stops rebase (1)' '
test_expect_success 'pre-rebase hook stops rebase (2)' '
git checkout test &&
git reset --hard side &&
- (
- EDITOR=:
- export EDITOR
- test_must_fail git rebase -i master
- ) &&
+ test_must_fail env EDITOR=: git rebase -i master &&
test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
test 0 = $(git rev-list HEAD...side | wc -l)
'
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 73194b2c3d..9c80633146 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -764,22 +764,14 @@ test_expect_success 'format-patch --signature="" suppresses signatures' '
test_expect_success TTY 'format-patch --stdout paginates' '
rm -f pager_used &&
- (
- GIT_PAGER="wc >pager_used" &&
- export GIT_PAGER &&
- test_terminal git format-patch --stdout --all
- ) &&
+ test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
test_path_is_file pager_used
'
test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
rm -f pager_used &&
- (
- GIT_PAGER="wc >pager_used" &&
- export GIT_PAGER &&
- test_terminal git --no-pager format-patch --stdout --all &&
- test_terminal git -c "pager.format-patch=false" format-patch --stdout --all
- ) &&
+ test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
+ test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
test_path_is_missing pager_used &&
test_path_is_missing .git/pager_used
'
diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
index 38a092a0da..34591c23da 100755
--- a/t/t4018-diff-funcname.sh
+++ b/t/t4018-diff-funcname.sh
@@ -7,179 +7,103 @@ test_description='Test custom diff function name patterns'
. ./test-lib.sh
-LF='
-'
-cat >Beer.java <<\EOF
-public class Beer
-{
- int special;
- public static void main(String args[])
- {
- String s=" ";
- for(int x = 99; x > 0; x--)
- {
- System.out.print(x + " bottles of beer on the wall "
- + x + " bottles of beer\n"
- + "Take one down, pass it around, " + (x - 1)
- + " bottles of beer on the wall.\n");
- }
- System.out.print("Go to the store, buy some more,\n"
- + "99 bottles of beer on the wall.\n");
- }
-}
-EOF
-sed 's/beer\\/beer,\\/' <Beer.java >Beer-correct.java
-cat >Beer.perl <<\EOT
-package Beer;
-
-use strict;
-use warnings;
-use parent qw(Exporter);
-our @EXPORT_OK = qw(round finalround);
-
-sub other; # forward declaration
-
-# hello
-
-sub round {
- my ($n) = @_;
- print "$n bottles of beer on the wall ";
- print "$n bottles of beer\n";
- print "Take one down, pass it around, ";
- $n = $n - 1;
- print "$n bottles of beer on the wall.\n";
-}
-
-sub finalround
-{
- print "Go to the store, buy some more\n";
- print "99 bottles of beer on the wall.\n");
-}
-
-sub withheredocument {
- print <<"EOF"
-decoy here-doc
-EOF
- # some lines of context
- # to pad it out
- print "hello\n";
-}
-
-__END__
-
-=head1 NAME
-
-Beer - subroutine to output fragment of a drinking song
-
-=head1 SYNOPSIS
-
- use Beer qw(round finalround);
-
- sub song {
- for (my $i = 99; $i > 0; $i--) {
- round $i;
- }
- finalround;
- }
+test_expect_success 'setup' '
+ # a non-trivial custom pattern
+ git config diff.custom1.funcname "!static
+!String
+[^ ].*s.*" &&
- song;
+ # a custom pattern which matches to end of line
+ git config diff.custom2.funcname "......Beer\$" &&
-=cut
-EOT
-sed -e '
- s/hello/goodbye/
- s/beer\\/beer,\\/
- s/more\\/more,\\/
- s/song;/song();/
-' <Beer.perl >Beer-correct.perl
+ # alternation in pattern
+ git config diff.custom3.funcname "Beer$" &&
+ git config diff.custom3.xfuncname "^[ ]*((public|static).*)$" &&
-test_expect_funcname () {
- lang=${2-java}
- test_expect_code 1 git diff --no-index -U1 \
- "Beer.$lang" "Beer-correct.$lang" >diff &&
- grep "^@@.*@@ $1" diff
-}
+ # for regexp compilation tests
+ echo A >A.java &&
+ echo B >B.java
+'
-for p in ada bibtex cpp csharp fortran html java matlab objc pascal perl php python ruby tex
+diffpatterns="
+ ada
+ bibtex
+ cpp
+ csharp
+ fortran
+ html
+ java
+ matlab
+ objc
+ pascal
+ perl
+ php
+ python
+ ruby
+ tex
+ custom1
+ custom2
+ custom3
+"
+
+for p in $diffpatterns
do
test_expect_success "builtin $p pattern compiles" '
echo "*.java diff=$p" >.gitattributes &&
test_expect_code 1 git diff --no-index \
- Beer.java Beer-correct.java 2>msg &&
- ! grep fatal msg &&
- ! grep error msg
+ A.java B.java 2>msg &&
+ ! test_i18ngrep fatal msg &&
+ ! test_i18ngrep error msg
'
test_expect_success "builtin $p wordRegex pattern compiles" '
echo "*.java diff=$p" >.gitattributes &&
test_expect_code 1 git diff --no-index --word-diff \
- Beer.java Beer-correct.java 2>msg &&
- ! grep fatal msg &&
- ! grep error msg
+ A.java B.java 2>msg &&
+ ! test_i18ngrep fatal msg &&
+ ! test_i18ngrep error msg
'
done
-test_expect_success 'default behaviour' '
- rm -f .gitattributes &&
- test_expect_funcname "public class Beer\$"
-'
-
-test_expect_success 'set up .gitattributes declaring drivers to test' '
- cat >.gitattributes <<-\EOF
- *.java diff=java
- *.perl diff=perl
- EOF
-'
-
-test_expect_success 'preset java pattern' '
- test_expect_funcname "public static void main("
-'
-
-test_expect_success 'preset perl pattern' '
- test_expect_funcname "sub round {\$" perl
-'
-
-test_expect_success 'perl pattern accepts K&R style brace placement, too' '
- test_expect_funcname "sub finalround\$" perl
-'
-
-test_expect_success 'but is not distracted by end of <<here document' '
- test_expect_funcname "sub withheredocument {\$" perl
-'
-
-test_expect_success 'perl pattern is not distracted by sub within POD' '
- test_expect_funcname "=head" perl
-'
-
-test_expect_success 'perl pattern gets full line of POD header' '
- test_expect_funcname "=head1 SYNOPSIS\$" perl
-'
-
-test_expect_success 'perl pattern is not distracted by forward declaration' '
- test_expect_funcname "package Beer;\$" perl
-'
-
-test_expect_success 'custom pattern' '
- test_config diff.java.funcname "!static
-!String
-[^ ].*s.*" &&
- test_expect_funcname "int special;\$"
-'
-
test_expect_success 'last regexp must not be negated' '
+ echo "*.java diff=java" >.gitattributes &&
test_config diff.java.funcname "!static" &&
- test_expect_code 128 git diff --no-index Beer.java Beer-correct.java 2>msg &&
- grep ": Last expression must not be negated:" msg
+ test_expect_code 128 git diff --no-index A.java B.java 2>msg &&
+ test_i18ngrep ": Last expression must not be negated:" msg
'
-test_expect_success 'pattern which matches to end of line' '
- test_config diff.java.funcname "Beer\$" &&
- test_expect_funcname "Beer\$"
+test_expect_success 'setup hunk header tests' '
+ for i in $diffpatterns
+ do
+ echo "$i-* diff=$i"
+ done > .gitattributes &&
+
+ # add all test files to the index
+ (
+ cd "$TEST_DIRECTORY"/t4018 &&
+ git --git-dir="$TRASH_DIRECTORY/.git" add .
+ ) &&
+
+ # place modified files in the worktree
+ for i in $(git ls-files)
+ do
+ sed -e "s/ChangeMe/IWasChanged/" <"$TEST_DIRECTORY/t4018/$i" >"$i" || return 1
+ done
'
-test_expect_success 'alternation in pattern' '
- test_config diff.java.funcname "Beer$" &&
- test_config diff.java.xfuncname "^[ ]*((public|static).*)$" &&
- test_expect_funcname "public static void main("
-'
+# check each individual file
+for i in $(git ls-files)
+do
+ if grep broken "$i" >/dev/null 2>&1
+ then
+ result=failure
+ else
+ result=success
+ fi
+ test_expect_$result "hunk header: $i" "
+ test_when_finished 'cat actual' && # for debugging only
+ git diff -U1 $i >actual &&
+ grep '@@ .* @@.*RIGHT' actual
+ "
+done
test_done
diff --git a/t/t4018/README b/t/t4018/README
new file mode 100644
index 0000000000..283e01cca1
--- /dev/null
+++ b/t/t4018/README
@@ -0,0 +1,18 @@
+How to write RIGHT test cases
+=============================
+
+Insert the word "ChangeMe" (exactly this form) at a distance of
+at least two lines from the line that must appear in the hunk header.
+
+The text that must appear in the hunk header must contain the word
+"right", but in all upper-case, like in the title above.
+
+To mark a test case that highlights a malfunction, insert the word
+BROKEN in all lower-case somewhere in the file.
+
+This text is a bit twisted and out of order, but it is itself a
+test case for the default hunk header pattern. Know what you are doing
+if you change it.
+
+BTW, this tests that the head line goes to the hunk header, not the line
+of equal signs.
diff --git a/t/t4018/cpp-c++-function b/t/t4018/cpp-c++-function
new file mode 100644
index 0000000000..9ee6bbef55
--- /dev/null
+++ b/t/t4018/cpp-c++-function
@@ -0,0 +1,4 @@
+Item RIGHT::DoSomething( Args with_spaces )
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-class-constructor b/t/t4018/cpp-class-constructor
new file mode 100644
index 0000000000..ec4f115c25
--- /dev/null
+++ b/t/t4018/cpp-class-constructor
@@ -0,0 +1,4 @@
+Item::Item(int RIGHT)
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-class-constructor-mem-init b/t/t4018/cpp-class-constructor-mem-init
new file mode 100644
index 0000000000..49a69f37e1
--- /dev/null
+++ b/t/t4018/cpp-class-constructor-mem-init
@@ -0,0 +1,5 @@
+Item::Item(int RIGHT) :
+ member(0)
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-class-definition b/t/t4018/cpp-class-definition
new file mode 100644
index 0000000000..11b61da3b7
--- /dev/null
+++ b/t/t4018/cpp-class-definition
@@ -0,0 +1,4 @@
+class RIGHT
+{
+ int ChangeMe;
+};
diff --git a/t/t4018/cpp-class-definition-derived b/t/t4018/cpp-class-definition-derived
new file mode 100644
index 0000000000..3b98cd09ab
--- /dev/null
+++ b/t/t4018/cpp-class-definition-derived
@@ -0,0 +1,5 @@
+class RIGHT :
+ public Baseclass
+{
+ int ChangeMe;
+};
diff --git a/t/t4018/cpp-class-destructor b/t/t4018/cpp-class-destructor
new file mode 100644
index 0000000000..5487665096
--- /dev/null
+++ b/t/t4018/cpp-class-destructor
@@ -0,0 +1,4 @@
+RIGHT::~RIGHT()
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-function-returning-global-type b/t/t4018/cpp-function-returning-global-type
new file mode 100644
index 0000000000..1084d5990e
--- /dev/null
+++ b/t/t4018/cpp-function-returning-global-type
@@ -0,0 +1,4 @@
+::Item get::it::RIGHT()
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-function-returning-nested b/t/t4018/cpp-function-returning-nested
new file mode 100644
index 0000000000..d9750aa61a
--- /dev/null
+++ b/t/t4018/cpp-function-returning-nested
@@ -0,0 +1,5 @@
+get::Item get::it::RIGHT()
+{
+ ChangeMe;
+}
+
diff --git a/t/t4018/cpp-function-returning-pointer b/t/t4018/cpp-function-returning-pointer
new file mode 100644
index 0000000000..ef15657ea8
--- /dev/null
+++ b/t/t4018/cpp-function-returning-pointer
@@ -0,0 +1,4 @@
+const char *get_it_RIGHT(char *ptr)
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-function-returning-reference b/t/t4018/cpp-function-returning-reference
new file mode 100644
index 0000000000..01b051df70
--- /dev/null
+++ b/t/t4018/cpp-function-returning-reference
@@ -0,0 +1,4 @@
+string& get::it::RIGHT(char *ptr)
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-gnu-style-function b/t/t4018/cpp-gnu-style-function
new file mode 100644
index 0000000000..08c7c7565a
--- /dev/null
+++ b/t/t4018/cpp-gnu-style-function
@@ -0,0 +1,5 @@
+const char *
+RIGHT(int arg)
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-namespace-definition b/t/t4018/cpp-namespace-definition
new file mode 100644
index 0000000000..6749980241
--- /dev/null
+++ b/t/t4018/cpp-namespace-definition
@@ -0,0 +1,4 @@
+namespace RIGHT
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-operator-definition b/t/t4018/cpp-operator-definition
new file mode 100644
index 0000000000..1acd827159
--- /dev/null
+++ b/t/t4018/cpp-operator-definition
@@ -0,0 +1,4 @@
+Value operator+(Value LEFT, Value RIGHT)
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-skip-access-specifiers b/t/t4018/cpp-skip-access-specifiers
new file mode 100644
index 0000000000..4d4a9dbb9d
--- /dev/null
+++ b/t/t4018/cpp-skip-access-specifiers
@@ -0,0 +1,8 @@
+class RIGHT : public Baseclass
+{
+public:
+protected:
+private:
+ void DoSomething();
+ int ChangeMe;
+};
diff --git a/t/t4018/cpp-skip-comment-block b/t/t4018/cpp-skip-comment-block
new file mode 100644
index 0000000000..3800b9967a
--- /dev/null
+++ b/t/t4018/cpp-skip-comment-block
@@ -0,0 +1,9 @@
+struct item RIGHT(int i)
+// Do not
+// pick up
+/* these
+** comments.
+*/
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-skip-labels b/t/t4018/cpp-skip-labels
new file mode 100644
index 0000000000..b9c10aba22
--- /dev/null
+++ b/t/t4018/cpp-skip-labels
@@ -0,0 +1,8 @@
+void RIGHT (void)
+{
+repeat: // C++ comment
+next: /* C comment */
+ do_something();
+
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-struct-definition b/t/t4018/cpp-struct-definition
new file mode 100644
index 0000000000..521c59fd15
--- /dev/null
+++ b/t/t4018/cpp-struct-definition
@@ -0,0 +1,9 @@
+struct RIGHT {
+ unsigned
+ /* this bit field looks like a label and should not be picked up */
+ decoy_bitfield: 2,
+ more : 1;
+ int filler;
+
+ int ChangeMe;
+};
diff --git a/t/t4018/cpp-struct-single-line b/t/t4018/cpp-struct-single-line
new file mode 100644
index 0000000000..a0de5fb800
--- /dev/null
+++ b/t/t4018/cpp-struct-single-line
@@ -0,0 +1,7 @@
+void wrong()
+{
+}
+
+struct RIGHT_iterator_tag {};
+
+int ChangeMe;
diff --git a/t/t4018/cpp-template-function-definition b/t/t4018/cpp-template-function-definition
new file mode 100644
index 0000000000..0cdf5ba5bd
--- /dev/null
+++ b/t/t4018/cpp-template-function-definition
@@ -0,0 +1,4 @@
+template<class T> int RIGHT(T arg)
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-union-definition b/t/t4018/cpp-union-definition
new file mode 100644
index 0000000000..7ec94df697
--- /dev/null
+++ b/t/t4018/cpp-union-definition
@@ -0,0 +1,4 @@
+union RIGHT {
+ double v;
+ int ChangeMe;
+};
diff --git a/t/t4018/cpp-void-c-function b/t/t4018/cpp-void-c-function
new file mode 100644
index 0000000000..153081e872
--- /dev/null
+++ b/t/t4018/cpp-void-c-function
@@ -0,0 +1,4 @@
+void RIGHT (void)
+{
+ ChangeMe;
+}
diff --git a/t/t4018/custom1-pattern b/t/t4018/custom1-pattern
new file mode 100644
index 0000000000..e8fd59f884
--- /dev/null
+++ b/t/t4018/custom1-pattern
@@ -0,0 +1,17 @@
+public class Beer
+{
+ int special, RIGHT;
+ public static void main(String args[])
+ {
+ String s=" ";
+ for(int x = 99; x > 0; x--)
+ {
+ System.out.print(x + " bottles of beer on the wall "
+ + x + " bottles of beer\n" // ChangeMe
+ + "Take one down, pass it around, " + (x - 1)
+ + " bottles of beer on the wall.\n");
+ }
+ System.out.print("Go to the store, buy some more,\n"
+ + "99 bottles of beer on the wall.\n");
+ }
+}
diff --git a/t/t4018/custom2-match-to-end-of-line b/t/t4018/custom2-match-to-end-of-line
new file mode 100644
index 0000000000..f88ac318b7
--- /dev/null
+++ b/t/t4018/custom2-match-to-end-of-line
@@ -0,0 +1,8 @@
+public class RIGHT_Beer
+{
+ int special;
+ public static void main(String args[])
+ {
+ System.out.print("ChangeMe");
+ }
+}
diff --git a/t/t4018/custom3-alternation-in-pattern b/t/t4018/custom3-alternation-in-pattern
new file mode 100644
index 0000000000..5f3769c64f
--- /dev/null
+++ b/t/t4018/custom3-alternation-in-pattern
@@ -0,0 +1,17 @@
+public class Beer
+{
+ int special;
+ public static void main(String RIGHT[])
+ {
+ String s=" ";
+ for(int x = 99; x > 0; x--)
+ {
+ System.out.print(x + " bottles of beer on the wall "
+ + x + " bottles of beer\n" // ChangeMe
+ + "Take one down, pass it around, " + (x - 1)
+ + " bottles of beer on the wall.\n");
+ }
+ System.out.print("Go to the store, buy some more,\n"
+ + "99 bottles of beer on the wall.\n");
+ }
+}
diff --git a/t/t4018/java-class-member-function b/t/t4018/java-class-member-function
new file mode 100644
index 0000000000..298bc7a71b
--- /dev/null
+++ b/t/t4018/java-class-member-function
@@ -0,0 +1,8 @@
+public class Beer
+{
+ int special;
+ public static void main(String RIGHT[])
+ {
+ System.out.print("ChangeMe");
+ }
+}
diff --git a/t/t4018/perl-skip-end-of-heredoc b/t/t4018/perl-skip-end-of-heredoc
new file mode 100644
index 0000000000..c22d39b256
--- /dev/null
+++ b/t/t4018/perl-skip-end-of-heredoc
@@ -0,0 +1,8 @@
+sub RIGHTwithheredocument {
+ print <<"EOF"
+decoy here-doc
+EOF
+ # some lines of context
+ # to pad it out
+ print "ChangeMe\n";
+}
diff --git a/t/t4018/perl-skip-forward-decl b/t/t4018/perl-skip-forward-decl
new file mode 100644
index 0000000000..a98cb8bdad
--- /dev/null
+++ b/t/t4018/perl-skip-forward-decl
@@ -0,0 +1,10 @@
+package RIGHT;
+
+use strict;
+use warnings;
+use parent qw(Exporter);
+our @EXPORT_OK = qw(round finalround);
+
+sub other; # forward declaration
+
+# ChangeMe
diff --git a/t/t4018/perl-skip-sub-in-pod b/t/t4018/perl-skip-sub-in-pod
new file mode 100644
index 0000000000..e39f02462e
--- /dev/null
+++ b/t/t4018/perl-skip-sub-in-pod
@@ -0,0 +1,18 @@
+=head1 NAME
+
+Beer - subroutine to output fragment of a drinking song
+
+=head1 SYNOPSIS_RIGHT
+
+ use Beer qw(round finalround);
+
+ sub song {
+ for (my $i = 99; $i > 0; $i--) {
+ round $i;
+ }
+ finalround;
+ }
+
+ ChangeMe;
+
+=cut
diff --git a/t/t4018/perl-sub-definition b/t/t4018/perl-sub-definition
new file mode 100644
index 0000000000..a507d1f645
--- /dev/null
+++ b/t/t4018/perl-sub-definition
@@ -0,0 +1,4 @@
+sub RIGHT {
+ my ($n) = @_;
+ print "ChangeMe";
+}
diff --git a/t/t4018/perl-sub-definition-kr-brace b/t/t4018/perl-sub-definition-kr-brace
new file mode 100644
index 0000000000..330b3df114
--- /dev/null
+++ b/t/t4018/perl-sub-definition-kr-brace
@@ -0,0 +1,4 @@
+sub RIGHT
+{
+ print "ChangeMe\n";
+}
diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh
index bcae35ac1c..044620186d 100755
--- a/t/t4020-diff-external.sh
+++ b/t/t4020-diff-external.sh
@@ -226,12 +226,13 @@ keep_only_cr () {
}
test_expect_success 'external diff with autocrlf = true' '
- git config core.autocrlf true &&
+ test_config core.autocrlf true &&
GIT_EXTERNAL_DIFF=./fake-diff.sh git diff &&
test $(wc -l < crlfed.txt) = $(cat crlfed.txt | keep_only_cr | wc -c)
'
test_expect_success 'diff --cached' '
+ test_config core.autocrlf true &&
git add file &&
git update-index --assume-unchanged file &&
echo second >file &&
@@ -239,4 +240,31 @@ test_expect_success 'diff --cached' '
test_cmp "$TEST_DIRECTORY"/t4020/diff.NUL actual
'
+test_expect_success 'clean up crlf leftovers' '
+ git update-index --no-assume-unchanged file &&
+ rm -f file* &&
+ git reset --hard
+'
+
+test_expect_success 'submodule diff' '
+ git init sub &&
+ ( cd sub && test_commit sub1 ) &&
+ git add sub &&
+ test_tick &&
+ git commit -m "add submodule" &&
+ ( cd sub && test_commit sub2 ) &&
+ write_script gather_pre_post.sh <<-\EOF &&
+ echo "$1 $4" # path, mode
+ cat "$2" # old file
+ cat "$5" # new file
+ EOF
+ GIT_EXTERNAL_DIFF=./gather_pre_post.sh git diff >actual &&
+ cat >expected <<-EOF &&
+ sub 160000
+ Subproject commit $(git rev-parse HEAD:sub)
+ Subproject commit $(cd sub && git rev-parse HEAD)
+ EOF
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t4212-log-corrupt.sh b/t/t4212-log-corrupt.sh
index 93c7c366cf..3fa171541a 100755
--- a/t/t4212-log-corrupt.sh
+++ b/t/t4212-log-corrupt.sh
@@ -44,4 +44,49 @@ test_expect_success 'git log --format with broken author email' '
test_cmp expect.err actual.err
'
+munge_author_date () {
+ git cat-file commit "$1" >commit.orig &&
+ sed "s/^\(author .*>\) [0-9]*/\1 $2/" <commit.orig >commit.munge &&
+ git hash-object -w -t commit commit.munge
+}
+
+test_expect_success 'unparsable dates produce sentinel value' '
+ commit=$(munge_author_date HEAD totally_bogus) &&
+ echo "Date: Thu Jan 1 00:00:00 1970 +0000" >expect &&
+ git log -1 $commit >actual.full &&
+ grep Date <actual.full >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'unparsable dates produce sentinel value (%ad)' '
+ commit=$(munge_author_date HEAD totally_bogus) &&
+ echo >expect &&
+ git log -1 --format=%ad $commit >actual
+ test_cmp expect actual
+'
+
+# date is 2^64 + 1
+test_expect_success 'date parser recognizes integer overflow' '
+ commit=$(munge_author_date HEAD 18446744073709551617) &&
+ echo "Thu Jan 1 00:00:00 1970 +0000" >expect &&
+ git log -1 --format=%ad $commit >actual &&
+ test_cmp expect actual
+'
+
+# date is 2^64 - 2
+test_expect_success 'date parser recognizes time_t overflow' '
+ commit=$(munge_author_date HEAD 18446744073709551614) &&
+ echo "Thu Jan 1 00:00:00 1970 +0000" >expect &&
+ git log -1 --format=%ad $commit >actual &&
+ test_cmp expect actual
+'
+
+# date is within 2^63-1, but enough to choke glibc's gmtime
+test_expect_success 'absurdly far-in-future dates produce sentinel' '
+ commit=$(munge_author_date HEAD 999999999999999999) &&
+ echo "Thu Jan 1 00:00:00 1970 +0000" >expect &&
+ git log -1 --format=%ad $commit >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index 05f011d38e..1cf0a4e103 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -213,6 +213,15 @@ test_expect_success 'clients cannot access unreachable commits' '
test_must_fail git archive --remote=. $sha1 >remote.tar
'
+test_expect_success 'upload-archive can allow unreachable commits' '
+ test_commit unreachable1 &&
+ sha1=`git rev-parse HEAD` &&
+ git reset --hard HEAD^ &&
+ git archive $sha1 >remote.tar &&
+ test_config uploadarchive.allowUnreachable true &&
+ git archive --remote=. $sha1 >remote.tar
+'
+
test_expect_success 'setup tar filters' '
git config tar.tar.foo.command "tr ab ba" &&
git config tar.bar.command "tr ab ba" &&
diff --git a/t/t5150-request-pull.sh b/t/t5150-request-pull.sh
index 1afa0d5c44..75d6b3843a 100755
--- a/t/t5150-request-pull.sh
+++ b/t/t5150-request-pull.sh
@@ -86,7 +86,7 @@ test_expect_success 'setup: two scripts for reading pull requests' '
s/[-0-9]\{10\} [:0-9]\{8\} [-+][0-9]\{4\}/DATE/g
s/ [^ ].*/ SUBJECT/g
s/ [^ ].* (DATE)/ SUBJECT (DATE)/g
- s/for-upstream/BRANCH/g
+ s|tags/full|BRANCH|g
s/mnemonic.txt/FILENAME/g
s/^version [0-9]/VERSION/
/^ FILENAME | *[0-9]* [-+]*\$/ b diffstat
@@ -127,7 +127,7 @@ test_expect_success 'pull request when forgot to push' '
test_must_fail git request-pull initial "$downstream_url" \
2>../err
) &&
- grep "No branch of.*is at:\$" err &&
+ grep "No match for commit .*" err &&
grep "Are you sure you pushed" err
'
@@ -141,7 +141,7 @@ test_expect_success 'pull request after push' '
git checkout initial &&
git merge --ff-only master &&
git push origin master:for-upstream &&
- git request-pull initial origin >../request
+ git request-pull initial origin master:for-upstream >../request
) &&
sed -nf read-request.sed <request >digest &&
cat digest &&
@@ -160,7 +160,7 @@ test_expect_success 'pull request after push' '
'
-test_expect_success 'request names an appropriate branch' '
+test_expect_success 'request asks HEAD to be pulled' '
rm -fr downstream.git &&
git init --bare downstream.git &&
@@ -179,7 +179,7 @@ test_expect_success 'request names an appropriate branch' '
read repository &&
read branch
} <digest &&
- test "$branch" = tags/full
+ test -z "$branch"
'
@@ -212,12 +212,18 @@ test_expect_success 'pull request format' '
cd local &&
git checkout initial &&
git merge --ff-only master &&
- git push origin master:for-upstream &&
- git request-pull initial "$downstream_url" >../request
+ git push origin tags/full &&
+ git request-pull initial "$downstream_url" tags/full >../request
) &&
<request sed -nf fuzz.sed >request.fuzzy &&
- test_i18ncmp expect request.fuzzy
+ test_i18ncmp expect request.fuzzy &&
+ (
+ cd local &&
+ git request-pull initial "$downstream_url" tags/full:refs/tags/full
+ ) >request &&
+ sed -nf fuzz.sed <request >request.fuzzy &&
+ test_i18ncmp expect request.fuzzy
'
test_expect_success 'request-pull ignores OPTIONS_KEEPDASHDASH poison' '
@@ -229,7 +235,7 @@ test_expect_success 'request-pull ignores OPTIONS_KEEPDASHDASH poison' '
git checkout initial &&
git merge --ff-only master &&
git push origin master:for-upstream &&
- git request-pull -- initial "$downstream_url" >../request
+ git request-pull -- initial "$downstream_url" master:for-upstream >../request
)
'
diff --git a/t/t5305-include-tag.sh b/t/t5305-include-tag.sh
index b061864a87..21517c70cd 100755
--- a/t/t5305-include-tag.sh
+++ b/t/t5305-include-tag.sh
@@ -45,9 +45,7 @@ test_expect_success 'unpack objects' '
test_expect_success 'check unpacked result (have commit, no tag)' '
git rev-list --objects $commit >list.expect &&
(
- GIT_DIR=clone.git &&
- export GIT_DIR &&
- test_must_fail git cat-file -e $tag &&
+ test_must_fail env GIT_DIR=clone.git git cat-file -e $tag &&
git rev-list --objects $commit
) >list.actual &&
test_cmp list.expect list.actual
diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh
index d3a3afaba8..f13525caa3 100755
--- a/t/t5310-pack-bitmaps.sh
+++ b/t/t5310-pack-bitmaps.sh
@@ -91,7 +91,10 @@ test_expect_success 'fetch (partial bitmap)' '
test_expect_success 'incremental repack cannot create bitmaps' '
test_commit more-1 &&
- test_must_fail git repack -d
+ find .git/objects/pack -name "*.bitmap" >expect &&
+ git repack -d &&
+ find .git/objects/pack -name "*.bitmap" >actual &&
+ test_cmp expect actual
'
test_expect_success 'incremental repack can disable bitmaps' '
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index ab28594c62..5acd753dcf 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -301,7 +301,7 @@ test_expect_success 'fetch via rsync' '
mkdir rsynced &&
(cd rsynced &&
git init --bare &&
- git fetch "rsync:$(pwd)/../.git" master:refs/heads/master &&
+ git fetch "rsync:../.git" master:refs/heads/master &&
git gc --prune &&
test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
git fsck --full)
@@ -312,7 +312,7 @@ test_expect_success 'push via rsync' '
(cd rsynced2 &&
git init) &&
(cd rsynced &&
- git push "rsync:$(pwd)/../rsynced2/.git" master) &&
+ git push "rsync:../rsynced2/.git" master) &&
(cd rsynced2 &&
git gc --prune &&
test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
@@ -323,7 +323,7 @@ test_expect_success 'push via rsync' '
mkdir rsynced3 &&
(cd rsynced3 &&
git init) &&
- git push --all "rsync:$(pwd)/rsynced3/.git" &&
+ git push --all "rsync:rsynced3/.git" &&
(cd rsynced3 &&
test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
git fsck --full)
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 926e7f6b97..67e0ab3462 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -536,6 +536,19 @@ test_expect_success 'push with config branch.*.pushremote' '
check_push_result down_repo $the_commit heads/master
'
+test_expect_success 'branch.*.pushremote config order is irrelevant' '
+ mk_test one_repo heads/master &&
+ mk_test two_repo heads/master &&
+ test_config remote.one.url one_repo &&
+ test_config remote.two.url two_repo &&
+ test_config branch.master.pushremote two_repo &&
+ test_config remote.pushdefault one_repo &&
+ test_config push.default matching &&
+ git push &&
+ check_push_result one_repo $the_first_commit heads/master &&
+ check_push_result two_repo $the_commit heads/master
+'
+
test_expect_success 'push with dry-run' '
mk_test testrepo heads/master &&
diff --git a/t/t5529-push-errors.sh b/t/t5529-push-errors.sh
new file mode 100755
index 0000000000..9871307fd4
--- /dev/null
+++ b/t/t5529-push-errors.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+test_description='detect some push errors early (before contacting remote)'
+. ./test-lib.sh
+
+test_expect_success 'setup commits' '
+ test_commit one
+'
+
+test_expect_success 'setup remote' '
+ git init --bare remote.git &&
+ git remote add origin remote.git
+'
+
+test_expect_success 'setup fake receive-pack' '
+ FAKE_RP_ROOT=$(pwd) &&
+ export FAKE_RP_ROOT &&
+ write_script fake-rp <<-\EOF &&
+ echo yes >"$FAKE_RP_ROOT"/rp-ran
+ exit 1
+ EOF
+ git config remote.origin.receivepack "\"\$FAKE_RP_ROOT/fake-rp\""
+'
+
+test_expect_success 'detect missing branches early' '
+ echo no >rp-ran &&
+ echo no >expect &&
+ test_must_fail git push origin missing &&
+ test_cmp expect rp-ran
+'
+
+test_expect_success 'detect missing sha1 expressions early' '
+ echo no >rp-ran &&
+ echo no >expect &&
+ test_must_fail git push origin master~2:master &&
+ test_cmp expect rp-ran
+'
+
+test_expect_success 'detect ambiguous refs early' '
+ git branch foo &&
+ git tag foo &&
+ echo no >rp-ran &&
+ echo no >expect &&
+ test_must_fail git push origin foo &&
+ test_cmp expect rp-ran
+'
+
+test_done
diff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh
index 3ae9092f5c..be951a4679 100755
--- a/t/t5537-fetch-shallow.sh
+++ b/t/t5537-fetch-shallow.sh
@@ -173,4 +173,45 @@ EOF
)
'
+if test -n "$NO_CURL" -o -z "$GIT_TEST_HTTPD"; then
+ say 'skipping remaining tests, git built without http support'
+ test_done
+fi
+
+LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5537'}
+. "$TEST_DIRECTORY"/lib-httpd.sh
+start_httpd
+
+test_expect_success 'clone http repository' '
+ git clone --bare --no-local shallow "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ git clone $HTTPD_URL/smart/repo.git clone &&
+ (
+ cd clone &&
+ git fsck &&
+ git log --format=%s origin/master >actual &&
+ cat <<EOF >expect &&
+7
+6
+5
+4
+3
+EOF
+ test_cmp expect actual
+ )
+'
+
+test_expect_success POSIXPERM,SANITY 'shallow fetch from a read-only repo' '
+ cp -R .git read-only.git &&
+ find read-only.git -print | xargs chmod -w &&
+ test_when_finished "find read-only.git -type d -print | xargs chmod +w" &&
+ git clone --no-local --depth=2 read-only.git from-read-only &&
+ git --git-dir=from-read-only/.git log --format=%s >actual &&
+ cat >expect <<EOF &&
+add-1-back
+4
+EOF
+ test_cmp expect actual
+'
+
+stop_httpd
test_done
diff --git a/t/t5602-clone-remote-exec.sh b/t/t5602-clone-remote-exec.sh
index 3f353d99e8..cbcceab9d5 100755
--- a/t/t5602-clone-remote-exec.sh
+++ b/t/t5602-clone-remote-exec.sh
@@ -12,21 +12,14 @@ test_expect_success setup '
'
test_expect_success 'clone calls git upload-pack unqualified with no -u option' '
- (
- GIT_SSH=./not_ssh &&
- export GIT_SSH &&
- test_must_fail git clone localhost:/path/to/repo junk
- ) &&
+ test_must_fail env GIT_SSH=./not_ssh git clone localhost:/path/to/repo junk &&
echo "localhost git-upload-pack '\''/path/to/repo'\''" >expected &&
test_cmp expected not_ssh_output
'
test_expect_success 'clone calls specified git upload-pack with -u option' '
- (
- GIT_SSH=./not_ssh &&
- export GIT_SSH &&
- test_must_fail git clone -u ./something/bin/git-upload-pack localhost:/path/to/repo junk
- ) &&
+ test_must_fail env GIT_SSH=./not_ssh \
+ git clone -u ./something/bin/git-upload-pack localhost:/path/to/repo junk &&
echo "localhost ./something/bin/git-upload-pack '\''/path/to/repo'\''" >expected &&
test_cmp expected not_ssh_output
'
diff --git a/t/t5701-clone-local.sh b/t/t5701-clone-local.sh
index c4903687fb..3c087e907c 100755
--- a/t/t5701-clone-local.sh
+++ b/t/t5701-clone-local.sh
@@ -12,8 +12,8 @@ test_expect_success 'preparing origin repository' '
: >file && git add . && git commit -m1 &&
git clone --bare . a.git &&
git clone --bare . x &&
- test "$(GIT_CONFIG=a.git/config git config --bool core.bare)" = true &&
- test "$(GIT_CONFIG=x/config git config --bool core.bare)" = true &&
+ test "$(cd a.git && git config --bool core.bare)" = true &&
+ test "$(cd x && git config --bool core.bare)" = true &&
git bundle create b1.bundle --all &&
git bundle create b2.bundle master &&
mkdir dir &&
@@ -24,7 +24,7 @@ test_expect_success 'preparing origin repository' '
test_expect_success 'local clone without .git suffix' '
git clone -l -s a b &&
(cd b &&
- test "$(GIT_CONFIG=.git/config git config --bool core.bare)" = false &&
+ test "$(git config --bool core.bare)" = false &&
git fetch)
'
diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index 613f69a254..25fd2e7f46 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -94,6 +94,19 @@ test_expect_failure 'push new branch with old:new refspec' '
compare_refs local HEAD server refs/heads/new-refspec
'
+test_expect_success 'forced push' '
+ (cd local &&
+ git checkout -b force-test &&
+ echo content >> file &&
+ git commit -a -m eight &&
+ git push origin force-test &&
+ echo content >> file &&
+ git commit -a --amend -m eight-modified &&
+ git push --force origin force-test
+ ) &&
+ compare_refs local refs/heads/force-test server refs/heads/force-test
+'
+
test_expect_success 'cloning without refspec' '
GIT_REMOTE_TESTGIT_REFSPEC="" \
git clone "testgit::${PWD}/server" local2 2>error &&
@@ -218,10 +231,8 @@ test_expect_success 'proper failure checks for fetching' '
'
test_expect_success 'proper failure checks for pushing' '
- (GIT_REMOTE_TESTGIT_FAILURE=1 &&
- export GIT_REMOTE_TESTGIT_FAILURE &&
- cd local &&
- test_must_fail git push --all
+ (cd local &&
+ test_must_fail env GIT_REMOTE_TESTGIT_FAILURE=1 git push --all
)
'
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index 98744038ec..9d9d9de08e 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -190,12 +190,9 @@ test_expect_success '%C(auto) respects --no-color' '
'
test_expect_success TTY '%C(auto) respects --color=auto (stdout is tty)' '
- (
- TERM=vt100 && export TERM &&
- test_terminal \
- git log --format=$AUTO_COLOR -1 --color=auto >actual &&
- has_color actual
- )
+ test_terminal env TERM=vt100 \
+ git log --format=$AUTO_COLOR -1 --color=auto >actual &&
+ has_color actual
'
test_expect_success '%C(auto) respects --color=auto (stdout not tty)' '
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index e3c8c2c1b8..215d43d6a6 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -294,7 +294,8 @@ test_expect_success 'setup submodule' '
git submodule add ./. sub &&
echo content >file &&
git add file &&
- git commit -m "added sub and file"
+ git commit -m "added sub and file" &&
+ git branch submodule
'
test_expect_success 'git mv cannot move a submodule in a file' '
@@ -463,4 +464,14 @@ test_expect_success 'checking out a commit before submodule moved needs manual u
! test -s actual
'
+test_expect_success 'mv -k does not accidentally destroy submodules' '
+ git checkout submodule &&
+ mkdir dummy dest &&
+ git mv -k dummy sub dest &&
+ git status --porcelain >actual &&
+ grep "^R sub -> dest/sub" actual &&
+ git reset --hard &&
+ git checkout .
+'
+
test_done
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index c8d6e9f88c..143a8ea605 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -1380,4 +1380,47 @@ test_expect_success 'multiple --points-at are OR-ed together' '
test_cmp expect actual
'
+test_expect_success 'lexical sort' '
+ git tag foo1.3 &&
+ git tag foo1.6 &&
+ git tag foo1.10 &&
+ git tag -l --sort=refname "foo*" >actual &&
+ cat >expect <<EOF &&
+foo1.10
+foo1.3
+foo1.6
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'version sort' '
+ git tag -l --sort=version:refname "foo*" >actual &&
+ cat >expect <<EOF &&
+foo1.3
+foo1.6
+foo1.10
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'reverse version sort' '
+ git tag -l --sort=-version:refname "foo*" >actual &&
+ cat >expect <<EOF &&
+foo1.10
+foo1.6
+foo1.3
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'reverse lexical sort' '
+ git tag -l --sort=-refname "foo*" >actual &&
+ cat >expect <<EOF &&
+foo1.6
+foo1.3
+foo1.10
+EOF
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh
index b9365b431d..da958a8b56 100755
--- a/t/t7006-pager.sh
+++ b/t/t7006-pager.sh
@@ -146,11 +146,7 @@ test_expect_success 'no color when stdout is a regular file' '
test_expect_success TTY 'color when writing to a pager' '
rm -f paginated.out &&
test_config color.ui auto &&
- (
- TERM=vt100 &&
- export TERM &&
- test_terminal git log
- ) &&
+ test_terminal env TERM=vt100 git log &&
colorful paginated.out
'
@@ -158,11 +154,7 @@ test_expect_success TTY 'colors are suppressed by color.pager' '
rm -f paginated.out &&
test_config color.ui auto &&
test_config color.pager false &&
- (
- TERM=vt100 &&
- export TERM &&
- test_terminal git log
- ) &&
+ test_terminal env TERM=vt100 git log &&
! colorful paginated.out
'
@@ -181,11 +173,7 @@ test_expect_success 'color when writing to a file intended for a pager' '
test_expect_success TTY 'colors are sent to pager for external commands' '
test_config alias.externallog "!git log" &&
test_config color.ui auto &&
- (
- TERM=vt100 &&
- export TERM &&
- test_terminal git -p externallog
- ) &&
+ test_terminal env TERM=vt100 git -p externallog &&
colorful paginated.out
'
diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index 7d467c034a..741ec08576 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -38,7 +38,7 @@ You have unmerged paths.
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
- deleted by us: foo
+ deleted by us: foo
no changes added to commit (use "git add" and/or "git commit -a")
EOF
@@ -142,8 +142,8 @@ You have unmerged paths.
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
- both added: conflict.txt
- deleted by them: main.txt
+ both added: conflict.txt
+ deleted by them: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
EOF
@@ -175,9 +175,9 @@ You have unmerged paths.
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
- both deleted: main.txt
- added by them: sub_master.txt
- added by us: sub_second.txt
+ both deleted: main.txt
+ added by them: sub_master.txt
+ added by us: sub_second.txt
no changes added to commit (use "git add" and/or "git commit -a")
EOF
@@ -203,7 +203,7 @@ Changes to be committed:
Unmerged paths:
(use "git rm <file>..." to mark resolution)
- both deleted: main.txt
+ both deleted: main.txt
Untracked files not listed (use -u option to show untracked files)
EOF
diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh
index bc0846f435..450529404c 100755
--- a/t/t7102-reset.sh
+++ b/t/t7102-reset.sh
@@ -550,4 +550,15 @@ test_expect_success 'reset -N keeps removed files as intent-to-add' '
test_cmp expect actual
'
+test_expect_success 'reset --mixed sets up work tree' '
+ git init mixed_worktree &&
+ (
+ cd mixed_worktree &&
+ test_commit dummy
+ ) &&
+ : >expect &&
+ git --git-dir=mixed_worktree/.git --work-tree=mixed_worktree reset >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index 710be90489..74de814aec 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -511,4 +511,20 @@ test_expect_success SANITY 'git clean -d with an unreadable empty directory' '
! test -d foo
'
+test_expect_success 'git clean -d respects pathspecs (dir is prefix of pathspec)' '
+ mkdir -p foo &&
+ mkdir -p foobar &&
+ git clean -df foobar &&
+ test_path_is_dir foo &&
+ test_path_is_missing foobar
+'
+
+test_expect_success 'git clean -d respects pathspecs (pathspec is prefix of dir)' '
+ mkdir -p foo &&
+ mkdir -p foobar &&
+ git clean -df foo &&
+ test_path_is_missing foo &&
+ test_path_is_dir foobar
+'
+
test_done
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index c28e8d8ada..7c88245031 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -249,8 +249,7 @@ test_expect_success 'submodule add in subdirectory with relative path should fai
'
test_expect_success 'setup - add an example entry to .gitmodules' '
- GIT_CONFIG=.gitmodules \
- git config submodule.example.url git://example.com/init.git
+ git config --file=.gitmodules submodule.example.url git://example.com/init.git
'
test_expect_success 'status should fail for unmapped paths' '
@@ -264,7 +263,7 @@ test_expect_success 'setup - map path in .gitmodules' '
path = init
EOF
- GIT_CONFIG=.gitmodules git config submodule.example.path init &&
+ git config --file=.gitmodules submodule.example.path init &&
test_cmp expect .gitmodules
'
diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh
index 94eec83b37..d58b097ff3 100755
--- a/t/t7501-commit.sh
+++ b/t/t7501-commit.sh
@@ -61,11 +61,47 @@ test_expect_success 'nothing to commit' '
test_must_fail git commit -m initial
'
+test_expect_success '--dry-run fails with nothing to commit' '
+ test_must_fail git commit -m initial --dry-run
+'
+
+test_expect_success '--short fails with nothing to commit' '
+ test_must_fail git commit -m initial --short
+'
+
+test_expect_success '--porcelain fails with nothing to commit' '
+ test_must_fail git commit -m initial --porcelain
+'
+
+test_expect_success '--long fails with nothing to commit' '
+ test_must_fail git commit -m initial --long
+'
+
test_expect_success 'setup: non-initial commit' '
echo bongo bongo bongo >file &&
git commit -m next -a
'
+test_expect_success '--dry-run with stuff to commit returns ok' '
+ echo bongo bongo bongo >>file &&
+ git commit -m next -a --dry-run
+'
+
+test_expect_failure '--short with stuff to commit returns ok' '
+ echo bongo bongo bongo >>file &&
+ git commit -m next -a --short
+'
+
+test_expect_failure '--porcelain with stuff to commit returns ok' '
+ echo bongo bongo bongo >>file &&
+ git commit -m next -a --porcelain
+'
+
+test_expect_success '--long with stuff to commit returns ok' '
+ echo bongo bongo bongo >>file &&
+ git commit -m next -a --long
+'
+
test_expect_success 'commit message from non-existing file' '
echo more bongo: bongo bongo bongo bongo >file &&
test_must_fail git commit -F gah -a
diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh
index 6313da2cdd..9a3f3a1b41 100755
--- a/t/t7502-commit.sh
+++ b/t/t7502-commit.sh
@@ -223,6 +223,22 @@ test_expect_success 'cleanup commit messages (whitespace option,-F)' '
'
+test_expect_success 'cleanup commit messages (scissors option,-F,-e)' '
+
+ echo >>negative &&
+ cat >text <<EOF &&
+
+# to be kept
+# ------------------------ >8 ------------------------
+to be removed
+EOF
+ echo "# to be kept" >expect &&
+ git commit --cleanup=scissors -e -F text -a &&
+ git cat-file -p HEAD |sed -e "1,/^\$/d">actual &&
+ test_cmp expect actual
+
+'
+
test_expect_success 'cleanup commit messages (strip option,-F)' '
echo >>negative &&
diff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh
index 357375151d..03dce09cfe 100755
--- a/t/t7505-prepare-commit-msg-hook.sh
+++ b/t/t7505-prepare-commit-msg-hook.sh
@@ -134,14 +134,26 @@ test_expect_success 'with hook (-c)' '
test_expect_success 'with hook (merge)' '
- head=`git rev-parse HEAD` &&
- git checkout -b other HEAD@{1} &&
- echo "more" >> file &&
+ test_when_finished "git checkout -f master" &&
+ git checkout -B other HEAD@{1} &&
+ echo "more" >>file &&
+ git add file &&
+ git commit -m other &&
+ git checkout - &&
+ git merge --no-ff other &&
+ test "`git log -1 --pretty=format:%s`" = "merge (no editor)"
+'
+
+test_expect_success 'with hook and editor (merge)' '
+
+ test_when_finished "git checkout -f master" &&
+ git checkout -B other HEAD@{1} &&
+ echo "more" >>file &&
git add file &&
git commit -m other &&
git checkout - &&
- git merge other &&
- test "`git log -1 --pretty=format:%s`" = merge
+ env GIT_EDITOR="\"\$FAKE_EDITOR\"" git merge --no-ff -e other &&
+ test "`git log -1 --pretty=format:%s`" = "merge"
'
cat > "$HOOK" <<'EOF'
@@ -151,34 +163,37 @@ EOF
test_expect_success 'with failing hook' '
+ test_when_finished "git checkout -f master" &&
head=`git rev-parse HEAD` &&
echo "more" >> file &&
git add file &&
- ! GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -c $head
+ test_must_fail env GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -c $head
'
test_expect_success 'with failing hook (--no-verify)' '
+ test_when_finished "git checkout -f master" &&
head=`git rev-parse HEAD` &&
echo "more" >> file &&
git add file &&
- ! GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify -c $head
+ test_must_fail env GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify -c $head
'
test_expect_success 'with failing hook (merge)' '
+ test_when_finished "git checkout -f master" &&
git checkout -B other HEAD@{1} &&
echo "more" >> file &&
git add file &&
rm -f "$HOOK" &&
git commit -m other &&
- write_script "$HOOK" <<-EOF
+ write_script "$HOOK" <<-EOF &&
exit 1
EOF
git checkout - &&
- test_must_fail git merge other
+ test_must_fail git merge --no-ff other
'
diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index 3cec57af1e..68ad2d7454 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -33,7 +33,7 @@ You have unmerged paths.
Unmerged paths:
(use "git add <file>..." to mark resolution)
- both modified: main.txt
+ both modified: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
EOF
@@ -87,7 +87,7 @@ Unmerged paths:
(use "git reset HEAD <file>..." to unstage)
(use "git add <file>..." to mark resolution)
- both modified: main.txt
+ both modified: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
EOF
@@ -146,7 +146,7 @@ Unmerged paths:
(use "git reset HEAD <file>..." to unstage)
(use "git add <file>..." to mark resolution)
- both modified: main.txt
+ both modified: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
EOF
@@ -602,7 +602,7 @@ rebase in progress; onto $ONTO
You are currently rebasing branch '\''statushints_disabled'\'' on '\''$ONTO'\''.
Unmerged paths:
- both modified: main.txt
+ both modified: main.txt
no changes added to commit
EOF
@@ -636,7 +636,7 @@ You are currently cherry-picking commit $TO_CHERRY_PICK.
Unmerged paths:
(use "git add <file>..." to mark resolution)
- both modified: main.txt
+ both modified: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
EOF
@@ -707,7 +707,7 @@ Unmerged paths:
(use "git reset HEAD <file>..." to unstage)
(use "git add <file>..." to mark resolution)
- both modified: to-revert.txt
+ both modified: to-revert.txt
no changes added to commit (use "git add" and/or "git commit -a")
EOF
diff --git a/t/t7514-commit-patch.sh b/t/t7514-commit-patch.sh
new file mode 100755
index 0000000000..998a2103c7
--- /dev/null
+++ b/t/t7514-commit-patch.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+test_description='hunk edit with "commit -p -m"'
+. ./test-lib.sh
+
+if ! test_have_prereq PERL
+then
+ skip_all="skipping '$test_description' tests, perl not available"
+ test_done
+fi
+
+test_expect_success 'setup (initial)' '
+ echo line1 >file &&
+ git add file &&
+ git commit -m commit1
+'
+
+test_expect_success 'edit hunk "commit -p -m message"' '
+ test_when_finished "rm -f editor_was_started" &&
+ rm -f editor_was_started &&
+ echo more >>file &&
+ echo e | env GIT_EDITOR=": >editor_was_started" git commit -p -m commit2 file &&
+ test -r editor_was_started
+'
+
+test_expect_success 'edit hunk "commit --dry-run -p -m message"' '
+ test_when_finished "rm -f editor_was_started" &&
+ rm -f editor_was_started &&
+ echo more >>file &&
+ echo e | env GIT_EDITOR=": >editor_was_started" git commit -p -m commit3 file &&
+ test -r editor_was_started
+'
+
+test_done
diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
index b45bd1e76c..284018e3cd 100755
--- a/t/t7700-repack.sh
+++ b/t/t7700-repack.sh
@@ -21,7 +21,7 @@ test_expect_success 'objects in packs marked .keep are not repacked' '
objsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |
sed -e "s/^\([0-9a-f]\{40\}\).*/\1/") &&
mv pack-* .git/objects/pack/ &&
- git repack -A -d -l &&
+ git repack --no-pack-kept-objects -A -d -l &&
git prune-packed &&
for p in .git/objects/pack/*.idx; do
idx=$(basename $p)
@@ -35,6 +35,22 @@ test_expect_success 'objects in packs marked .keep are not repacked' '
test -z "$found_duplicate_object"
'
+test_expect_success 'writing bitmaps can duplicate .keep objects' '
+ # build on $objsha1, $packsha1, and .keep state from previous
+ git repack -Adl &&
+ test_when_finished "found_duplicate_object=" &&
+ for p in .git/objects/pack/*.idx; do
+ idx=$(basename $p)
+ test "pack-$packsha1.idx" = "$idx" && continue
+ if git verify-pack -v $p | egrep "^$objsha1"; then
+ found_duplicate_object=1
+ echo "DUPLICATE OBJECT FOUND"
+ break
+ fi
+ done &&
+ test "$found_duplicate_object" = 1
+'
+
test_expect_success 'loose objects in alternate ODB are not repacked' '
mkdir alt_objects &&
echo `pwd`/alt_objects > .git/objects/info/alternates &&
diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index 2418528487..5a193c500d 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -434,4 +434,18 @@ test_expect_success PERL 'difftool --no-symlinks detects conflict ' '
)
'
+test_expect_success PERL 'difftool properly honors gitlink and core.worktree' '
+ git submodule add ./. submod/ule &&
+ (
+ cd submod/ule &&
+ test_config diff.tool checktrees &&
+ test_config difftool.checktrees.cmd '\''
+ test -d "$LOCAL" && test -d "$REMOTE" && echo good
+ '\'' &&
+ echo good >expect &&
+ git difftool --tool=checktrees --dir-diff HEAD~ >actual &&
+ test_cmp expect actual
+ )
+'
+
test_done
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index f698001c99..63b3039243 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -105,7 +105,7 @@ do
test_expect_success "grep -w $L (w)" '
: >expected &&
- test_must_fail git grep -n -w -e "^w" >actual &&
+ test_must_fail git grep -n -w -e "^w" $H >actual &&
test_cmp expected actual
'
@@ -240,92 +240,104 @@ do
test_cmp expected actual
'
test_expect_success "grep $L with grep.extendedRegexp=false" '
- echo "ab:a+bc" >expected &&
- git -c grep.extendedRegexp=false grep "a+b*c" ab >actual &&
+ echo "${HC}ab:a+bc" >expected &&
+ git -c grep.extendedRegexp=false grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
test_expect_success "grep $L with grep.extendedRegexp=true" '
- echo "ab:abc" >expected &&
- git -c grep.extendedRegexp=true grep "a+b*c" ab >actual &&
+ echo "${HC}ab:abc" >expected &&
+ git -c grep.extendedRegexp=true grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
test_expect_success "grep $L with grep.patterntype=basic" '
- echo "ab:a+bc" >expected &&
- git -c grep.patterntype=basic grep "a+b*c" ab >actual &&
+ echo "${HC}ab:a+bc" >expected &&
+ git -c grep.patterntype=basic grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
test_expect_success "grep $L with grep.patterntype=extended" '
- echo "ab:abc" >expected &&
- git -c grep.patterntype=extended grep "a+b*c" ab >actual &&
+ echo "${HC}ab:abc" >expected &&
+ git -c grep.patterntype=extended grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
test_expect_success "grep $L with grep.patterntype=fixed" '
- echo "ab:a+b*c" >expected &&
- git -c grep.patterntype=fixed grep "a+b*c" ab >actual &&
+ echo "${HC}ab:a+b*c" >expected &&
+ git -c grep.patterntype=fixed grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
test_expect_success LIBPCRE "grep $L with grep.patterntype=perl" '
- echo "ab:a+b*c" >expected &&
- git -c grep.patterntype=perl grep "a\x{2b}b\x{2a}c" ab >actual &&
+ echo "${HC}ab:a+b*c" >expected &&
+ git -c grep.patterntype=perl grep "a\x{2b}b\x{2a}c" $H ab >actual &&
test_cmp expected actual
'
test_expect_success "grep $L with grep.patternType=default and grep.extendedRegexp=true" '
- echo "ab:abc" >expected &&
+ echo "${HC}ab:abc" >expected &&
git \
-c grep.patternType=default \
-c grep.extendedRegexp=true \
- grep "a+b*c" ab >actual &&
+ grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
test_expect_success "grep $L with grep.extendedRegexp=true and grep.patternType=default" '
- echo "ab:abc" >expected &&
+ echo "${HC}ab:abc" >expected &&
git \
-c grep.extendedRegexp=true \
-c grep.patternType=default \
- grep "a+b*c" ab >actual &&
+ grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
- test_expect_success 'grep $L with grep.patternType=extended and grep.extendedRegexp=false' '
- echo "ab:abc" >expected &&
+ test_expect_success "grep $L with grep.patternType=extended and grep.extendedRegexp=false" '
+ echo "${HC}ab:abc" >expected &&
git \
-c grep.patternType=extended \
-c grep.extendedRegexp=false \
- grep "a+b*c" ab >actual &&
+ grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
- test_expect_success 'grep $L with grep.patternType=basic and grep.extendedRegexp=true' '
- echo "ab:a+bc" >expected &&
+ test_expect_success "grep $L with grep.patternType=basic and grep.extendedRegexp=true" '
+ echo "${HC}ab:a+bc" >expected &&
git \
-c grep.patternType=basic \
-c grep.extendedRegexp=true \
- grep "a+b*c" ab >actual &&
+ grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
- test_expect_success 'grep $L with grep.extendedRegexp=false and grep.patternType=extended' '
- echo "ab:abc" >expected &&
+ test_expect_success "grep $L with grep.extendedRegexp=false and grep.patternType=extended" '
+ echo "${HC}ab:abc" >expected &&
git \
-c grep.extendedRegexp=false \
-c grep.patternType=extended \
- grep "a+b*c" ab >actual &&
+ grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
- test_expect_success 'grep $L with grep.extendedRegexp=true and grep.patternType=basic' '
- echo "ab:a+bc" >expected &&
+ test_expect_success "grep $L with grep.extendedRegexp=true and grep.patternType=basic" '
+ echo "${HC}ab:a+bc" >expected &&
git \
-c grep.extendedRegexp=true \
-c grep.patternType=basic \
- grep "a+b*c" ab >actual &&
+ grep "a+b*c" $H ab >actual &&
+ test_cmp expected actual
+ '
+
+ test_expect_success "grep --count $L" '
+ echo ${HC}ab:3 >expected &&
+ git grep --count -e b $H -- ab >actual &&
+ test_cmp expected actual
+ '
+
+ test_expect_success "grep --count -h $L" '
+ echo 3 >expected &&
+ git grep --count -h -e b $H -- ab >actual &&
test_cmp expected actual
'
done
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 3119c8c523..1ecdacb6fd 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -409,7 +409,7 @@ test_expect_success $PREREQ 'Valid In-Reply-To when prompting' '
(echo "From Example <from@example.com>"
echo "To Example <to@example.com>"
echo ""
- ) | env GIT_SEND_EMAIL_NOTTY=1 git send-email \
+ ) | GIT_SEND_EMAIL_NOTTY=1 git send-email \
--smtp-server="$(pwd)/fake.sendmail" \
$patches 2>errors &&
! grep "^In-Reply-To: < *>" msgtxt1
diff --git a/t/t9130-git-svn-authors-file.sh b/t/t9130-git-svn-authors-file.sh
index c3443ceb25..c44de267a1 100755
--- a/t/t9130-git-svn-authors-file.sh
+++ b/t/t9130-git-svn-authors-file.sh
@@ -67,7 +67,7 @@ test_expect_success 'fetch fails on ee' '
'
tmp_config_get () {
- GIT_CONFIG=.git/svn/.metadata git config --get "$1"
+ git config --file=.git/svn/.metadata --get "$1"
}
test_expect_success 'failure happened without negative side effects' '
@@ -97,7 +97,6 @@ test_expect_success 'fresh clone with svn.authors-file in config' '
test x = x"$(git config svn.authorsfile)" &&
test_config="$HOME"/.gitconfig &&
sane_unset GIT_DIR &&
- sane_unset GIT_CONFIG &&
git config --global \
svn.authorsfile "$HOME"/svn-authors &&
test x"$HOME"/svn-authors = x"$(git config svn.authorsfile)" &&
diff --git a/t/t9154-git-svn-fancy-glob.sh b/t/t9154-git-svn-fancy-glob.sh
index b780e0efe3..a0150f057d 100755
--- a/t/t9154-git-svn-fancy-glob.sh
+++ b/t/t9154-git-svn-fancy-glob.sh
@@ -22,7 +22,7 @@ test_expect_success 'add red branch' "
"
test_expect_success 'add gre branch' "
- GIT_CONFIG=.git/svn/.metadata git config --unset svn-remote.svn.branches-maxRev &&
+ git config --file=.git/svn/.metadata --unset svn-remote.svn.branches-maxRev &&
git config svn-remote.svn.branches 'branches/{red,gre}:refs/remotes/*' &&
git svn fetch &&
git rev-parse refs/remotes/red &&
@@ -31,7 +31,7 @@ test_expect_success 'add gre branch' "
"
test_expect_success 'add green branch' "
- GIT_CONFIG=.git/svn/.metadata git config --unset svn-remote.svn.branches-maxRev &&
+ git config --file=.git/svn/.metadata --unset svn-remote.svn.branches-maxRev &&
git config svn-remote.svn.branches 'branches/{red,green}:refs/remotes/*' &&
git svn fetch &&
git rev-parse refs/remotes/red &&
@@ -40,7 +40,7 @@ test_expect_success 'add green branch' "
"
test_expect_success 'add all branches' "
- GIT_CONFIG=.git/svn/.metadata git config --unset svn-remote.svn.branches-maxRev &&
+ git config --file=.git/svn/.metadata --unset svn-remote.svn.branches-maxRev &&
git config svn-remote.svn.branches 'branches/*:refs/remotes/*' &&
git svn fetch &&
git rev-parse refs/remotes/red &&
diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh
index 3edc4086d8..ed98e64477 100755
--- a/t/t9400-git-cvsserver-server.sh
+++ b/t/t9400-git-cvsserver-server.sh
@@ -25,7 +25,6 @@ perl -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || {
test_done
}
-unset GIT_DIR GIT_CONFIG
WORKDIR=$(pwd)
SERVERDIR=$(pwd)/gitcvs.git
git_config="$SERVERDIR/config"
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index b333e3ff86..158e10a67e 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -32,6 +32,11 @@ test_set_editor () {
export EDITOR
}
+test_set_index_version () {
+ GIT_INDEX_VERSION="$1"
+ export GIT_INDEX_VERSION
+}
+
test_decode_color () {
awk '
function name(n) {
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 1531c241c0..c081668dfe 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -108,6 +108,12 @@ export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME
export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME
export EDITOR
+if test -n "${TEST_GIT_INDEX_VERSION:+isset}"
+then
+ GIT_INDEX_VERSION="$TEST_GIT_INDEX_VERSION"
+ export GIT_INDEX_VERSION
+fi
+
# Add libc MALLOC and MALLOC_PERTURB test
# only if we are not executing the test with valgrind
if expr " $GIT_TEST_OPTS " : ".* --valgrind " >/dev/null ||
@@ -277,7 +283,7 @@ error "Test script did not set test_description."
if test "$help" = "t"
then
- echo "$test_description"
+ printf '%s\n' "$test_description"
exit 0
fi
@@ -328,7 +334,7 @@ test_failure_ () {
test_failure=$(($test_failure + 1))
say_color error "not ok $test_count - $1"
shift
- echo "$@" | sed -e 's/^/# /'
+ printf '%s\n' "$*" | sed -e 's/^/# /'
test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; }
}
@@ -649,7 +655,6 @@ else # normal case, use ../bin-wrappers only unless $with_dashes:
fi
fi
GIT_TEMPLATE_DIR="$GIT_BUILD_DIR"/templates/blt
-unset GIT_CONFIG
GIT_CONFIG_NOSYSTEM=1
GIT_ATTR_NOSYSTEM=1
export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_ATTR_NOSYSTEM
diff --git a/test-wildmatch.c b/test-wildmatch.c
index a3e2643fbc..578b164fe6 100644
--- a/test-wildmatch.c
+++ b/test-wildmatch.c
@@ -1,85 +1,8 @@
-#ifdef USE_WILDMATCH
-#undef USE_WILDMATCH /* We need real fnmatch implementation here */
-#endif
#include "cache.h"
-#include "wildmatch.h"
-
-static int perf(int ac, char **av)
-{
- struct timeval tv1, tv2;
- struct stat st;
- int fd, i, n, flags1 = 0, flags2 = 0;
- char *buffer, *p;
- uint32_t usec1, usec2;
- const char *lang;
- const char *file = av[0];
- const char *pattern = av[1];
-
- lang = getenv("LANG");
- if (lang && strcmp(lang, "C"))
- die("Please test it on C locale.");
-
- if ((fd = open(file, O_RDONLY)) == -1 || fstat(fd, &st))
- die_errno("file open");
-
- buffer = xmalloc(st.st_size + 2);
- if (read(fd, buffer, st.st_size) != st.st_size)
- die_errno("read");
-
- buffer[st.st_size] = '\0';
- buffer[st.st_size + 1] = '\0';
- for (i = 0; i < st.st_size; i++)
- if (buffer[i] == '\n')
- buffer[i] = '\0';
-
- n = atoi(av[2]);
- if (av[3] && !strcmp(av[3], "pathname")) {
- flags1 = WM_PATHNAME;
- flags2 = FNM_PATHNAME;
- }
-
- gettimeofday(&tv1, NULL);
- for (i = 0; i < n; i++) {
- for (p = buffer; *p; p += strlen(p) + 1)
- wildmatch(pattern, p, flags1, NULL);
- }
- gettimeofday(&tv2, NULL);
-
- usec1 = (uint32_t)tv2.tv_sec * 1000000 + tv2.tv_usec;
- usec1 -= (uint32_t)tv1.tv_sec * 1000000 + tv1.tv_usec;
- printf("wildmatch %ds %dus\n",
- (int)(usec1 / 1000000),
- (int)(usec1 % 1000000));
-
- gettimeofday(&tv1, NULL);
- for (i = 0; i < n; i++) {
- for (p = buffer; *p; p += strlen(p) + 1)
- fnmatch(pattern, p, flags2);
- }
- gettimeofday(&tv2, NULL);
-
- usec2 = (uint32_t)tv2.tv_sec * 1000000 + tv2.tv_usec;
- usec2 -= (uint32_t)tv1.tv_sec * 1000000 + tv1.tv_usec;
- if (usec2 > usec1)
- printf("fnmatch %ds %dus or %.2f%% slower\n",
- (int)((usec2 - usec1) / 1000000),
- (int)((usec2 - usec1) % 1000000),
- (float)(usec2 - usec1) / usec1 * 100);
- else
- printf("fnmatch %ds %dus or %.2f%% faster\n",
- (int)((usec1 - usec2) / 1000000),
- (int)((usec1 - usec2) % 1000000),
- (float)(usec1 - usec2) / usec1 * 100);
- return 0;
-}
int main(int argc, char **argv)
{
int i;
-
- if (!strcmp(argv[1], "perf"))
- return perf(argc - 2, argv + 2);
-
for (i = 2; i < argc; i++) {
if (argv[i][0] == '/')
die("Forward slash is not allowed at the beginning of the\n"
@@ -93,8 +16,6 @@ int main(int argc, char **argv)
return !!wildmatch(argv[3], argv[2], WM_PATHNAME | WM_CASEFOLD, NULL);
else if (!strcmp(argv[1], "pathmatch"))
return !!wildmatch(argv[3], argv[2], 0, NULL);
- else if (!strcmp(argv[1], "fnmatch"))
- return !!fnmatch(argv[3], argv[2], FNM_PATHNAME);
else
return 1;
}
diff --git a/transport-helper.c b/transport-helper.c
index ad72fbd53c..86e1679c1e 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -650,7 +650,7 @@ static int push_update_ref_status(struct strbuf *buf,
struct ref *remote_refs)
{
char *refname, *msg;
- int status;
+ int status, forced = 0;
if (starts_with(buf->buf, "ok ")) {
status = REF_STATUS_OK;
@@ -708,6 +708,11 @@ static int push_update_ref_status(struct strbuf *buf,
free(msg);
msg = NULL;
}
+ else if (!strcmp(msg, "forced update")) {
+ forced = 1;
+ free(msg);
+ msg = NULL;
+ }
}
if (*ref)
@@ -729,12 +734,14 @@ static int push_update_ref_status(struct strbuf *buf,
}
(*ref)->status = status;
+ (*ref)->forced_update |= forced;
(*ref)->remote_status = msg;
return !(status == REF_STATUS_OK);
}
static void push_update_refs_status(struct helper_data *data,
- struct ref *remote_refs)
+ struct ref *remote_refs,
+ int flags)
{
struct strbuf buf = STRBUF_INIT;
struct ref *ref = remote_refs;
@@ -748,7 +755,7 @@ static void push_update_refs_status(struct helper_data *data,
if (push_update_ref_status(&buf, &ref, remote_refs))
continue;
- if (!data->refspecs || data->no_private_update)
+ if (flags & TRANSPORT_PUSH_DRY_RUN || !data->refspecs || data->no_private_update)
continue;
/* propagate back the update to the remote namespace */
@@ -839,7 +846,7 @@ static int push_refs_with_push(struct transport *transport,
sendline(data, &buf);
strbuf_release(&buf);
- push_update_refs_status(data, remote_refs);
+ push_update_refs_status(data, remote_refs, flags);
return 0;
}
@@ -860,6 +867,11 @@ static int push_refs_with_export(struct transport *transport,
die("helper %s does not support dry-run", data->name);
}
+ if (flags & TRANSPORT_PUSH_FORCE) {
+ if (set_helper_option(transport, "force", "true") != 0)
+ warning("helper %s does not support 'force'", data->name);
+ }
+
helper = get_helper(transport);
write_constant(helper->in, "export\n");
@@ -881,9 +893,6 @@ static int push_refs_with_export(struct transport *transport,
}
free(private);
- if (ref->deletion)
- die("remote-helpers do not support ref deletion");
-
if (ref->peer_ref) {
if (strcmp(ref->peer_ref->name, ref->name))
die("remote-helpers do not support old:new syntax");
@@ -896,7 +905,7 @@ static int push_refs_with_export(struct transport *transport,
if (finish_command(&exporter))
die("Error while running fast-export");
- push_update_refs_status(data, remote_refs);
+ push_update_refs_status(data, remote_refs, flags);
return 0;
}
diff --git a/transport.c b/transport.c
index ca7bb441bf..325f03e1ee 100644
--- a/transport.c
+++ b/transport.c
@@ -1132,8 +1132,7 @@ int transport_push(struct transport *transport,
return transport->push(transport, refspec_nr, refspec, flags);
} else if (transport->push_refs) {
- struct ref *remote_refs =
- transport->get_refs_list(transport, 1);
+ struct ref *remote_refs;
struct ref *local_refs = get_local_heads();
int match_flags = MATCH_REFS_NONE;
int verbose = (transport->verbose > 0);
@@ -1142,6 +1141,11 @@ int transport_push(struct transport *transport,
int pretend = flags & TRANSPORT_PUSH_DRY_RUN;
int push_ret, ret, err;
+ if (check_push_refs(local_refs, refspec_nr, refspec) < 0)
+ return -1;
+
+ remote_refs = transport->get_refs_list(transport, 1);
+
if (flags & TRANSPORT_PUSH_ALL)
match_flags |= MATCH_REFS_ALL;
if (flags & TRANSPORT_PUSH_MIRROR)
diff --git a/unpack-trees.c b/unpack-trees.c
index 0692ebe16e..97fc995467 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -203,7 +203,7 @@ static int check_updates(struct unpack_trees_options *o)
total++;
}
- progress = start_progress_delay("Checking out files",
+ progress = start_progress_delay(_("Checking out files"),
total, 50, 1);
cnt = 0;
}
diff --git a/upload-pack.c b/upload-pack.c
index 0c44f6b292..286a9ed3ea 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -70,6 +70,14 @@ static ssize_t send_client_data(int fd, const char *data, ssize_t sz)
return sz;
}
+static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
+{
+ FILE *fp = cb_data;
+ if (graft->nr_parent == -1)
+ fprintf(fp, "--shallow %s\n", sha1_to_hex(graft->sha1));
+ return 0;
+}
+
static void create_pack_file(void)
{
struct child_process pack_objects;
@@ -81,12 +89,10 @@ static void create_pack_file(void)
const char *argv[12];
int i, arg = 0;
FILE *pipe_fd;
- char *shallow_file = NULL;
if (shallow_nr) {
- shallow_file = setup_temporary_shallow(NULL);
argv[arg++] = "--shallow-file";
- argv[arg++] = shallow_file;
+ argv[arg++] = "";
}
argv[arg++] = "pack-objects";
argv[arg++] = "--revs";
@@ -114,6 +120,9 @@ static void create_pack_file(void)
pipe_fd = xfdopen(pack_objects.in, "w");
+ if (shallow_nr)
+ for_each_commit_graft(write_one_shallow, pipe_fd);
+
for (i = 0; i < want_obj.nr; i++)
fprintf(pipe_fd, "%s\n",
sha1_to_hex(want_obj.objects[i].item->sha1));
@@ -242,11 +251,6 @@ static void create_pack_file(void)
error("git upload-pack: git-pack-objects died with error.");
goto fail;
}
- if (shallow_file) {
- if (*shallow_file)
- unlink(shallow_file);
- free(shallow_file);
- }
/* flush the data */
if (0 <= buffered) {
@@ -796,7 +800,7 @@ int main(int argc, char **argv)
packet_trace_identity("upload-pack");
git_extract_argv0_path(argv[0]);
- read_replace_refs = 0;
+ check_replace_refs = 0;
for (i = 1; i < argc; i++) {
char *arg = argv[i];
diff --git a/userdiff.c b/userdiff.c
index 10b61ec37d..fad52d6392 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -125,15 +125,13 @@ PATTERNS("tex", "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$",
"\\\\[a-zA-Z@]+|\\\\.|[a-zA-Z0-9\x80-\xff]+"),
PATTERNS("cpp",
/* Jump targets or access declarations */
- "!^[ \t]*[A-Za-z_][A-Za-z_0-9]*:.*$\n"
- /* C/++ functions/methods at top level */
- "^([A-Za-z_][A-Za-z_0-9]*([ \t*]+[A-Za-z_][A-Za-z_0-9]*([ \t]*::[ \t]*[^[:space:]]+)?){1,}[ \t]*\\([^;]*)$\n"
- /* compound type at top level */
- "^((struct|class|enum)[^;]*)$",
+ "!^[ \t]*[A-Za-z_][A-Za-z_0-9]*:[[:space:]]*($|/[/*])\n"
+ /* functions/methods, variables, and compounds at top level */
+ "^((::[[:space:]]*)?[A-Za-z_].*)$",
/* -- */
"[a-zA-Z_][a-zA-Z0-9_]*"
- "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?"
- "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"),
+ "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lLuU]*"
+ "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->\\*?|\\.\\*"),
PATTERNS("csharp",
/* Keywords */
"!^[ \t]*(do|while|for|if|else|instanceof|new|return|switch|case|throw|catch|using)\n"
diff --git a/utf8.c b/utf8.c
index 0d20e0acb2..a831d50899 100644
--- a/utf8.c
+++ b/utf8.c
@@ -5,8 +5,8 @@
/* This code is originally from http://www.cl.cam.ac.uk/~mgk25/ucs/ */
struct interval {
- int first;
- int last;
+ ucs_char_t first;
+ ucs_char_t last;
};
size_t display_mode_esc_sequence_len(const char *s)
@@ -529,7 +529,7 @@ char *reencode_string_iconv(const char *in, size_t insz, iconv_t conv, int *outs
while (1) {
size_t cnt = iconv(conv, &cp, &insz, &outpos, &outsz);
- if (cnt == -1) {
+ if (cnt == (size_t) -1) {
size_t sofar;
if (errno != E2BIG) {
free(out);
diff --git a/versioncmp.c b/versioncmp.c
new file mode 100644
index 0000000000..7511e08271
--- /dev/null
+++ b/versioncmp.c
@@ -0,0 +1,93 @@
+#include "cache.h"
+
+/*
+ * versioncmp(): copied from string/strverscmp.c in glibc commit
+ * ee9247c38a8def24a59eb5cfb7196a98bef8cfdc, reformatted to Git coding
+ * style. The implementation is under LGPL-2.1 and Git relicenses it
+ * to GPLv2.
+ */
+
+/*
+ * states: S_N: normal, S_I: comparing integral part, S_F: comparing
+ * fractionnal parts, S_Z: idem but with leading Zeroes only
+ */
+#define S_N 0x0
+#define S_I 0x3
+#define S_F 0x6
+#define S_Z 0x9
+
+/* result_type: CMP: return diff; LEN: compare using len_diff/diff */
+#define CMP 2
+#define LEN 3
+
+
+/*
+ * Compare S1 and S2 as strings holding indices/version numbers,
+ * returning less than, equal to or greater than zero if S1 is less
+ * than, equal to or greater than S2 (for more info, see the texinfo
+ * doc).
+ */
+
+int versioncmp(const char *s1, const char *s2)
+{
+ const unsigned char *p1 = (const unsigned char *) s1;
+ const unsigned char *p2 = (const unsigned char *) s2;
+ unsigned char c1, c2;
+ int state, diff;
+
+ /*
+ * Symbol(s) 0 [1-9] others
+ * Transition (10) 0 (01) d (00) x
+ */
+ static const uint8_t next_state[] = {
+ /* state x d 0 */
+ /* S_N */ S_N, S_I, S_Z,
+ /* S_I */ S_N, S_I, S_I,
+ /* S_F */ S_N, S_F, S_F,
+ /* S_Z */ S_N, S_F, S_Z
+ };
+
+ static const int8_t result_type[] = {
+ /* state x/x x/d x/0 d/x d/d d/0 0/x 0/d 0/0 */
+
+ /* S_N */ CMP, CMP, CMP, CMP, LEN, CMP, CMP, CMP, CMP,
+ /* S_I */ CMP, -1, -1, +1, LEN, LEN, +1, LEN, LEN,
+ /* S_F */ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+ /* S_Z */ CMP, +1, +1, -1, CMP, CMP, -1, CMP, CMP
+ };
+
+ if (p1 == p2)
+ return 0;
+
+ c1 = *p1++;
+ c2 = *p2++;
+ /* Hint: '0' is a digit too. */
+ state = S_N + ((c1 == '0') + (isdigit (c1) != 0));
+
+ while ((diff = c1 - c2) == 0) {
+ if (c1 == '\0')
+ return diff;
+
+ state = next_state[state];
+ c1 = *p1++;
+ c2 = *p2++;
+ state += (c1 == '0') + (isdigit (c1) != 0);
+ }
+
+ state = result_type[state * 3 + (((c2 == '0') + (isdigit (c2) != 0)))];
+
+ switch (state) {
+ case CMP:
+ return diff;
+
+ case LEN:
+ while (isdigit (*p1++))
+ if (!isdigit (*p2++))
+ return 1;
+
+ return isdigit (*p2) ? -1 : diff;
+
+ default:
+ return state;
+ }
+}
diff --git a/ws.c b/ws.c
index b498d7599d..ea4b2b1dfd 100644
--- a/ws.c
+++ b/ws.c
@@ -33,11 +33,8 @@ unsigned parse_whitespace_rule(const char *string)
int negated = 0;
string = string + strspn(string, ", \t\n\r");
- ep = strchr(string, ',');
- if (!ep)
- len = strlen(string);
- else
- len = ep - string;
+ ep = strchrnul(string, ',');
+ len = ep - string;
if (*string == '-') {
negated = 1;
diff --git a/wt-status.c b/wt-status.c
index a452407dad..e1827faf07 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -17,7 +17,7 @@
#include "strbuf.h"
#include "utf8.h"
-static char cut_line[] =
+static const char cut_line[] =
"------------------------ >8 ------------------------\n";
static char default_wt_status_colors[][COLOR_MAXLEN] = {
@@ -245,53 +245,92 @@ static void wt_status_print_trailer(struct wt_status *s)
#define quote_path quote_path_relative
-static void wt_status_print_unmerged_data(struct wt_status *s,
- struct string_list_item *it)
+static const char *wt_status_unmerged_status_string(int stagemask)
{
- const char *c = color(WT_STATUS_UNMERGED, s);
- struct wt_status_change_data *d = it->util;
- struct strbuf onebuf = STRBUF_INIT;
- const char *one, *how = _("bug");
-
- one = quote_path(it->string, s->prefix, &onebuf);
- status_printf(s, color(WT_STATUS_HEADER, s), "\t");
- switch (d->stagemask) {
- case 1: how = _("both deleted:"); break;
- case 2: how = _("added by us:"); break;
- case 3: how = _("deleted by them:"); break;
- case 4: how = _("added by them:"); break;
- case 5: how = _("deleted by us:"); break;
- case 6: how = _("both added:"); break;
- case 7: how = _("both modified:"); break;
+ switch (stagemask) {
+ case 1:
+ return _("both deleted:");
+ case 2:
+ return _("added by us:");
+ case 3:
+ return _("deleted by them:");
+ case 4:
+ return _("added by them:");
+ case 5:
+ return _("deleted by us:");
+ case 6:
+ return _("both added:");
+ case 7:
+ return _("both modified:");
+ default:
+ die(_("bug: unhandled unmerged status %x"), stagemask);
}
- status_printf_more(s, c, "%-20s%s\n", how, one);
- strbuf_release(&onebuf);
}
static const char *wt_status_diff_status_string(int status)
{
switch (status) {
case DIFF_STATUS_ADDED:
- return _("new file");
+ return _("new file:");
case DIFF_STATUS_COPIED:
- return _("copied");
+ return _("copied:");
case DIFF_STATUS_DELETED:
- return _("deleted");
+ return _("deleted:");
case DIFF_STATUS_MODIFIED:
- return _("modified");
+ return _("modified:");
case DIFF_STATUS_RENAMED:
- return _("renamed");
+ return _("renamed:");
case DIFF_STATUS_TYPE_CHANGED:
- return _("typechange");
+ return _("typechange:");
case DIFF_STATUS_UNKNOWN:
- return _("unknown");
+ return _("unknown:");
case DIFF_STATUS_UNMERGED:
- return _("unmerged");
+ return _("unmerged:");
default:
return NULL;
}
}
+static int maxwidth(const char *(*label)(int), int minval, int maxval)
+{
+ int result = 0, i;
+
+ for (i = minval; i <= maxval; i++) {
+ const char *s = label(i);
+ int len = s ? utf8_strwidth(s) : 0;
+ if (len > result)
+ result = len;
+ }
+ return result;
+}
+
+static void wt_status_print_unmerged_data(struct wt_status *s,
+ struct string_list_item *it)
+{
+ const char *c = color(WT_STATUS_UNMERGED, s);
+ struct wt_status_change_data *d = it->util;
+ struct strbuf onebuf = STRBUF_INIT;
+ static char *padding;
+ static int label_width;
+ const char *one, *how;
+ int len;
+
+ if (!padding) {
+ label_width = maxwidth(wt_status_unmerged_status_string, 1, 7);
+ label_width += strlen(" ");
+ padding = xmallocz(label_width);
+ memset(padding, ' ', label_width);
+ }
+
+ one = quote_path(it->string, s->prefix, &onebuf);
+ status_printf(s, color(WT_STATUS_HEADER, s), "\t");
+
+ how = wt_status_unmerged_status_string(d->stagemask);
+ len = label_width - utf8_strwidth(how);
+ status_printf_more(s, c, "%s%.*s%s\n", how, len, padding, one);
+ strbuf_release(&onebuf);
+}
+
static void wt_status_print_change_data(struct wt_status *s,
int change_type,
struct string_list_item *it)
@@ -305,21 +344,16 @@ static void wt_status_print_change_data(struct wt_status *s,
struct strbuf onebuf = STRBUF_INIT, twobuf = STRBUF_INIT;
struct strbuf extra = STRBUF_INIT;
static char *padding;
+ static int label_width;
const char *what;
int len;
if (!padding) {
- int width = 0;
- /* If DIFF_STATUS_* uses outside this range, we're in trouble */
- for (status = 'A'; status <= 'Z'; status++) {
- what = wt_status_diff_status_string(status);
- len = what ? strlen(what) : 0;
- if (len > width)
- width = len;
- }
- width += 2; /* colon and a space */
- padding = xmallocz(width);
- memset(padding, ' ', width);
+ /* If DIFF_STATUS_* uses outside the range [A..Z], we're in trouble */
+ label_width = maxwidth(wt_status_diff_status_string, 'A', 'Z');
+ label_width += strlen(" ");
+ padding = xmallocz(label_width);
+ memset(padding, ' ', label_width);
}
one_name = two_name = it->string;
@@ -355,14 +389,13 @@ static void wt_status_print_change_data(struct wt_status *s,
what = wt_status_diff_status_string(status);
if (!what)
die(_("bug: unhandled diff status %c"), status);
- /* 1 for colon, which is not part of "what" */
- len = strlen(padding) - (utf8_strwidth(what) + 1);
+ len = label_width - utf8_strwidth(what);
assert(len >= 0);
if (status == DIFF_STATUS_COPIED || status == DIFF_STATUS_RENAMED)
- status_printf_more(s, c, "%s:%.*s%s -> %s",
+ status_printf_more(s, c, "%s%.*s%s -> %s",
what, len, padding, one, two);
else
- status_printf_more(s, c, "%s:%.*s%s",
+ status_printf_more(s, c, "%s%.*s%s",
what, len, padding, one);
if (extra.len) {
status_printf_more(s, color(WT_STATUS_HEADER, s), "%s", extra.buf);
@@ -808,6 +841,17 @@ void wt_status_truncate_message_at_cut_line(struct strbuf *buf)
strbuf_release(&pattern);
}
+void wt_status_add_cut_line(FILE *fp)
+{
+ const char *explanation = _("Do not touch the line above.\nEverything below will be removed.");
+ struct strbuf buf = STRBUF_INIT;
+
+ fprintf(fp, "%c %s", comment_line_char, cut_line);
+ strbuf_add_commented_lines(&buf, explanation, strlen(explanation));
+ fputs(buf.buf, fp);
+ strbuf_release(&buf);
+}
+
static void wt_status_print_verbose(struct wt_status *s)
{
struct rev_info rev;
@@ -833,14 +877,8 @@ static void wt_status_print_verbose(struct wt_status *s)
* diff before committing.
*/
if (s->fp != stdout) {
- const char *explanation = _("Do not touch the line above.\nEverything below will be removed.");
- struct strbuf buf = STRBUF_INIT;
-
rev.diffopt.use_color = 0;
- fprintf(s->fp, "%c %s", comment_line_char, cut_line);
- strbuf_add_commented_lines(&buf, explanation, strlen(explanation));
- fputs(buf.buf, s->fp);
- strbuf_release(&buf);
+ wt_status_add_cut_line(s->fp);
}
run_diff_index(&rev, 1);
}
diff --git a/wt-status.h b/wt-status.h
index 30a4812583..b56ce3f035 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -92,6 +92,7 @@ struct wt_status_state {
};
void wt_status_truncate_message_at_cut_line(struct strbuf *);
+void wt_status_add_cut_line(FILE *fp);
void wt_status_prepare(struct wt_status *s);
void wt_status_print(struct wt_status *s);
void wt_status_collect(struct wt_status *s);