summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/RelNotes/2.41.0.txt46
-rw-r--r--Documentation/config/sendemail.txt1
-rwxr-xr-xDocumentation/doc-diff2
-rw-r--r--Documentation/git-credential.txt6
-rw-r--r--Documentation/git-interpret-trailers.txt97
-rw-r--r--Documentation/git-name-rev.txt11
-rw-r--r--Documentation/git-push.txt3
-rw-r--r--Documentation/git-send-email.txt19
-rw-r--r--Documentation/git.txt6
-rw-r--r--Documentation/gitattributes.txt59
-rw-r--r--Documentation/githooks.txt27
-rw-r--r--Documentation/gitignore.txt4
-rw-r--r--Documentation/gittutorial.txt129
-rw-r--r--Documentation/manpage-normal.xsl16
-rw-r--r--add-interactive.c1
-rw-r--r--alloc.c1
-rw-r--r--apply.c3
-rw-r--r--apply.h2
-rw-r--r--archive-zip.c2
-rw-r--r--archive.c2
-rw-r--r--attr.c1
-rw-r--r--base85.c3
-rw-r--r--base85.h7
-rw-r--r--bloom.c1
-rw-r--r--branch.c28
-rw-r--r--branch.h8
-rw-r--r--builtin/apply.c1
-rw-r--r--builtin/archive.c1
-rw-r--r--builtin/bisect.c1
-rw-r--r--builtin/branch.c71
-rw-r--r--builtin/bundle.c2
-rw-r--r--builtin/check-attr.c1
-rw-r--r--builtin/check-ignore.c1
-rw-r--r--builtin/checkout-index.c1
-rw-r--r--builtin/checkout.c1
-rw-r--r--builtin/clean.c1
-rw-r--r--builtin/clone.c2
-rw-r--r--builtin/config.c1
-rw-r--r--builtin/credential-cache--daemon.c3
-rw-r--r--builtin/credential-cache.c1
-rw-r--r--builtin/credential-store.c1
-rw-r--r--builtin/diff-tree.c1
-rw-r--r--builtin/diff.c1
-rw-r--r--builtin/difftool.c1
-rw-r--r--builtin/fetch.c1
-rw-r--r--builtin/for-each-repo.c2
-rw-r--r--builtin/fsck.c10
-rw-r--r--builtin/gc.c1
-rw-r--r--builtin/help.c1
-rw-r--r--builtin/init-db.c2
-rw-r--r--builtin/log.c1
-rw-r--r--builtin/ls-remote.c1
-rw-r--r--builtin/merge-index.c1
-rw-r--r--builtin/merge-recursive.c2
-rw-r--r--builtin/merge-tree.c1
-rw-r--r--builtin/mv.c1
-rw-r--r--builtin/name-rev.c6
-rw-r--r--builtin/pull.c2
-rw-r--r--builtin/push.c9
-rw-r--r--builtin/read-tree.c1
-rw-r--r--builtin/receive-pack.c1
-rw-r--r--builtin/repack.c1
-rw-r--r--builtin/rerere.c1
-rw-r--r--builtin/rm.c2
-rw-r--r--builtin/show-branch.c2
-rw-r--r--builtin/show-index.c2
-rw-r--r--builtin/update-index.c3
-rw-r--r--builtin/update-ref.c2
-rw-r--r--builtin/update-server-info.c1
-rw-r--r--builtin/upload-archive.c1
-rw-r--r--builtin/worktree.c2
-rw-r--r--builtin/write-tree.c1
-rw-r--r--bundle-uri.c3
-rw-r--r--cache.h122
-rw-r--r--checkout.c1
-rw-r--r--checkout.h2
-rw-r--r--chunk-format.c1
-rw-r--r--chunk-format.h2
-rw-r--r--color.c3
-rw-r--r--combine-diff.c3
-rw-r--r--commit-graph.c1
-rw-r--r--commit.c58
-rw-r--r--commit.h11
-rw-r--r--common-main.c4
-rw-r--r--compat/fsmonitor/fsm-health-darwin.c2
-rw-r--r--compat/fsmonitor/fsm-ipc-darwin.c4
-rw-r--r--compat/fsmonitor/fsm-ipc-win32.c1
-rw-r--r--compat/fsmonitor/fsm-listen-darwin.c3
-rw-r--r--compat/mingw.c1
-rw-r--r--compat/precompose_utf8.c1
-rw-r--r--compat/win32/trace2_win32_process_info.c1
-rw-r--r--config.c3
-rw-r--r--contrib/credential/gnome-keyring/.gitignore1
-rw-r--r--contrib/credential/gnome-keyring/Makefile25
-rw-r--r--contrib/credential/gnome-keyring/git-credential-gnome-keyring.c470
-rw-r--r--contrib/credential/libsecret/.gitignore1
-rw-r--r--contrib/credential/libsecret/git-credential-libsecret.c15
-rw-r--r--contrib/credential/osxkeychain/git-credential-osxkeychain.c10
-rw-r--r--contrib/credential/wincred/git-credential-wincred.c107
-rw-r--r--convert.c1
-rw-r--r--convert.h2
-rw-r--r--copy.c4
-rw-r--r--copy.h10
-rw-r--r--credential.c11
-rw-r--r--credential.h1
-rw-r--r--csum-file.c1
-rw-r--r--csum-file.h2
-rw-r--r--daemon.c3
-rw-r--r--date.c3
-rwxr-xr-xdetect-compiler10
-rw-r--r--diagnose.c2
-rw-r--r--diff-lib.c1
-rw-r--r--diff.c36
-rw-r--r--diff.h1
-rw-r--r--diffcore.h2
-rw-r--r--dir.c2
-rw-r--r--dir.h15
-rw-r--r--editor.c1
-rw-r--r--entry.c1
-rw-r--r--environment.c3
-rw-r--r--exec-cmd.c1
-rw-r--r--fetch-pack.c1
-rw-r--r--fsck.c1
-rw-r--r--fsmonitor--daemon.h1
-rw-r--r--fsmonitor-ipc.c1
-rwxr-xr-xgit-send-email.perl185
-rwxr-xr-xgitk-git/gitk36
-rw-r--r--gpg-interface.c2
-rw-r--r--grep.c1
-rw-r--r--hash-ll.h276
-rw-r--r--hash-lookup.c1
-rw-r--r--hash.h273
-rw-r--r--hashmap.h2
-rw-r--r--hex.c1
-rw-r--r--hex.h2
-rw-r--r--hook.c1
-rw-r--r--http-push.c2
-rw-r--r--khash.h1
-rw-r--r--line-log.c1
-rw-r--r--ll-merge.c3
-rw-r--r--log-tree.c1
-rw-r--r--ls-refs.c1
-rw-r--r--match-trees.c3
-rw-r--r--match-trees.h10
-rw-r--r--merge-ort-wrappers.c2
-rw-r--r--merge-ort.c1
-rw-r--r--merge-ort.h2
-rw-r--r--merge-recursive.c2
-rw-r--r--merge.c1
-rw-r--r--midx.c2
-rw-r--r--negotiator/default.c40
-rw-r--r--negotiator/skipping.c23
-rw-r--r--notes-cache.c1
-rw-r--r--notes-utils.c1
-rw-r--r--object-file.c3
-rw-r--r--object-file.h2
-rw-r--r--object-name.c2
-rw-r--r--object-store.h8
-rw-r--r--object.h3
-rw-r--r--oidmap.c1
-rw-r--r--oidtree.h2
-rw-r--r--pack-bitmap-write.c2
-rw-r--r--pack-bitmap.c45
-rw-r--r--pack-bitmap.h2
-rw-r--r--packfile.c2
-rw-r--r--packfile.h16
-rw-r--r--parallel-checkout.c2
-rw-r--r--parse-options-cb.c1
-rw-r--r--parse-options.c1
-rw-r--r--pathspec.c2
-rw-r--r--pkt-line.c3
-rw-r--r--pkt-line.h2
-rw-r--r--preload-index.c1
-rw-r--r--progress.c1
-rw-r--r--protocol-caps.c2
-rw-r--r--range-diff.c2
-rw-r--r--read-cache.c81
-rw-r--r--rebase-interactive.c1
-rw-r--r--ref-filter.c4
-rw-r--r--reflog.c2
-rw-r--r--refs/debug.c1
-rw-r--r--refs/files-backend.c2
-rw-r--r--refs/packed-backend.c1
-rw-r--r--refs/ref-cache.c2
-rw-r--r--refs/ref-cache.h3
-rw-r--r--refspec.c2
-rw-r--r--reftable/dump.c2
-rw-r--r--reftable/error.c1
-rw-r--r--reftable/publicbasics.c2
-rw-r--r--reftable/system.h2
-rw-r--r--reftable/tree.c2
-rw-r--r--reftable/tree_test.c1
-rw-r--r--rerere.c1
-rw-r--r--reset.h2
-rw-r--r--resolve-undo.c1
-rw-r--r--resolve-undo.h2
-rw-r--r--revision.h1
-rw-r--r--run-command.c1
-rw-r--r--send-pack.c1
-rw-r--r--sequencer.c7
-rw-r--r--server-info.c3
-rw-r--r--server-info.h7
-rw-r--r--setup.c1
-rw-r--r--split-index.c2
-rw-r--r--split-index.h2
-rw-r--r--strbuf.c1
-rw-r--r--submodule-config.c1
-rw-r--r--symlinks.c3
-rw-r--r--symlinks.h28
-rw-r--r--t/helper/test-bloom.c1
-rw-r--r--t/helper/test-cache-tree.c1
-rw-r--r--t/helper/test-ctype.c2
-rw-r--r--t/helper/test-dump-cache-tree.c2
-rw-r--r--t/helper/test-dump-fsmonitor.c1
-rw-r--r--t/helper/test-dump-untracked-cache.c1
-rw-r--r--t/helper/test-example-decorate.c1
-rw-r--r--t/helper/test-fsmonitor-client.c1
-rw-r--r--t/helper/test-lazy-init-name-hash.c1
-rw-r--r--t/helper/test-match-trees.c3
-rw-r--r--t/helper/test-mergesort.c2
-rw-r--r--t/helper/test-oid-array.c2
-rw-r--r--t/helper/test-oidmap.c1
-rw-r--r--t/helper/test-oidtree.c2
-rw-r--r--t/helper/test-parse-options.c2
-rw-r--r--t/helper/test-path-utils.c1
-rw-r--r--t/helper/test-read-cache.c1
-rw-r--r--t/helper/test-read-midx.c2
-rw-r--r--t/helper/test-reftable.c1
-rw-r--r--t/helper/test-scrap-cache-tree.c1
-rw-r--r--t/helper/test-string-list.c2
-rw-r--r--t/helper/test-submodule-config.c2
-rw-r--r--t/helper/test-submodule-nested-repo-config.c1
-rw-r--r--t/helper/test-submodule.c1
-rw-r--r--t/helper/test-trace2.c1
-rw-r--r--t/helper/test-write-cache.c1
-rw-r--r--t/lib-credential.sh59
-rwxr-xr-xt/t0020-crlf.sh38
-rwxr-xr-xt/t0035-safe-bare-repository.sh32
-rwxr-xr-xt/t0300-credentials.sh20
-rwxr-xr-xt/t0301-credential-cache.sh1
-rwxr-xr-xt/t1300-config.sh43
-rwxr-xr-xt/t1301-shared-repo.sh4
-rwxr-xr-xt/t1450-fsck.sh5
-rwxr-xr-xt/t1502-rev-parse-parseopt.sh6
-rwxr-xr-xt/t1507-rev-parse-upstream.sh3
-rwxr-xr-xt/t2019-checkout-ambiguous-ref.sh4
-rwxr-xr-xt/t3200-branch.sh29
-rwxr-xr-xt/t3202-show-branch.sh18
-rwxr-xr-xt/t3427-rebase-subtree.sh12
-rwxr-xr-xt/t3501-revert-cherry-pick.sh18
-rwxr-xr-xt/t4022-diff-rewrite.sh2
-rwxr-xr-xt/t4047-diff-dirstat.sh2
-rwxr-xr-xt/t4062-diff-pickaxe.sh2
-rwxr-xr-xt/t4212-log-corrupt.sh51
-rwxr-xr-xt/t5304-prune.sh16
-rwxr-xr-xt/t5326-multi-pack-bitmaps.sh44
-rwxr-xr-xt/t5523-push-upstream.sh12
-rwxr-xr-xt/t5543-atomic-push.sh5
-rwxr-xr-xt/t5583-push-branches.sh115
-rwxr-xr-xt/t6006-rev-list-format.sh2
-rwxr-xr-xt/t6501-freshen-objects.sh2
-rwxr-xr-xt/t7001-mv.sh37
-rwxr-xr-xt/t7300-clean.sh4
-rwxr-xr-xt/t9001-send-email.sh98
-rwxr-xr-xt/t9800-git-p4-basic.sh2
-rwxr-xr-xt/t9902-completion.sh30
-rw-r--r--t/test-lib-functions.sh9
-rw-r--r--trace2.c1
-rw-r--r--trace2/tr2_tgt_event.c1
-rw-r--r--trace2/tr2_tgt_normal.c1
-rw-r--r--trace2/tr2_tgt_perf.c1
-rw-r--r--tree-diff.c16
-rw-r--r--tree-walk.c2
-rw-r--r--tree-walk.h3
-rw-r--r--tree.c72
-rw-r--r--tree.h11
-rw-r--r--unpack-trees.c1
-rw-r--r--versioncmp.c3
-rw-r--r--versioncmp.h6
-rw-r--r--wrapper.c5
-rw-r--r--ws.c6
-rw-r--r--ws.h33
-rw-r--r--wt-status.c1
-rw-r--r--xdiff-interface.h2
284 files changed, 2110 insertions, 1583 deletions
diff --git a/Documentation/RelNotes/2.41.0.txt b/Documentation/RelNotes/2.41.0.txt
index 52bfa08511..fa2834bd72 100644
--- a/Documentation/RelNotes/2.41.0.txt
+++ b/Documentation/RelNotes/2.41.0.txt
@@ -83,6 +83,14 @@ UI, Workflows & Features
taken from the file specified by the "--contents" option shows it
differently from a line attributed to the working tree file.
+ * "git send-email" learned to give the e-mail headers to the validate
+ hook by passing an extra argument from the command line.
+
+ * The credential subsystem learns to help OAuth framework.
+
+ * The titles of manual pages used to be chomped at an unreasonably
+ short limit, which has been removed.
+
Performance, Internal Implementation, Development Support etc.
@@ -131,6 +139,27 @@ Performance, Internal Implementation, Development Support etc.
* strtok() and strtok_r() are banned in this codebase.
+ * The detect-compilers script to help auto-tweaking the build system
+ had trouble working with compilers whose version number has extra
+ suffixes. The script has been taught that certain suffixes (like
+ "-win32" in "gcc 10-win32") can be safely stripped as they share
+ the same features and bugs with the version without the suffix.
+
+ * ctype tests have been taught to test EOF, too.
+
+ * The implementation of credential helpers used fgets() over fixed
+ size buffers to read protocol messages, causing the remainder of
+ the folded long line to trigger unexpected behaviour, which has
+ been corrected.
+
+ * The implementation of the default "negotiator", used to find common
+ ancestor over the network for object tranfer, used to be recursive;
+ it was updated to be iterative to conserve stackspace usage.
+
+ * Our custom callout formatter is no longer used in the documentation
+ formatting toolchain, as the upstream default ones give better
+ output these days.
+
Fixes since v2.40
-----------------
@@ -284,6 +313,18 @@ Fixes since v2.40
* A small API fix to the ort merge strategy backend.
(merge 000c4ceca7 en/ort-finalize-after-0-merges-fix later to maint).
+ * The commit object parser has been taught to be a bit more lenient
+ to parse timestamps on the author/committer line with a malformed
+ author/committer ident.
+ (merge 90ef0f14eb jk/parse-commit-with-malformed-ident later to maint).
+
+ * Retitle a test script with an overly narrow name.
+ (merge 8bb19c14fb ob/t3501-retitle later to maint).
+
+ * Doc update to clarify how text and eol attributes interact to
+ specify the end-of-line conversion.
+ (merge 6696077ace ah/doc-attributes-text later to maint).
+
* Other code cleanup, docfix, build fix, etc.
(merge f7111175df as/doc-markup-fix later to maint).
(merge 90ff7c9898 fc/test-aggregation-clean-up later to maint).
@@ -300,3 +341,8 @@ Fixes since v2.40
(merge 4833b08426 ow/ref-format-remove-unused-member later to maint).
(merge d0ea2ca1cf dw/doc-submittingpatches-grammofix later to maint).
(merge fd72637423 ar/t2024-checkout-output-fix later to maint).
+ (merge d45cbe3fe0 ob/sequencer-i18n-fix later to maint).
+ (merge b734fe49fd ob/messages-capitalize-exception later to maint).
+ (merge ad353d7e77 ma/gittutorial-fixes later to maint).
+ (merge a5855fd8d4 ar/test-cleanup-unused-file-creation-part2 later to maint).
+ (merge 0c5308af30 sd/doc-gitignore-and-rm-cached later to maint).
diff --git a/Documentation/config/sendemail.txt b/Documentation/config/sendemail.txt
index 51da7088a8..92a9ebe98c 100644
--- a/Documentation/config/sendemail.txt
+++ b/Documentation/config/sendemail.txt
@@ -61,6 +61,7 @@ sendemail.ccCmd::
sendemail.chainReplyTo::
sendemail.envelopeSender::
sendemail.from::
+sendemail.headerCmd::
sendemail.signedoffbycc::
sendemail.smtpPass::
sendemail.suppresscc::
diff --git a/Documentation/doc-diff b/Documentation/doc-diff
index 1694300e50..fb09e0ac0e 100755
--- a/Documentation/doc-diff
+++ b/Documentation/doc-diff
@@ -153,7 +153,7 @@ render_tree () {
make -j$parallel -C "$tmp/worktree" \
$makemanflags \
GIT_VERSION=omitted \
- SOURCE_DATE_EPOCH=0 \
+ GIT_DATE=1970-01-01 \
DESTDIR="$tmp/installed/$dname+" \
install-man &&
mv "$tmp/installed/$dname+" "$tmp/installed/$dname"
diff --git a/Documentation/git-credential.txt b/Documentation/git-credential.txt
index 3394c03611..0e6d9e85ec 100644
--- a/Documentation/git-credential.txt
+++ b/Documentation/git-credential.txt
@@ -156,6 +156,12 @@ Git understands the following attributes:
When reading credentials from helpers, `git credential fill` ignores expired
passwords. Represented as Unix time UTC, seconds since 1970.
+`oauth_refresh_token`::
+
+ An OAuth refresh token may accompany a password that is an OAuth access
+ token. Helpers must treat this attribute as confidential like the password
+ attribute. Git itself has no special behaviour for this attribute.
+
`url`::
When this special attribute is read by `git credential`, the
diff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt
index 22ff3a603e..4b97f812be 100644
--- a/Documentation/git-interpret-trailers.txt
+++ b/Documentation/git-interpret-trailers.txt
@@ -280,7 +280,7 @@ $ cat msg.txt
subject
message
-$ cat msg.txt | git interpret-trailers --trailer 'sign: Alice <alice@example.com>' --trailer 'sign: Bob <bob@example.com>'
+$ git interpret-trailers --trailer 'sign: Alice <alice@example.com>' --trailer 'sign: Bob <bob@example.com>' <msg.txt
subject
message
@@ -322,17 +322,30 @@ $ git interpret-trailers --trailer 'Cc: Alice <alice@example.com>' --trailer 'Re
'Signed-off-by: ' already, and show how it works:
+
------------
+$ cat msg1.txt
+subject
+
+message
$ git config trailer.sign.key "Signed-off-by: "
$ git config trailer.sign.ifmissing add
$ git config trailer.sign.ifexists doNothing
-$ git config trailer.sign.command 'echo "$(git config user.name) <$(git config user.email)>"'
-$ git interpret-trailers <<EOF
-> EOF
+$ git config trailer.sign.cmd 'echo "$(git config user.name) <$(git config user.email)>"'
+$ git interpret-trailers --trailer sign <msg1.txt
+subject
+
+message
Signed-off-by: Bob <bob@example.com>
-$ git interpret-trailers <<EOF
-> Signed-off-by: Alice <alice@example.com>
-> EOF
+$ cat msg2.txt
+subject
+
+message
+
+Signed-off-by: Alice <alice@example.com>
+$ git interpret-trailers --trailer sign <msg2.txt
+subject
+
+message
Signed-off-by: Alice <alice@example.com>
------------
@@ -357,15 +370,14 @@ Fix #42
$ cat ~/bin/glog-find-author
#!/bin/sh
test -n "$1" && git log --author="$1" --pretty="%an <%ae>" -1 || true
+$ cat msg.txt
+subject
+
+message
$ git config trailer.help.key "Helped-by: "
$ git config trailer.help.ifExists "addIfDifferentNeighbor"
$ git config trailer.help.cmd "~/bin/glog-find-author"
-$ git interpret-trailers --trailer="help:Junio" --trailer="help:Couder" <<EOF
-> subject
->
-> message
->
-> EOF
+$ git interpret-trailers --trailer="help:Junio" --trailer="help:Couder" <msg.txt
subject
message
@@ -382,15 +394,14 @@ Helped-by: Christian Couder <christian.couder@gmail.com>
$ cat ~/bin/glog-grep
#!/bin/sh
test -n "$1" && git log --grep "$1" --pretty=reference -1 || true
+$ cat msg.txt
+subject
+
+message
$ git config trailer.ref.key "Reference-to: "
$ git config trailer.ref.ifExists "replace"
$ git config trailer.ref.cmd "~/bin/glog-grep"
-$ git interpret-trailers --trailer="ref:Add copyright notices." <<EOF
-> subject
->
-> message
->
-> EOF
+$ git interpret-trailers --trailer="ref:Add copyright notices." <msg.txt
subject
message
@@ -402,17 +413,20 @@ Reference-to: 8bc9a0c769 (Add copyright notices., 2005-04-07)
commit that is related, and show how it works:
+
------------
+$ cat msg.txt
+subject
+
+message
+
+see: HEAD~2
+$ cat ~/bin/glog-ref
+#!/bin/sh
+git log -1 --oneline --format="%h (%s)" --abbrev-commit --abbrev=14
$ git config trailer.see.key "See-also: "
$ git config trailer.see.ifExists "replace"
$ git config trailer.see.ifMissing "doNothing"
-$ git config trailer.see.command "git log -1 --oneline --format=\"%h (%s)\" --abbrev-commit --abbrev=14 \$ARG"
-$ git interpret-trailers <<EOF
-> subject
->
-> message
->
-> see: HEAD~2
-> EOF
+$ git config trailer.see.cmd "glog-ref"
+$ git interpret-trailers --trailer=see <msg.txt
subject
message
@@ -427,22 +441,21 @@ See-also: fe3187489d69c4 (subject of related commit)
to add a 'git-version' trailer:
+
------------
-$ sed -e 's/ Z$/ /' >commit_template.txt <<EOF
-> ***subject***
->
-> ***message***
->
-> Fixes: Z
-> Cc: Z
-> Reviewed-by: Z
-> Signed-off-by: Z
-> EOF
+$ cat temp.txt
+***subject***
+
+***message***
+
+Fixes: Z
+Cc: Z
+Reviewed-by: Z
+Signed-off-by: Z
+$ sed -e 's/ Z$/ /' temp.txt > commit_template.txt
$ git config commit.template commit_template.txt
-$ cat >.git/hooks/commit-msg <<EOF
-> #!/bin/sh
-> git interpret-trailers --trim-empty --trailer "git-version: \$(git describe)" "\$1" > "\$1.new"
-> mv "\$1.new" "\$1"
-> EOF
+$ cat .git/hooks/commit-msg
+#!/bin/sh
+git interpret-trailers --trim-empty --trailer "git-version: \$(git describe)" "\$1" > "\$1.new"
+mv "\$1.new" "\$1"
$ chmod +x .git/hooks/commit-msg
------------
diff --git a/Documentation/git-name-rev.txt b/Documentation/git-name-rev.txt
index ec8a27ce8b..5c56c87025 100644
--- a/Documentation/git-name-rev.txt
+++ b/Documentation/git-name-rev.txt
@@ -10,7 +10,7 @@ SYNOPSIS
--------
[verse]
'git name-rev' [--tags] [--refs=<pattern>]
- ( --all | --stdin | <commit-ish>... )
+ ( --all | --annotate-stdin | <commit-ish>... )
DESCRIPTION
-----------
@@ -46,7 +46,8 @@ OPTIONS
Transform stdin by substituting all the 40-character SHA-1
hexes (say $hex) with "$hex ($rev_name)". When used with
--name-only, substitute with "$rev_name", omitting $hex
- altogether.
+ altogether. This option was called `--stdin` in older versions
+ of Git.
+
For example:
+
@@ -70,10 +71,6 @@ The full name after substitution is master,
while its tree object is 70d105cc79e63b81cfdcb08a15297c23e60b07ad
-----------
---stdin::
- This option is deprecated in favor of 'git name-rev --annotate-stdin'.
- They are functionally equivalent.
-
--name-only::
Instead of printing both the SHA-1 and the name, print only
the name. If given with --tags the usual tag prefix of
@@ -107,7 +104,7 @@ Now you are wiser, because you know that it happened 940 revisions before v0.99.
Another nice thing you can do is:
------------
-% git log | git name-rev --stdin
+% git log | git name-rev --annotate-stdin
------------
GIT
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 5bb1d5aae2..297927d866 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -9,7 +9,7 @@ git-push - Update remote refs along with associated objects
SYNOPSIS
--------
[verse]
-'git push' [--all | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
+'git push' [--all | --branches | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
[--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-v | --verbose]
[-u | --set-upstream] [-o <string> | --push-option=<string>]
[--[no-]signed|--signed=(true|false|if-asked)]
@@ -147,6 +147,7 @@ already exists on the remote side.
`tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`.
--all::
+--branches::
Push all branches (i.e. refs under `refs/heads/`); cannot be
used with other <refspec>.
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index b0f438ec99..492a82323d 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -320,6 +320,17 @@ Automating
Output of this command must be single email address per line.
Default is the value of `sendemail.ccCmd` configuration value.
+--header-cmd=<command>::
+ Specify a command that is executed once per outgoing message
+ and output RFC 2822 style header lines to be inserted into
+ them. When the `sendemail.headerCmd` configuration variable is
+ set, its value is always used. When --header-cmd is provided
+ at the command line, its value takes precedence over the
+ `sendemail.headerCmd` configuration variable.
+
+--no-header-cmd::
+ Disable any header command in use.
+
--[no-]chain-reply-to::
If this is set, each email will be sent as a reply to the previous
email sent. If disabled with "--no-chain-reply-to", all emails after
@@ -484,14 +495,10 @@ edit ~/.gitconfig to specify your account settings:
smtpServerPort = 587
----
-If you have multi-factor authentication set up on your Gmail account, you will
-need to generate an app-specific password for use with 'git send-email'. Visit
+If you have multi-factor authentication set up on your Gmail account, you can
+generate an app-specific password for use with 'git send-email'. Visit
https://security.google.com/settings/security/apppasswords to create it.
-If you do not have multi-factor authentication set up on your Gmail account,
-you will need to allow less secure app access. Visit
-https://myaccount.google.com/lesssecureapps to enable it.
-
Once your commits are ready to be sent to the mailing list, run the
following commands:
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 74973d3cc4..54b043899f 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -546,9 +546,9 @@ double-quotes and respecting backslash escapes. E.g., the value
`GIT_DEFAULT_HASH`::
If this variable is set, the default hash algorithm for new
- repositories will be set to this value. This value is currently
- ignored when cloning; the setting of the remote repository
- is used instead. The default is "sha1". THIS VARIABLE IS
+ repositories will be set to this value. This value is
+ ignored when cloning and the setting of the remote repository
+ is always used. The default is "sha1". THIS VARIABLE IS
EXPERIMENTAL! See `--object-format` in linkgit:git-init[1].
Git Commits
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index 39bfbca1ff..02a3ec83e4 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -120,20 +120,19 @@ repository upon 'git add' and 'git commit'.
`text`
^^^^^^
-This attribute enables and controls end-of-line normalization. When a
-text file is normalized, its line endings are converted to LF in the
-repository. To control what line ending style is used in the working
-directory, use the `eol` attribute for a single file and the
-`core.eol` configuration variable for all text files.
-Note that setting `core.autocrlf` to `true` or `input` overrides
-`core.eol` (see the definitions of those options in
-linkgit:git-config[1]).
+This attribute marks the path as a text file, which enables end-of-line
+conversion: When a matching file is added to the index, the file's line
+endings are normalized to LF in the index. Conversely, when the file is
+copied from the index to the working directory, its line endings may be
+converted from LF to CRLF depending on the `eol` attribute, the Git
+config, and the platform (see explanation of `eol` below).
Set::
Setting the `text` attribute on a path enables end-of-line
- normalization and marks the path as a text file. End-of-line
- conversion takes place without guessing the content type.
+ conversion on checkin and checkout as described above. Line endings
+ are normalized to LF in the index every time the file is checked in,
+ even if the file was previously added to Git with CRLF line endings.
Unset::
@@ -142,10 +141,11 @@ Unset::
Set to string value "auto"::
- When `text` is set to "auto", the path is marked for automatic
- end-of-line conversion. If Git decides that the content is
- text, its line endings are converted to LF on checkin.
- When the file has been committed with CRLF, no conversion is done.
+ When `text` is set to "auto", Git decides by itself whether the file
+ is text or binary. If it is text and the file was not already in
+ Git with CRLF endings, line endings are converted on checkin and
+ checkout as described above. Otherwise, no conversion is done on
+ checkin or checkout.
Unspecified::
@@ -159,26 +159,29 @@ unspecified.
`eol`
^^^^^
-This attribute sets a specific line-ending style to be used in the
-working directory. This attribute has effect only if the `text`
-attribute is set or unspecified, or if it is set to `auto`, the file is
-detected as text, and it is stored with LF endings in the index. Note
-that setting this attribute on paths which are in the index with CRLF
-line endings may make the paths to be considered dirty unless
-`text=auto` is set. Adding the path to the index again will normalize
-the line endings in the index.
+This attribute marks a path to use a specific line-ending style in the
+working tree when it is checked out. It has effect only if `text` or
+`text=auto` is set (see above), but specifying `eol` automatically sets
+`text` if `text` was left unspecified.
Set to string value "crlf"::
- This setting forces Git to normalize line endings for this
- file on checkin and convert them to CRLF when the file is
- checked out.
+ This setting converts the file's line endings in the working
+ directory to CRLF when the file is checked out.
Set to string value "lf"::
- This setting forces Git to normalize line endings to LF on
- checkin and prevents conversion to CRLF when the file is
- checked out.
+ This setting uses the same line endings in the working directory as
+ in the index when the file is checked out.
+
+Unspecified::
+
+ If the `eol` attribute is unspecified for a file, its line endings
+ in the working directory are determined by the `core.autocrlf` or
+ `core.eol` configuration variable (see the definitions of those
+ options in linkgit:git-config[1]). If `text` is set but neither of
+ those variables is, the default is `eol=crlf` on Windows and
+ `eol=lf` on all other platforms.
Backwards compatibility with `crlf` attribute
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index c8e55b2613..86f804720a 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -595,10 +595,29 @@ processed by rebase.
sendemail-validate
~~~~~~~~~~~~~~~~~~
-This hook is invoked by linkgit:git-send-email[1]. It takes a single parameter,
-the name of the file that holds the e-mail to be sent. Exiting with a
-non-zero status causes `git send-email` to abort before sending any
-e-mails.
+This hook is invoked by linkgit:git-send-email[1].
+
+It takes these command line arguments. They are,
+1. the name of the file which holds the contents of the email to be sent.
+2. The name of the file which holds the SMTP headers of the email.
+
+The SMTP headers are passed in the exact same way as they are passed to the
+user's Mail Transport Agent (MTA). In effect, the email given to the user's
+MTA, is the contents of $2 followed by the contents of $1.
+
+An example of a few common headers is shown below. Take notice of the
+capitalization and multi-line tab structure.
+
+ From: Example <from@example.com>
+ To: to@example.com
+ Cc: cc@example.com,
+ A <author@example.com>,
+ One <one@example.com>,
+ two@example.com
+ Subject: PATCH-STRING
+
+Exiting with a non-zero status causes `git send-email` to abort
+before sending any e-mails.
The following environment variables are set when executing the hook.
diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt
index f2738b10db..4c17f2356c 100644
--- a/Documentation/gitignore.txt
+++ b/Documentation/gitignore.txt
@@ -146,7 +146,9 @@ The purpose of gitignore files is to ensure that certain files
not tracked by Git remain untracked.
To stop tracking a file that is currently tracked, use
-'git rm --cached'.
+'git rm --cached' to remove the file from the index. The filename
+can then be added to the `.gitignore` file to stop the file from
+being reintroduced in later commits.
Git does not follow symbolic links when accessing a `.gitignore` file in
the working tree. This keeps behavior consistent when the file is
diff --git a/Documentation/gittutorial.txt b/Documentation/gittutorial.txt
index 0e0b863105..c7cadd8aaf 100644
--- a/Documentation/gittutorial.txt
+++ b/Documentation/gittutorial.txt
@@ -49,7 +49,7 @@ $ git config --global user.email you@yourdomain.example.com
Importing a new project
-----------------------
-Assume you have a tarball project.tar.gz with your initial work. You
+Assume you have a tarball `project.tar.gz` with your initial work. You
can place it under Git revision control as follows.
------------------------------------------------
@@ -65,10 +65,10 @@ Initialized empty Git repository in .git/
------------------------------------------------
You've now initialized the working directory--you may notice a new
-directory created, named ".git".
+directory created, named `.git`.
Next, tell Git to take a snapshot of the contents of all files under the
-current directory (note the '.'), with 'git add':
+current directory (note the `.`), with `git add`:
------------------------------------------------
$ git add .
@@ -76,7 +76,7 @@ $ git add .
This snapshot is now stored in a temporary staging area which Git calls
the "index". You can permanently store the contents of the index in the
-repository with 'git commit':
+repository with `git commit`:
------------------------------------------------
$ git commit
@@ -95,21 +95,20 @@ $ git add file1 file2 file3
------------------------------------------------
You are now ready to commit. You can see what is about to be committed
-using 'git diff' with the --cached option:
+using `git diff` with the `--cached` option:
------------------------------------------------
$ git diff --cached
------------------------------------------------
-(Without --cached, 'git diff' will show you any changes that
+(Without `--cached`, `git diff` will show you any changes that
you've made but not yet added to the index.) You can also get a brief
-summary of the situation with 'git status':
+summary of the situation with `git status`:
------------------------------------------------
$ git status
On branch master
Changes to be committed:
-Your branch is up to date with 'origin/master'.
(use "git restore --staged <file>..." to unstage)
modified: file1
@@ -128,7 +127,7 @@ $ git commit
This will again prompt you for a message describing the change, and then
record a new version of the project.
-Alternatively, instead of running 'git add' beforehand, you can use
+Alternatively, instead of running `git add` beforehand, you can use
------------------------------------------------
$ git commit -a
@@ -151,7 +150,7 @@ Git tracks content not files
Many revision control systems provide an `add` command that tells the
system to start tracking changes to a new file. Git's `add` command
-does something simpler and more powerful: 'git add' is used both for new
+does something simpler and more powerful: `git add` is used both for new
and newly modified files, and in both cases it takes a snapshot of the
given files and stages that content in the index, ready for inclusion in
the next commit.
@@ -182,7 +181,7 @@ Managing branches
-----------------
A single Git repository can maintain multiple branches of
-development. To create a new branch named "experimental", use
+development. To create a new branch named `experimental`, use
------------------------------------------------
$ git branch experimental
@@ -201,8 +200,8 @@ you'll get a list of all existing branches:
* master
------------------------------------------------
-The "experimental" branch is the one you just created, and the
-"master" branch is a default branch that was created for you
+The `experimental` branch is the one you just created, and the
+`master` branch is a default branch that was created for you
automatically. The asterisk marks the branch you are currently on;
type
@@ -210,8 +209,8 @@ type
$ git switch experimental
------------------------------------------------
-to switch to the experimental branch. Now edit a file, commit the
-change, and switch back to the master branch:
+to switch to the `experimental` branch. Now edit a file, commit the
+change, and switch back to the `master` branch:
------------------------------------------------
(edit file)
@@ -220,9 +219,9 @@ $ git switch master
------------------------------------------------
Check that the change you made is no longer visible, since it was
-made on the experimental branch and you're back on the master branch.
+made on the `experimental` branch and you're back on the `master` branch.
-You can make a different change on the master branch:
+You can make a different change on the `master` branch:
------------------------------------------------
(edit file)
@@ -230,7 +229,7 @@ $ git commit -a
------------------------------------------------
at this point the two branches have diverged, with different changes
-made in each. To merge the changes made in experimental into master, run
+made in each. To merge the changes made in `experimental` into `master`, run
------------------------------------------------
$ git merge experimental
@@ -258,16 +257,16 @@ $ gitk
will show a nice graphical representation of the resulting history.
-At this point you could delete the experimental branch with
+At this point you could delete the `experimental` branch with
------------------------------------------------
$ git branch -d experimental
------------------------------------------------
-This command ensures that the changes in the experimental branch are
+This command ensures that the changes in the `experimental` branch are
already in the current branch.
-If you develop on a branch crazy-idea, then regret it, you can always
+If you develop on a branch `crazy-idea`, then regret it, you can always
delete the branch with
-------------------------------------
@@ -281,7 +280,7 @@ Using Git for collaboration
---------------------------
Suppose that Alice has started a new project with a Git repository in
-/home/alice/project, and that Bob, who has a home directory on the
+`/home/alice/project`, and that Bob, who has a home directory on the
same machine, wants to contribute.
Bob begins with:
@@ -290,7 +289,7 @@ Bob begins with:
bob$ git clone /home/alice/project myrepo
------------------------------------------------
-This creates a new directory "myrepo" containing a clone of Alice's
+This creates a new directory `myrepo` containing a clone of Alice's
repository. The clone is on an equal footing with the original
project, possessing its own copy of the original project's history.
@@ -303,31 +302,31 @@ bob$ git commit -a
------------------------------------------------
When he's ready, he tells Alice to pull changes from the repository
-at /home/bob/myrepo. She does this with:
+at `/home/bob/myrepo`. She does this with:
------------------------------------------------
alice$ cd /home/alice/project
alice$ git pull /home/bob/myrepo master
------------------------------------------------
-This merges the changes from Bob's "master" branch into Alice's
+This merges the changes from Bob's `master` branch into Alice's
current branch. If Alice has made her own changes in the meantime,
then she may need to manually fix any conflicts.
-The "pull" command thus performs two operations: it fetches changes
+The `pull` command thus performs two operations: it fetches changes
from a remote branch, then merges them into the current branch.
Note that in general, Alice would want her local changes committed before
-initiating this "pull". If Bob's work conflicts with what Alice did since
+initiating this `pull`. If Bob's work conflicts with what Alice did since
their histories forked, Alice will use her working tree and the index to
resolve conflicts, and existing local changes will interfere with the
conflict resolution process (Git will still perform the fetch but will
refuse to merge -- Alice will have to get rid of her local changes in
some way and pull again when this happens).
-Alice can peek at what Bob did without merging first, using the "fetch"
+Alice can peek at what Bob did without merging first, using the `fetch`
command; this allows Alice to inspect what Bob did, using a special
-symbol "FETCH_HEAD", in order to determine if he has anything worth
+symbol `FETCH_HEAD`, in order to determine if he has anything worth
pulling, like this:
------------------------------------------------
@@ -336,10 +335,10 @@ alice$ git log -p HEAD..FETCH_HEAD
------------------------------------------------
This operation is safe even if Alice has uncommitted local changes.
-The range notation "HEAD..FETCH_HEAD" means "show everything that is reachable
-from the FETCH_HEAD but exclude anything that is reachable from HEAD".
-Alice already knows everything that leads to her current state (HEAD),
-and reviews what Bob has in his state (FETCH_HEAD) that she has not
+The range notation `HEAD..FETCH_HEAD` means "show everything that is reachable
+from the `FETCH_HEAD` but exclude anything that is reachable from `HEAD`".
+Alice already knows everything that leads to her current state (`HEAD`),
+and reviews what Bob has in his state (`FETCH_HEAD`) that she has not
seen with this command.
If Alice wants to visualize what Bob did since their histories forked
@@ -349,7 +348,7 @@ she can issue the following command:
$ gitk HEAD..FETCH_HEAD
------------------------------------------------
-This uses the same two-dot range notation we saw earlier with 'git log'.
+This uses the same two-dot range notation we saw earlier with `git log`.
Alice may want to view what both of them did since they forked.
She can use three-dot form instead of the two-dot form:
@@ -361,13 +360,13 @@ $ gitk HEAD...FETCH_HEAD
This means "show everything that is reachable from either one, but
exclude anything that is reachable from both of them".
-Please note that these range notation can be used with both gitk
-and "git log".
+Please note that these range notation can be used with both `gitk`
+and `git log`.
After inspecting what Bob did, if there is nothing urgent, Alice may
decide to continue working without pulling from Bob. If Bob's history
does have something Alice would immediately need, Alice may choose to
-stash her work-in-progress first, do a "pull", and then finally unstash
+stash her work-in-progress first, do a `pull`, and then finally unstash
her work-in-progress on top of the resulting history.
When you are working in a small closely knit group, it is not
@@ -379,8 +378,8 @@ it easier:
alice$ git remote add bob /home/bob/myrepo
------------------------------------------------
-With this, Alice can perform the first part of the "pull" operation
-alone using the 'git fetch' command without merging them with her own
+With this, Alice can perform the first part of the `pull` operation
+alone using the `git fetch` command without merging them with her own
branch, using:
-------------------------------------
@@ -388,7 +387,7 @@ alice$ git fetch bob
-------------------------------------
Unlike the longhand form, when Alice fetches from Bob using a
-remote repository shorthand set up with 'git remote', what was
+remote repository shorthand set up with `git remote`, what was
fetched is stored in a remote-tracking branch, in this case
`bob/master`. So after this:
@@ -397,10 +396,10 @@ alice$ git log -p master..bob/master
-------------------------------------
shows a list of all the changes that Bob made since he branched from
-Alice's master branch.
+Alice's `master` branch.
After examining those changes, Alice
-could merge the changes into her master branch:
+could merge the changes into her `master` branch:
-------------------------------------
alice$ git merge bob/master
@@ -432,12 +431,12 @@ bob$ git config --get remote.origin.url
/home/alice/project
-------------------------------------
-(The complete configuration created by 'git clone' is visible using
+(The complete configuration created by `git clone` is visible using
`git config -l`, and the linkgit:git-config[1] man page
explains the meaning of each option.)
-Git also keeps a pristine copy of Alice's master branch under the
-name "origin/master":
+Git also keeps a pristine copy of Alice's `master` branch under the
+name `origin/master`:
-------------------------------------
bob$ git branch -r
@@ -462,8 +461,8 @@ Exploring history
-----------------
Git history is represented as a series of interrelated commits. We
-have already seen that the 'git log' command can list those commits.
-Note that first line of each git log entry also gives a name for the
+have already seen that the `git log` command can list those commits.
+Note that first line of each `git log` entry also gives a name for the
commit:
-------------------------------------
@@ -475,7 +474,7 @@ Date: Tue May 16 17:18:22 2006 -0700
merge-base: Clarify the comments on post processing.
-------------------------------------
-We can give this name to 'git show' to see the details about this
+We can give this name to `git show` to see the details about this
commit.
-------------------------------------
@@ -514,7 +513,7 @@ You can also give commits names of your own; after running
$ git tag v2.5 1b2e1d63ff
-------------------------------------
-you can refer to 1b2e1d63ff by the name "v2.5". If you intend to
+you can refer to `1b2e1d63ff` by the name `v2.5`. If you intend to
share this name with other people (for example, to identify a release
version), you should create a "tag" object, and perhaps sign it; see
linkgit:git-tag[1] for details.
@@ -533,22 +532,22 @@ $ git reset --hard HEAD^ # reset your current branch and working
Be careful with that last command: in addition to losing any changes
in the working directory, it will also remove all later commits from
this branch. If this branch is the only branch containing those
-commits, they will be lost. Also, don't use 'git reset' on a
+commits, they will be lost. Also, don't use `git reset` on a
publicly-visible branch that other developers pull from, as it will
force needless merges on other developers to clean up the history.
-If you need to undo changes that you have pushed, use 'git revert'
+If you need to undo changes that you have pushed, use `git revert`
instead.
-The 'git grep' command can search for strings in any version of your
+The `git grep` command can search for strings in any version of your
project, so
-------------------------------------
$ git grep "hello" v2.5
-------------------------------------
-searches for all occurrences of "hello" in v2.5.
+searches for all occurrences of "hello" in `v2.5`.
-If you leave out the commit name, 'git grep' will search any of the
+If you leave out the commit name, `git grep` will search any of the
files it manages in your current directory. So
-------------------------------------
@@ -558,7 +557,7 @@ $ git grep "hello"
is a quick way to search just the files that are tracked by Git.
Many Git commands also take sets of commits, which can be specified
-in a number of ways. Here are some examples with 'git log':
+in a number of ways. Here are some examples with `git log`:
-------------------------------------
$ git log v2.5..v2.6 # commits between v2.5 and v2.6
@@ -568,16 +567,16 @@ $ git log v2.5.. Makefile # commits since v2.5 which modify
# Makefile
-------------------------------------
-You can also give 'git log' a "range" of commits where the first is not
+You can also give `git log` a "range" of commits where the first is not
necessarily an ancestor of the second; for example, if the tips of
-the branches "stable" and "master" diverged from a common
+the branches `stable` and `master` diverged from a common
commit some time ago, then
-------------------------------------
$ git log stable..master
-------------------------------------
-will list commits made in the master branch but not in the
+will list commits made in the `master` branch but not in the
stable branch, while
-------------------------------------
@@ -585,15 +584,15 @@ $ git log master..stable
-------------------------------------
will show the list of commits made on the stable branch but not
-the master branch.
+the `master` branch.
-The 'git log' command has a weakness: it must present commits in a
+The `git log` command has a weakness: it must present commits in a
list. When the history has lines of development that diverged and
-then merged back together, the order in which 'git log' presents
+then merged back together, the order in which `git log` presents
those commits is meaningless.
Most projects with multiple contributors (such as the Linux kernel,
-or Git itself) have frequent merges, and 'gitk' does a better job of
+or Git itself) have frequent merges, and `gitk` does a better job of
visualizing their history. For example,
-------------------------------------
@@ -601,7 +600,7 @@ $ gitk --since="2 weeks ago" drivers/
-------------------------------------
allows you to browse any commits from the last 2 weeks of commits
-that modified files under the "drivers" directory. (Note: you can
+that modified files under the `drivers` directory. (Note: you can
adjust gitk's fonts by holding down the control key while pressing
"-" or "+".)
@@ -613,7 +612,7 @@ of the file:
$ git diff v2.5:Makefile HEAD:Makefile.in
-------------------------------------
-You can also use 'git show' to see any such file:
+You can also use `git show` to see any such file:
-------------------------------------
$ git show v2.5:Makefile
@@ -649,7 +648,7 @@ digressions that may be interesting at this point are:
* linkgit:git-bisect[1]: When there is a regression in your
project, one way to track down the bug is by searching through
- the history to find the exact commit that's to blame. Git bisect
+ the history to find the exact commit that's to blame. `git bisect`
can help you perform a binary search for that commit. It is
smart enough to perform a close-to-optimal search even in the
case of complex non-linear history with lots of merged branches.
diff --git a/Documentation/manpage-normal.xsl b/Documentation/manpage-normal.xsl
index a9c7ec69f4..beb5ff8ec2 100644
--- a/Documentation/manpage-normal.xsl
+++ b/Documentation/manpage-normal.xsl
@@ -8,19 +8,7 @@
<xsl:param name="man.output.quietly" select="1"/>
<xsl:param name="refentry.meta.get.quietly" select="1"/>
-<!-- convert asciidoc callouts to man page format -->
-<xsl:template match="co">
- <xsl:value-of select="concat('\fB(',substring-after(@id,'-'),')\fR')"/>
-</xsl:template>
-<xsl:template match="calloutlist">
- <xsl:text>.sp&#10;</xsl:text>
- <xsl:apply-templates/>
- <xsl:text>&#10;</xsl:text>
-</xsl:template>
-<xsl:template match="callout">
- <xsl:value-of select="concat('\fB',substring-after(@arearefs,'-'),'. \fR')"/>
- <xsl:apply-templates/>
- <xsl:text>.br&#10;</xsl:text>
-</xsl:template>
+<!-- unset maximum length of title -->
+<xsl:param name="man.th.title.max.length"/>
</xsl:stylesheet>
diff --git a/add-interactive.c b/add-interactive.c
index 757a9929d4..de877ca052 100644
--- a/add-interactive.c
+++ b/add-interactive.c
@@ -12,6 +12,7 @@
#include "dir.h"
#include "run-command.h"
#include "prompt.h"
+#include "tree.h"
static void init_color(struct repository *r, struct add_i_state *s,
const char *section_and_slot, char *dst,
diff --git a/alloc.c b/alloc.c
index 2886aa9354..377e80f5dd 100644
--- a/alloc.c
+++ b/alloc.c
@@ -13,6 +13,7 @@
#include "blob.h"
#include "tree.h"
#include "commit.h"
+#include "repository.h"
#include "tag.h"
#include "alloc.h"
diff --git a/apply.c b/apply.c
index 3636bc14c2..6212ab3a1b 100644
--- a/apply.c
+++ b/apply.c
@@ -10,6 +10,7 @@
#include "cache.h"
#include "abspath.h"
#include "alloc.h"
+#include "base85.h"
#include "config.h"
#include "object-store.h"
#include "blob.h"
@@ -30,6 +31,8 @@
#include "apply.h"
#include "entry.h"
#include "setup.h"
+#include "symlinks.h"
+#include "ws.h"
#include "wrapper.h"
struct gitdiff_data {
diff --git a/apply.h b/apply.h
index b9f18ce87d..7cd38b1443 100644
--- a/apply.h
+++ b/apply.h
@@ -1,7 +1,7 @@
#ifndef APPLY_H
#define APPLY_H
-#include "hash.h"
+#include "hash-ll.h"
#include "lockfile.h"
#include "string-list.h"
#include "strmap.h"
diff --git a/archive-zip.c b/archive-zip.c
index ef538a90df..d0d065a312 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2006 Rene Scharfe
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "archive.h"
#include "gettext.h"
diff --git a/archive.c b/archive.c
index 8570cf37ff..641baad627 100644
--- a/archive.c
+++ b/archive.c
@@ -6,10 +6,12 @@
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "pretty.h"
#include "setup.h"
#include "refs.h"
#include "object-store.h"
#include "commit.h"
+#include "tree.h"
#include "tree-walk.h"
#include "attr.h"
#include "archive.h"
diff --git a/attr.c b/attr.c
index 2d8aeb8b58..ddf2b0cbc2 100644
--- a/attr.c
+++ b/attr.c
@@ -20,6 +20,7 @@
#include "object-store.h"
#include "setup.h"
#include "thread-utils.h"
+#include "tree-walk.h"
const char git_attr__true[] = "(builtin)true";
const char git_attr__false[] = "\0(builtin)false";
diff --git a/base85.c b/base85.c
index 5ca601ee14..bbacdca31b 100644
--- a/base85.c
+++ b/base85.c
@@ -1,4 +1,5 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "base85.h"
#undef DEBUG_85
diff --git a/base85.h b/base85.h
new file mode 100644
index 0000000000..c835086e09
--- /dev/null
+++ b/base85.h
@@ -0,0 +1,7 @@
+#ifndef BASE85_H
+#define BASE85_H
+
+int decode_85(char *dst, const char *line, int linelen);
+void encode_85(char *buf, const unsigned char *data, int bytes);
+
+#endif /* BASE85_H */
diff --git a/bloom.c b/bloom.c
index d0730525da..aef6b5fea2 100644
--- a/bloom.c
+++ b/bloom.c
@@ -6,6 +6,7 @@
#include "hashmap.h"
#include "commit-graph.h"
#include "commit.h"
+#include "commit-slab.h"
define_commit_slab(bloom_filter_slab, struct bloom_filter);
diff --git a/branch.c b/branch.c
index 7df982693a..ba3914adf5 100644
--- a/branch.c
+++ b/branch.c
@@ -9,6 +9,7 @@
#include "refs.h"
#include "refspec.h"
#include "remote.h"
+#include "repository.h"
#include "sequencer.h"
#include "commit.h"
#include "worktree.h"
@@ -839,30 +840,3 @@ void die_if_checked_out(const char *branch, int ignore_current_worktree)
free_worktrees(worktrees);
}
-
-int replace_each_worktree_head_symref(const char *oldref, const char *newref,
- const char *logmsg)
-{
- int ret = 0;
- struct worktree **worktrees = get_worktrees();
- int i;
-
- for (i = 0; worktrees[i]; i++) {
- struct ref_store *refs;
-
- if (worktrees[i]->is_detached)
- continue;
- if (!worktrees[i]->head_ref)
- continue;
- if (strcmp(oldref, worktrees[i]->head_ref))
- continue;
-
- refs = get_worktree_ref_store(worktrees[i]);
- if (refs_create_symref(refs, "HEAD", newref, logmsg))
- ret = error(_("HEAD of working tree %s is not updated"),
- worktrees[i]->path);
- }
-
- free_worktrees(worktrees);
- return ret;
-}
diff --git a/branch.h b/branch.h
index ef56103c05..30c01aed73 100644
--- a/branch.h
+++ b/branch.h
@@ -155,12 +155,4 @@ int read_branch_desc(struct strbuf *, const char *branch_name);
*/
void die_if_checked_out(const char *branch, int ignore_current_worktree);
-/*
- * Update all per-worktree HEADs pointing at the old ref to point the new ref.
- * This will be used when renaming a branch. Returns 0 if successful, non-zero
- * otherwise.
- */
-int replace_each_worktree_head_symref(const char *oldref, const char *newref,
- const char *logmsg);
-
#endif
diff --git a/builtin/apply.c b/builtin/apply.c
index fe72c0ec3e..e3ff02a09e 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -2,6 +2,7 @@
#include "builtin.h"
#include "gettext.h"
#include "parse-options.h"
+#include "repository.h"
#include "apply.h"
static const char * const apply_usage[] = {
diff --git a/builtin/archive.c b/builtin/archive.c
index d13934f1a8..b0eaa3c14a 100644
--- a/builtin/archive.c
+++ b/builtin/archive.c
@@ -9,6 +9,7 @@
#include "transport.h"
#include "parse-options.h"
#include "pkt-line.h"
+#include "repository.h"
#include "sideband.h"
static void create_output_file(const char *output_file)
diff --git a/builtin/bisect.c b/builtin/bisect.c
index 4b2143d455..4812450c39 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -1,5 +1,6 @@
#include "builtin.h"
#include "cache.h"
+#include "copy.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
diff --git a/builtin/branch.c b/builtin/branch.c
index 501c47657c..e6c2655af6 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -512,9 +512,9 @@ static void print_current_branch_name(void)
die(_("HEAD (%s) points outside of refs/heads/"), refname);
}
-static void reject_rebase_or_bisect_branch(const char *target)
+static void reject_rebase_or_bisect_branch(struct worktree **worktrees,
+ const char *target)
{
- struct worktree **worktrees = get_worktrees();
int i;
for (i = 0; worktrees[i]; i++) {
@@ -531,17 +531,50 @@ static void reject_rebase_or_bisect_branch(const char *target)
die(_("Branch %s is being bisected at %s"),
target, wt->path);
}
+}
- free_worktrees(worktrees);
+/*
+ * Update all per-worktree HEADs pointing at the old ref to point the new ref.
+ * This will be used when renaming a branch. Returns 0 if successful, non-zero
+ * otherwise.
+ */
+static int replace_each_worktree_head_symref(struct worktree **worktrees,
+ const char *oldref, const char *newref,
+ const char *logmsg)
+{
+ int ret = 0;
+ int i;
+
+ for (i = 0; worktrees[i]; i++) {
+ struct ref_store *refs;
+
+ if (worktrees[i]->is_detached)
+ continue;
+ if (!worktrees[i]->head_ref)
+ continue;
+ if (strcmp(oldref, worktrees[i]->head_ref))
+ continue;
+
+ refs = get_worktree_ref_store(worktrees[i]);
+ if (refs_create_symref(refs, "HEAD", newref, logmsg))
+ ret = error(_("HEAD of working tree %s is not updated"),
+ worktrees[i]->path);
+ }
+
+ return ret;
}
+#define IS_HEAD 1
+#define IS_ORPHAN 2
+
static void copy_or_rename_branch(const char *oldname, const char *newname, int copy, int force)
{
struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT;
struct strbuf oldsection = STRBUF_INIT, newsection = STRBUF_INIT;
const char *interpreted_oldname = NULL;
const char *interpreted_newname = NULL;
- int recovery = 0;
+ int recovery = 0, oldref_usage = 0;
+ struct worktree **worktrees = get_worktrees();
if (strbuf_check_branch_ref(&oldref, oldname)) {
/*
@@ -554,8 +587,19 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
die(_("Invalid branch name: '%s'"), oldname);
}
- if ((copy || strcmp(head, oldname)) && !ref_exists(oldref.buf)) {
- if (copy && !strcmp(head, oldname))
+ for (int i = 0; worktrees[i]; i++) {
+ struct worktree *wt = worktrees[i];
+
+ if (wt->head_ref && !strcmp(oldref.buf, wt->head_ref)) {
+ oldref_usage |= IS_HEAD;
+ if (is_null_oid(&wt->head_oid))
+ oldref_usage |= IS_ORPHAN;
+ break;
+ }
+ }
+
+ if ((copy || !(oldref_usage & IS_HEAD)) && !ref_exists(oldref.buf)) {
+ if (oldref_usage & IS_HEAD)
die(_("No commit on branch '%s' yet."), oldname);
else
die(_("No branch named '%s'."), oldname);
@@ -570,7 +614,7 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
else
validate_new_branchname(newname, &newref, force);
- reject_rebase_or_bisect_branch(oldref.buf);
+ reject_rebase_or_bisect_branch(worktrees, oldref.buf);
if (!skip_prefix(oldref.buf, "refs/heads/", &interpreted_oldname) ||
!skip_prefix(newref.buf, "refs/heads/", &interpreted_newname)) {
@@ -584,8 +628,7 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
strbuf_addf(&logmsg, "Branch: renamed %s to %s",
oldref.buf, newref.buf);
- if (!copy &&
- (!head || strcmp(oldname, head) || !is_null_oid(&head_oid)) &&
+ if (!copy && !(oldref_usage & IS_ORPHAN) &&
rename_ref(oldref.buf, newref.buf, logmsg.buf))
die(_("Branch rename failed"));
if (copy && copy_existing_ref(oldref.buf, newref.buf, logmsg.buf))
@@ -600,8 +643,9 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
interpreted_oldname);
}
- if (!copy &&
- replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf))
+ if (!copy && (oldref_usage & IS_HEAD) &&
+ replace_each_worktree_head_symref(worktrees, oldref.buf, newref.buf,
+ logmsg.buf))
die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
strbuf_release(&logmsg);
@@ -616,6 +660,7 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
strbuf_release(&newref);
strbuf_release(&oldsection);
strbuf_release(&newsection);
+ free_worktrees(worktrees);
}
static GIT_PATH_FUNC(edit_description, "EDIT_DESCRIPTION")
@@ -834,7 +879,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
strbuf_addf(&branch_ref, "refs/heads/%s", branch_name);
if (!ref_exists(branch_ref.buf))
- error((!argc || !strcmp(head, branch_name))
+ error((!argc || branch_checked_out(branch_ref.buf))
? _("No commit on branch '%s' yet.")
: _("No branch named '%s'."),
branch_name);
@@ -879,7 +924,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
}
if (!ref_exists(branch->refname)) {
- if (!argc || !strcmp(head, branch->name))
+ if (!argc || branch_checked_out(branch->refname))
die(_("No commit on branch '%s' yet."), branch->name);
die(_("branch '%s' does not exist"), branch->name);
}
diff --git a/builtin/bundle.c b/builtin/bundle.c
index e68fc83d94..44113389d7 100644
--- a/builtin/bundle.c
+++ b/builtin/bundle.c
@@ -4,6 +4,8 @@
#include "setup.h"
#include "strvec.h"
#include "parse-options.h"
+#include "pkt-line.h"
+#include "repository.h"
#include "cache.h"
#include "bundle.h"
diff --git a/builtin/check-attr.c b/builtin/check-attr.c
index 037bf1aaa2..b2b678847f 100644
--- a/builtin/check-attr.c
+++ b/builtin/check-attr.c
@@ -7,6 +7,7 @@
#include "gettext.h"
#include "object-name.h"
#include "quote.h"
+#include "repository.h"
#include "setup.h"
#include "parse-options.h"
#include "write-or-die.h"
diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c
index 9401dad007..e4b78782a3 100644
--- a/builtin/check-ignore.c
+++ b/builtin/check-ignore.c
@@ -7,6 +7,7 @@
#include "quote.h"
#include "pathspec.h"
#include "parse-options.h"
+#include "repository.h"
#include "submodule.h"
#include "write-or-die.h"
diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c
index 7df673e3e7..9375a05539 100644
--- a/builtin/checkout-index.c
+++ b/builtin/checkout-index.c
@@ -11,6 +11,7 @@
#include "gettext.h"
#include "lockfile.h"
#include "quote.h"
+#include "repository.h"
#include "cache-tree.h"
#include "parse-options.h"
#include "entry.h"
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 6f5d82ed3d..715eeb5048 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -28,6 +28,7 @@
#include "setup.h"
#include "submodule.h"
#include "submodule-config.h"
+#include "symlinks.h"
#include "trace2.h"
#include "tree.h"
#include "tree-walk.h"
diff --git a/builtin/clean.c b/builtin/clean.c
index 14c0d555ea..78852d28ce 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -14,6 +14,7 @@
#include "dir.h"
#include "gettext.h"
#include "parse-options.h"
+#include "repository.h"
#include "setup.h"
#include "string-list.h"
#include "quote.h"
diff --git a/builtin/clone.c b/builtin/clone.c
index 186845ef0b..15f9912b4c 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -13,6 +13,7 @@
#include "abspath.h"
#include "advice.h"
#include "config.h"
+#include "copy.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
@@ -38,6 +39,7 @@
#include "setup.h"
#include "connected.h"
#include "packfile.h"
+#include "pkt-line.h"
#include "list-objects-filter-options.h"
#include "hook.h"
#include "bundle.h"
diff --git a/builtin/config.c b/builtin/config.c
index 9401f1e5e3..ff2fe8ef12 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -9,6 +9,7 @@
#include "ident.h"
#include "parse-options.h"
#include "urlmatch.h"
+#include "path.h"
#include "quote.h"
#include "setup.h"
#include "worktree.h"
diff --git a/builtin/credential-cache--daemon.c b/builtin/credential-cache--daemon.c
index 4e571d9951..756c5f02ae 100644
--- a/builtin/credential-cache--daemon.c
+++ b/builtin/credential-cache--daemon.c
@@ -134,6 +134,9 @@ static void serve_one_client(FILE *in, FILE *out)
if (e->item.password_expiry_utc != TIME_MAX)
fprintf(out, "password_expiry_utc=%"PRItime"\n",
e->item.password_expiry_utc);
+ if (e->item.oauth_refresh_token)
+ fprintf(out, "oauth_refresh_token=%s\n",
+ e->item.oauth_refresh_token);
}
}
else if (!strcmp(action.buf, "exit")) {
diff --git a/builtin/credential-cache.c b/builtin/credential-cache.c
index 508da4c6e4..0ffacfdd83 100644
--- a/builtin/credential-cache.c
+++ b/builtin/credential-cache.c
@@ -1,6 +1,7 @@
#include "builtin.h"
#include "gettext.h"
#include "parse-options.h"
+#include "path.h"
#include "wrapper.h"
#include "write-or-die.h"
diff --git a/builtin/credential-store.c b/builtin/credential-store.c
index 8977604eb9..30c6ccf56c 100644
--- a/builtin/credential-store.c
+++ b/builtin/credential-store.c
@@ -3,6 +3,7 @@
#include "gettext.h"
#include "lockfile.h"
#include "credential.h"
+#include "path.h"
#include "string-list.h"
#include "parse-options.h"
#include "write-or-die.h"
diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c
index 385c2d0230..0b02c62b85 100644
--- a/builtin/diff-tree.c
+++ b/builtin/diff-tree.c
@@ -9,6 +9,7 @@
#include "builtin.h"
#include "submodule.h"
#include "repository.h"
+#include "tree.h"
static struct rev_info log_tree_opt;
diff --git a/builtin/diff.c b/builtin/diff.c
index 5a6a5d7f4b..7b64659fe7 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -22,6 +22,7 @@
#include "setup.h"
#include "submodule.h"
#include "oid-array.h"
+#include "tree.h"
#define DIFF_NO_INDEX_EXPLICIT 1
#define DIFF_NO_INDEX_IMPLICIT 2
diff --git a/builtin/difftool.c b/builtin/difftool.c
index f09d24d37f..0049342f5c 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -15,6 +15,7 @@
#include "cache.h"
#include "abspath.h"
#include "config.h"
+#include "copy.h"
#include "builtin.h"
#include "run-command.h"
#include "environment.h"
diff --git a/builtin/fetch.c b/builtin/fetch.c
index ab623f41b4..4d7c289752 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -29,6 +29,7 @@
#include "utf8.h"
#include "packfile.h"
#include "pager.h"
+#include "pkt-line.h"
#include "list-objects-filter-options.h"
#include "commit-reach.h"
#include "branch.h"
diff --git a/builtin/for-each-repo.c b/builtin/for-each-repo.c
index 598ca16c46..37daf7bec1 100644
--- a/builtin/for-each-repo.c
+++ b/builtin/for-each-repo.c
@@ -3,6 +3,8 @@
#include "builtin.h"
#include "gettext.h"
#include "parse-options.h"
+#include "path.h"
+#include "repository.h"
#include "run-command.h"
#include "string-list.h"
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 2cd461b84c..dcc165bf0c 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -27,6 +27,7 @@
#include "run-command.h"
#include "worktree.h"
#include "pack-revindex.h"
+#include "pack-bitmap.h"
#define REACHABLE 0x0001
#define SEEN 0x0002
@@ -57,6 +58,7 @@ static int name_objects;
#define ERROR_COMMIT_GRAPH 020
#define ERROR_MULTI_PACK_INDEX 040
#define ERROR_PACK_REV_INDEX 0100
+#define ERROR_BITMAP 0200
static const char *describe_object(const struct object_id *oid)
{
@@ -867,20 +869,20 @@ static int check_pack_rev_indexes(struct repository *r, int show_progress)
int res = 0;
if (show_progress) {
- for (struct packed_git *p = get_all_packs(the_repository); p; p = p->next)
+ for (struct packed_git *p = get_all_packs(r); p; p = p->next)
pack_count++;
progress = start_delayed_progress("Verifying reverse pack-indexes", pack_count);
pack_count = 0;
}
- for (struct packed_git *p = get_all_packs(the_repository); p; p = p->next) {
+ for (struct packed_git *p = get_all_packs(r); p; p = p->next) {
int load_error = load_pack_revindex_from_disk(p);
if (load_error < 0) {
error(_("unable to load rev-index for pack '%s'"), p->pack_name);
res = ERROR_PACK_REV_INDEX;
} else if (!load_error &&
- !load_pack_revindex(the_repository, p) &&
+ !load_pack_revindex(r, p) &&
verify_pack_revindex(p)) {
error(_("invalid rev-index for pack '%s'"), p->pack_name);
res = ERROR_PACK_REV_INDEX;
@@ -1056,6 +1058,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
}
errors_found |= check_pack_rev_indexes(the_repository, show_progress);
+ if (verify_bitmap_files(the_repository))
+ errors_found |= ERROR_BITMAP;
check_connectivity();
diff --git a/builtin/gc.c b/builtin/gc.c
index 031d42c64c..f3942188a6 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -12,6 +12,7 @@
#include "builtin.h"
#include "abspath.h"
+#include "date.h"
#include "environment.h"
#include "hex.h"
#include "repository.h"
diff --git a/builtin/help.c b/builtin/help.c
index 128aa83099..d3cf4af3f6 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -8,6 +8,7 @@
#include "gettext.h"
#include "pager.h"
#include "parse-options.h"
+#include "path.h"
#include "run-command.h"
#include "config-list.h"
#include "help.h"
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 6183f3fb3f..aef4036105 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -6,6 +6,7 @@
#include "cache.h"
#include "abspath.h"
#include "config.h"
+#include "copy.h"
#include "environment.h"
#include "gettext.h"
#include "refs.h"
@@ -13,6 +14,7 @@
#include "exec-cmd.h"
#include "object-file.h"
#include "parse-options.h"
+#include "path.h"
#include "setup.h"
#include "worktree.h"
#include "wrapper.h"
diff --git a/builtin/log.c b/builtin/log.c
index 4f162ff4d0..676de107d6 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -44,6 +44,7 @@
#include "commit-reach.h"
#include "range-diff.h"
#include "tmp-objdir.h"
+#include "tree.h"
#include "write-or-die.h"
#define MAIL_DEFAULT_WRAP 72
diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
index 3c74c4a104..cb6cb77e08 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -3,6 +3,7 @@
#include "gettext.h"
#include "hex.h"
#include "transport.h"
+#include "pkt-line.h"
#include "ref-filter.h"
#include "remote.h"
#include "refs.h"
diff --git a/builtin/merge-index.c b/builtin/merge-index.c
index b747b4ed98..ab16e70f23 100644
--- a/builtin/merge-index.c
+++ b/builtin/merge-index.c
@@ -1,6 +1,7 @@
#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "hex.h"
+#include "repository.h"
#include "run-command.h"
static const char *pgm;
diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c
index 708a8ffabe..b9e980384a 100644
--- a/builtin/merge-recursive.c
+++ b/builtin/merge-recursive.c
@@ -3,9 +3,11 @@
#include "advice.h"
#include "commit.h"
#include "gettext.h"
+#include "hash.h"
#include "tag.h"
#include "merge-recursive.h"
#include "object-name.h"
+#include "repository.h"
#include "xdiff-interface.h"
static const char builtin_merge_recursive_usage[] =
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index 6b9f006ec1..aa8040c2a6 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -16,6 +16,7 @@
#include "exec-cmd.h"
#include "merge-blobs.h"
#include "quote.h"
+#include "tree.h"
static int line_termination = '\n';
diff --git a/builtin/mv.c b/builtin/mv.c
index 32935af48e..665bd27448 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -18,6 +18,7 @@
#include "cache-tree.h"
#include "string-list.h"
#include "parse-options.h"
+#include "repository.h"
#include "setup.h"
#include "submodule.h"
#include "entry.h"
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 593f0506a1..4d15a23fc4 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -573,7 +573,11 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
N_("ignore refs matching <pattern>")),
OPT_GROUP(""),
OPT_BOOL(0, "all", &all, N_("list all commits reachable from all refs")),
- OPT_BOOL(0, "stdin", &transform_stdin, N_("deprecated: use --annotate-stdin instead")),
+ OPT_BOOL_F(0,
+ "stdin",
+ &transform_stdin,
+ N_("deprecated: use --annotate-stdin instead"),
+ PARSE_OPT_HIDDEN),
OPT_BOOL(0, "annotate-stdin", &annotate_stdin, N_("annotate text from stdin")),
OPT_BOOL(0, "undefined", &allow_undefined, N_("allow to print `undefined` names (default)")),
OPT_BOOL(0, "always", &always,
diff --git a/builtin/pull.c b/builtin/pull.c
index 967368ebc6..0c7bac97b7 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -1047,7 +1047,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
if (!opt_autostash)
require_clean_work_tree(the_repository,
N_("pull with rebase"),
- _("please commit or stash them."), 1, 0);
+ _("Please commit or stash them."), 1, 0);
if (get_rebase_fork_point(&rebase_fork_point, repo, *refspecs))
oidclr(&rebase_fork_point);
diff --git a/builtin/push.c b/builtin/push.c
index 6001e4ae0a..dbdf609daf 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -14,6 +14,8 @@
#include "remote.h"
#include "transport.h"
#include "parse-options.h"
+#include "pkt-line.h"
+#include "repository.h"
#include "submodule.h"
#include "submodule-config.h"
#include "send-pack.h"
@@ -593,11 +595,12 @@ int cmd_push(int argc, const char **argv, const char *prefix)
struct option options[] = {
OPT__VERBOSITY(&verbosity),
OPT_STRING( 0 , "repo", &repo, N_("repository"), N_("repository")),
- OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL),
+ OPT_BIT( 0 , "all", &flags, N_("push all branches"), TRANSPORT_PUSH_ALL),
+ OPT_ALIAS( 0 , "branches", "all"),
OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"),
(TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
OPT_BOOL('d', "delete", &deleterefs, N_("delete refs")),
- OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")),
+ OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --branches or --mirror)")),
OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN),
OPT_BIT( 0, "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN),
OPT_BIT('f', "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE),
@@ -640,7 +643,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
set_push_cert_flags(&flags, push_cert);
if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
- die(_("options '%s' and '%s' cannot be used together"), "--delete", "--all/--mirror/--tags");
+ die(_("options '%s' and '%s' cannot be used together"), "--delete", "--all/--branches/--mirror/--tags");
if (deleterefs && argc < 2)
die(_("--delete doesn't make sense without any refs"));
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index d61cbad96d..440f19b1b8 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -19,6 +19,7 @@
#include "dir.h"
#include "builtin.h"
#include "parse-options.h"
+#include "repository.h"
#include "resolve-undo.h"
#include "setup.h"
#include "submodule.h"
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index d22180435c..1a31a58367 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -33,6 +33,7 @@
#include "object-store.h"
#include "protocol.h"
#include "commit-reach.h"
+#include "server-info.h"
#include "trace.h"
#include "trace2.h"
#include "worktree.h"
diff --git a/builtin/repack.c b/builtin/repack.c
index bb7bf60e7c..0541c3ce15 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -7,6 +7,7 @@
#include "hex.h"
#include "parse-options.h"
#include "run-command.h"
+#include "server-info.h"
#include "sigchain.h"
#include "strbuf.h"
#include "string-list.h"
diff --git a/builtin/rerere.c b/builtin/rerere.c
index d4a03707b1..d4bd52797f 100644
--- a/builtin/rerere.c
+++ b/builtin/rerere.c
@@ -4,6 +4,7 @@
#include "dir.h"
#include "gettext.h"
#include "parse-options.h"
+#include "repository.h"
#include "string-list.h"
#include "rerere.h"
#include "wrapper.h"
diff --git a/builtin/rm.c b/builtin/rm.c
index d36072252e..b4589c824c 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -12,9 +12,11 @@
#include "dir.h"
#include "cache-tree.h"
#include "gettext.h"
+#include "hash.h"
#include "tree-walk.h"
#include "object-name.h"
#include "parse-options.h"
+#include "repository.h"
#include "string-list.h"
#include "setup.h"
#include "submodule.h"
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 20030b75e3..7ef4a642c1 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -2,6 +2,7 @@
#include "config.h"
#include "environment.h"
#include "gettext.h"
+#include "hash.h"
#include "hex.h"
#include "pretty.h"
#include "refs.h"
@@ -10,6 +11,7 @@
#include "strvec.h"
#include "object-name.h"
#include "parse-options.h"
+#include "repository.h"
#include "dir.h"
#include "commit-slab.h"
#include "date.h"
diff --git a/builtin/show-index.c b/builtin/show-index.c
index d4bbbbcd6c..d839e55335 100644
--- a/builtin/show-index.c
+++ b/builtin/show-index.c
@@ -1,9 +1,11 @@
#include "builtin.h"
#include "cache.h"
#include "gettext.h"
+#include "hash.h"
#include "hex.h"
#include "pack.h"
#include "parse-options.h"
+#include "repository.h"
static const char *const show_index_usage[] = {
"git show-index [--object-format=<hash-algorithm>]",
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 33b00cef15..5fab9ad2ec 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -9,6 +9,7 @@
#include "config.h"
#include "environment.h"
#include "gettext.h"
+#include "hash.h"
#include "hex.h"
#include "lockfile.h"
#include "quote.h"
@@ -21,8 +22,10 @@
#include "parse-options.h"
#include "pathspec.h"
#include "dir.h"
+#include "repository.h"
#include "setup.h"
#include "split-index.h"
+#include "symlinks.h"
#include "fsmonitor.h"
#include "write-or-die.h"
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 6ca85420c3..0c59b1c9ef 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -1,11 +1,13 @@
#include "cache.h"
#include "config.h"
#include "gettext.h"
+#include "hash.h"
#include "refs.h"
#include "builtin.h"
#include "object-name.h"
#include "parse-options.h"
#include "quote.h"
+#include "repository.h"
#include "strvec.h"
static const char * const git_update_ref_usage[] = {
diff --git a/builtin/update-server-info.c b/builtin/update-server-info.c
index e7bff27ae4..19dce3c065 100644
--- a/builtin/update-server-info.c
+++ b/builtin/update-server-info.c
@@ -3,6 +3,7 @@
#include "builtin.h"
#include "gettext.h"
#include "parse-options.h"
+#include "server-info.h"
static const char * const update_server_info_usage[] = {
"git update-server-info [-f | --force]",
diff --git a/builtin/upload-archive.c b/builtin/upload-archive.c
index 7f9320ac6d..44ad400e18 100644
--- a/builtin/upload-archive.c
+++ b/builtin/upload-archive.c
@@ -6,6 +6,7 @@
#include "archive.h"
#include "pkt-line.h"
#include "sideband.h"
+#include "repository.h"
#include "run-command.h"
#include "strvec.h"
diff --git a/builtin/worktree.c b/builtin/worktree.c
index a61bc32189..f3180463be 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -2,6 +2,7 @@
#include "abspath.h"
#include "checkout.h"
#include "config.h"
+#include "copy.h"
#include "builtin.h"
#include "dir.h"
#include "environment.h"
@@ -13,6 +14,7 @@
#include "strvec.h"
#include "branch.h"
#include "refs.h"
+#include "repository.h"
#include "run-command.h"
#include "hook.h"
#include "sigchain.h"
diff --git a/builtin/write-tree.c b/builtin/write-tree.c
index 32e302a813..84b83318c9 100644
--- a/builtin/write-tree.c
+++ b/builtin/write-tree.c
@@ -13,6 +13,7 @@
#include "tree.h"
#include "cache-tree.h"
#include "parse-options.h"
+#include "repository.h"
static const char * const write_tree_usage[] = {
N_("git write-tree [--missing-ok] [--prefix=<prefix>/]"),
diff --git a/bundle-uri.c b/bundle-uri.c
index f22490a2ca..2a2db1a1d3 100644
--- a/bundle-uri.c
+++ b/bundle-uri.c
@@ -1,6 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "bundle-uri.h"
#include "bundle.h"
+#include "copy.h"
#include "environment.h"
#include "gettext.h"
#include "object-store.h"
diff --git a/cache.h b/cache.h
index 71e2fe74c4..bdedb87e83 100644
--- a/cache.h
+++ b/cache.h
@@ -4,41 +4,10 @@
#include "git-compat-util.h"
#include "strbuf.h"
#include "hashmap.h"
-#include "gettext.h"
-#include "string-list.h"
#include "pathspec.h"
#include "object.h"
#include "statinfo.h"
-#if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
-#define DTYPE(de) ((de)->d_type)
-#else
-#undef DT_UNKNOWN
-#undef DT_DIR
-#undef DT_REG
-#undef DT_LNK
-#define DT_UNKNOWN 0
-#define DT_DIR 1
-#define DT_REG 2
-#define DT_LNK 3
-#define DTYPE(de) DT_UNKNOWN
-#endif
-
-/*
- * Some mode bits are also used internally for computations.
- *
- * They *must* not overlap with any valid modes, and they *must* not be emitted
- * to outside world - i.e. appear on disk or network. In other words, it's just
- * temporary fields, which we internally use, but they have to stay in-house.
- *
- * ( such approach is valid, as standard S_IF* fits into 16 bits, and in Git
- * codebase mode is `unsigned int` which is assumed to be at least 32 bits )
- */
-
-/* used internally in tree-diff */
-#define S_DIFFTREE_IFXMIN_NEQ 0x80000000
-
-
/*
* Basic data structures for the directory cache
*/
@@ -586,64 +555,7 @@ extern int verify_ce_order;
#define DATA_CHANGED 0x0020
#define TYPE_CHANGED 0x0040
-int base_name_compare(const char *name1, size_t len1, int mode1,
- const char *name2, size_t len2, int mode2);
-int df_name_compare(const char *name1, size_t len1, int mode1,
- const char *name2, size_t len2, int mode2);
-int name_compare(const char *name1, size_t len1, const char *name2, size_t len2);
-int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2);
-
-struct cache_def {
- struct strbuf path;
- int flags;
- int track_flags;
- int prefix_len_stat_func;
-};
-#define CACHE_DEF_INIT { \
- .path = STRBUF_INIT, \
-}
-static inline void cache_def_clear(struct cache_def *cache)
-{
- strbuf_release(&cache->path);
-}
-
-int has_symlink_leading_path(const char *name, int len);
-int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
-int check_leading_path(const char *name, int len, int warn_on_lstat_err);
-int has_dirs_only_path(const char *name, int len, int prefix_len);
-void invalidate_lstat_cache(void);
-void schedule_dir_for_removal(const char *name, int len);
-void remove_scheduled_dirs(void);
-
-struct pack_window {
- struct pack_window *next;
- unsigned char *base;
- off_t offset;
- size_t len;
- unsigned int last_used;
- unsigned int inuse_cnt;
-};
-
-struct pack_entry {
- off_t offset;
- struct packed_git *p;
-};
-
-/* Dumb servers support */
-int update_server_info(int);
-
-#define COPY_READ_ERROR (-2)
-#define COPY_WRITE_ERROR (-3)
-int copy_fd(int ifd, int ofd);
-int copy_file(const char *dst, const char *src, int mode);
-int copy_file_with_time(const char *dst, const char *src, int mode);
-
-/* base85 */
-int decode_85(char *dst, const char *line, int linelen);
-void encode_85(char *buf, const unsigned char *data, int bytes);
-
-/* pkt-line.c */
-void packet_trace_identity(const char *prog);
+int cmp_cache_name_compare(const void *a_, const void *b_);
/* add */
/*
@@ -655,36 +567,6 @@ int add_files_to_cache(const char *prefix, const struct pathspec *pathspec, int
/* diff.c */
extern int diff_auto_refresh_index;
-/* match-trees.c */
-void shift_tree(struct repository *, const struct object_id *, const struct object_id *, struct object_id *, int);
-void shift_tree_by(struct repository *, const struct object_id *, const struct object_id *, struct object_id *, const char *);
-
-/*
- * whitespace rules.
- * used by both diff and apply
- * last two digits are tab width
- */
-#define WS_BLANK_AT_EOL 0100
-#define WS_SPACE_BEFORE_TAB 0200
-#define WS_INDENT_WITH_NON_TAB 0400
-#define WS_CR_AT_EOL 01000
-#define WS_BLANK_AT_EOF 02000
-#define WS_TAB_IN_INDENT 04000
-#define WS_TRAILING_SPACE (WS_BLANK_AT_EOL|WS_BLANK_AT_EOF)
-#define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB|8)
-#define WS_TAB_WIDTH_MASK 077
-/* All WS_* -- when extended, adapt diff.c emit_symbol */
-#define WS_RULE_MASK 07777
-extern unsigned whitespace_rule_cfg;
-unsigned whitespace_rule(struct index_state *, const char *);
-unsigned parse_whitespace_rule(const char *);
-unsigned ws_check(const char *line, int len, unsigned ws_rule);
-void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws);
-char *whitespace_error_string(unsigned ws);
-void ws_fix_copy(struct strbuf *, const char *, int, unsigned, int *);
-int ws_blank_line(const char *line, int len);
-#define ws_tab_width(rule) ((rule) & WS_TAB_WIDTH_MASK)
-
/* ls-files */
void overlay_tree_on_index(struct index_state *istate,
const char *tree_name, const char *prefix);
@@ -730,6 +612,4 @@ 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/checkout.c b/checkout.c
index 04238b2713..4256e71a7c 100644
--- a/checkout.c
+++ b/checkout.c
@@ -2,6 +2,7 @@
#include "object-name.h"
#include "remote.h"
#include "refspec.h"
+#include "repository.h"
#include "checkout.h"
#include "config.h"
#include "strbuf.h"
diff --git a/checkout.h b/checkout.h
index 1917f3b323..3c514a5ab4 100644
--- a/checkout.h
+++ b/checkout.h
@@ -1,7 +1,7 @@
#ifndef CHECKOUT_H
#define CHECKOUT_H
-#include "hash.h"
+#include "hash-ll.h"
/*
* Check if the branch name uniquely matches a branch name on a remote
diff --git a/chunk-format.c b/chunk-format.c
index 60a73c1b14..e7d613c907 100644
--- a/chunk-format.c
+++ b/chunk-format.c
@@ -3,6 +3,7 @@
#include "chunk-format.h"
#include "csum-file.h"
#include "gettext.h"
+#include "hash.h"
#include "trace2.h"
/*
diff --git a/chunk-format.h b/chunk-format.h
index 025c38f938..c7794e84ad 100644
--- a/chunk-format.h
+++ b/chunk-format.h
@@ -1,7 +1,7 @@
#ifndef CHUNK_FORMAT_H
#define CHUNK_FORMAT_H
-#include "hash.h"
+#include "hash-ll.h"
struct hashfile;
struct chunkfile;
diff --git a/color.c b/color.c
index 6031998d3e..83abb11eda 100644
--- a/color.c
+++ b/color.c
@@ -1,10 +1,11 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "color.h"
#include "editor.h"
#include "gettext.h"
#include "hex.h"
#include "pager.h"
+#include "strbuf.h"
static int git_use_color_default = GIT_COLOR_AUTO;
int color_stdout_is_tty = -1;
diff --git a/combine-diff.c b/combine-diff.c
index f7e9fb5747..1e3cd7fb17 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "object-store.h"
#include "commit.h"
#include "convert.h"
@@ -13,6 +13,7 @@
#include "xdiff/xmacros.h"
#include "log-tree.h"
#include "refs.h"
+#include "tree.h"
#include "userdiff.h"
#include "oid-array.h"
#include "revision.h"
diff --git a/commit-graph.c b/commit-graph.c
index 43558b4d9b..843bdb458d 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -23,6 +23,7 @@
#include "shallow.h"
#include "json-writer.h"
#include "trace2.h"
+#include "tree.h"
#include "chunk-format.h"
#include "wrapper.h"
diff --git a/commit.c b/commit.c
index 878b4473e4..0fb9316931 100644
--- a/commit.c
+++ b/commit.c
@@ -26,6 +26,7 @@
#include "run-command.h"
#include "setup.h"
#include "shallow.h"
+#include "tree.h"
#include "hook.h"
static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
@@ -96,6 +97,7 @@ struct commit *lookup_commit_reference_by_name(const char *name)
static timestamp_t parse_commit_date(const char *buf, const char *tail)
{
const char *dateptr;
+ const char *eol;
if (buf + 6 >= tail)
return 0;
@@ -107,16 +109,56 @@ static timestamp_t parse_commit_date(const char *buf, const char *tail)
return 0;
if (memcmp(buf, "committer", 9))
return 0;
- while (buf < tail && *buf++ != '>')
- /* nada */;
- if (buf >= tail)
+
+ /*
+ * Jump to end-of-line so that we can walk backwards to find the
+ * end-of-email ">". This is more forgiving of malformed cases
+ * because unexpected characters tend to be in the name and email
+ * fields.
+ */
+ eol = memchr(buf, '\n', tail - buf);
+ if (!eol)
return 0;
- dateptr = buf;
- while (buf < tail && *buf++ != '\n')
- /* nada */;
- if (buf >= tail)
+ dateptr = eol;
+ while (dateptr > buf && dateptr[-1] != '>')
+ dateptr--;
+ if (dateptr == buf)
return 0;
- /* dateptr < buf && buf[-1] == '\n', so parsing will stop at buf-1 */
+
+ /*
+ * Trim leading whitespace, but make sure we have at least one
+ * non-whitespace character, as parse_timestamp() will otherwise walk
+ * right past the newline we found in "eol" when skipping whitespace
+ * itself.
+ *
+ * In theory it would be sufficient to allow any character not matched
+ * by isspace(), but there's a catch: our isspace() does not
+ * necessarily match the behavior of parse_timestamp(), as the latter
+ * is implemented by system routines which match more exotic control
+ * codes, or even locale-dependent sequences.
+ *
+ * Since we expect the timestamp to be a number, we can check for that.
+ * Anything else (e.g., a non-numeric token like "foo") would just
+ * cause parse_timestamp() to return 0 anyway.
+ */
+ while (dateptr < eol && isspace(*dateptr))
+ dateptr++;
+ if (!isdigit(*dateptr) && *dateptr != '-')
+ return 0;
+
+ /*
+ * We know there is at least one digit (or dash), so we'll begin
+ * parsing there and stop at worst case at eol.
+ *
+ * Note that we may feed parse_timestamp() extra characters here if the
+ * commit is malformed, and it will parse as far as it can. For
+ * example, "123foo456" would return "123". That might be questionable
+ * (versus returning "0"), but it would help in a hypothetical case
+ * like "123456+0100", where the whitespace from the timezone is
+ * missing. Since such syntactic errors may be baked into history and
+ * hard to correct now, let's err on trying to make our best guess
+ * here, rather than insist on perfect syntax.
+ */
return parse_timestamp(dateptr, NULL, 10);
}
diff --git a/commit.h b/commit.h
index 69b2f376e9..28928833c5 100644
--- a/commit.h
+++ b/commit.h
@@ -2,13 +2,10 @@
#define COMMIT_H
#include "object.h"
-#include "tree.h"
-#include "strbuf.h"
-#include "decorate.h"
-#include "gpg-interface.h"
-#include "string-list.h"
-#include "pretty.h"
-#include "commit-slab.h"
+
+struct signature_check;
+struct strbuf;
+struct tree;
#define COMMIT_NOT_FROM_GRAPH 0xFFFFFFFF
#define GENERATION_NUMBER_INFINITY ((1ULL << 63) - 1)
diff --git a/common-main.c b/common-main.c
index f319317353..033778b3c5 100644
--- a/common-main.c
+++ b/common-main.c
@@ -1,8 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "exec-cmd.h"
#include "gettext.h"
#include "attr.h"
+#include "repository.h"
#include "setup.h"
+#include "strbuf.h"
#include "trace2.h"
/*
diff --git a/compat/fsmonitor/fsm-health-darwin.c b/compat/fsmonitor/fsm-health-darwin.c
index b9f709e854..4c291f8a06 100644
--- a/compat/fsmonitor/fsm-health-darwin.c
+++ b/compat/fsmonitor/fsm-health-darwin.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "fsmonitor.h"
#include "fsm-health.h"
diff --git a/compat/fsmonitor/fsm-ipc-darwin.c b/compat/fsmonitor/fsm-ipc-darwin.c
index eb25123fa1..793073aaa7 100644
--- a/compat/fsmonitor/fsm-ipc-darwin.c
+++ b/compat/fsmonitor/fsm-ipc-darwin.c
@@ -1,6 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
+#include "gettext.h"
#include "hex.h"
+#include "repository.h"
#include "strbuf.h"
#include "fsmonitor.h"
#include "fsmonitor-ipc.h"
diff --git a/compat/fsmonitor/fsm-ipc-win32.c b/compat/fsmonitor/fsm-ipc-win32.c
index c9536dfb66..8928fa93ce 100644
--- a/compat/fsmonitor/fsm-ipc-win32.c
+++ b/compat/fsmonitor/fsm-ipc-win32.c
@@ -1,6 +1,7 @@
#include "git-compat-util.h"
#include "config.h"
#include "fsmonitor-ipc.h"
+#include "path.h"
const char *fsmonitor_ipc__get_path(struct repository *r) {
static char *ret;
diff --git a/compat/fsmonitor/fsm-listen-darwin.c b/compat/fsmonitor/fsm-listen-darwin.c
index 5eb6402ab8..23e24b4b37 100644
--- a/compat/fsmonitor/fsm-listen-darwin.c
+++ b/compat/fsmonitor/fsm-listen-darwin.c
@@ -23,12 +23,13 @@
#endif
#endif
-#include "cache.h"
+#include "git-compat-util.h"
#include "fsmonitor.h"
#include "fsm-listen.h"
#include "fsmonitor--daemon.h"
#include "fsmonitor-path-utils.h"
#include "gettext.h"
+#include "string-list.h"
struct fsm_listen_data
{
diff --git a/compat/mingw.c b/compat/mingw.c
index abbc3faf32..d06cdc6254 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -13,6 +13,7 @@
#include "../config.h"
#include "../environment.h"
#include "../trace2.h"
+#include "../symlinks.h"
#include "../wrapper.h"
#include "dir.h"
#include "gettext.h"
diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c
index 8a9881db07..a4d11376ba 100644
--- a/compat/precompose_utf8.c
+++ b/compat/precompose_utf8.c
@@ -9,6 +9,7 @@
#include "config.h"
#include "environment.h"
#include "gettext.h"
+#include "path.h"
#include "utf8.h"
#include "precompose_utf8.h"
diff --git a/compat/win32/trace2_win32_process_info.c b/compat/win32/trace2_win32_process_info.c
index e3e895c78a..a4e33768f4 100644
--- a/compat/win32/trace2_win32_process_info.c
+++ b/compat/win32/trace2_win32_process_info.c
@@ -1,5 +1,6 @@
#include "../../cache.h"
#include "../../json-writer.h"
+#include "../../repository.h"
#include "../../trace2.h"
#include "lazyload.h"
#include <Psapi.h>
diff --git a/config.c b/config.c
index 43b0d3fb57..b79baf83e3 100644
--- a/config.c
+++ b/config.c
@@ -5,7 +5,7 @@
* Copyright (C) Johannes Schindelin, 2005
*
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "advice.h"
#include "alloc.h"
@@ -35,6 +35,7 @@
#include "setup.h"
#include "trace2.h"
#include "worktree.h"
+#include "ws.h"
#include "wrapper.h"
#include "write-or-die.h"
diff --git a/contrib/credential/gnome-keyring/.gitignore b/contrib/credential/gnome-keyring/.gitignore
deleted file mode 100644
index 88d8fcdbce..0000000000
--- a/contrib/credential/gnome-keyring/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-git-credential-gnome-keyring
diff --git a/contrib/credential/gnome-keyring/Makefile b/contrib/credential/gnome-keyring/Makefile
deleted file mode 100644
index 22c19df94b..0000000000
--- a/contrib/credential/gnome-keyring/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-MAIN:=git-credential-gnome-keyring
-all:: $(MAIN)
-
-CC = gcc
-RM = rm -f
-CFLAGS = -g -O2 -Wall
-PKG_CONFIG = pkg-config
-
--include ../../../config.mak.autogen
--include ../../../config.mak
-
-INCS:=$(shell $(PKG_CONFIG) --cflags gnome-keyring-1 glib-2.0)
-LIBS:=$(shell $(PKG_CONFIG) --libs gnome-keyring-1 glib-2.0)
-
-SRCS:=$(MAIN).c
-OBJS:=$(SRCS:.c=.o)
-
-%.o: %.c
- $(CC) $(CFLAGS) $(CPPFLAGS) $(INCS) -o $@ -c $<
-
-$(MAIN): $(OBJS)
- $(CC) -o $@ $(LDFLAGS) $^ $(LIBS)
-
-clean:
- @$(RM) $(MAIN) $(OBJS)
diff --git a/contrib/credential/gnome-keyring/git-credential-gnome-keyring.c b/contrib/credential/gnome-keyring/git-credential-gnome-keyring.c
deleted file mode 100644
index 5927e27ae6..0000000000
--- a/contrib/credential/gnome-keyring/git-credential-gnome-keyring.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Copyright (C) 2011 John Szakmeister <john@szakmeister.net>
- * 2012 Philipp A. Hartmann <pah@qo.cx>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
- * Credits:
- * - GNOME Keyring API handling originally written by John Szakmeister
- * - ported to credential helper API by Philipp A. Hartmann
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <glib.h>
-#include <gnome-keyring.h>
-
-#ifdef GNOME_KEYRING_DEFAULT
-
- /* Modern gnome-keyring */
-
-#include <gnome-keyring-memory.h>
-
-#else
-
- /*
- * Support ancient gnome-keyring, circ. RHEL 5.X.
- * GNOME_KEYRING_DEFAULT seems to have been introduced with Gnome 2.22,
- * and the other features roughly around Gnome 2.20, 6 months before.
- * Ubuntu 8.04 used Gnome 2.22 (I think). Not sure any distro used 2.20.
- * So the existence/non-existence of GNOME_KEYRING_DEFAULT seems like
- * a decent thing to use as an indicator.
- */
-
-#define GNOME_KEYRING_DEFAULT NULL
-
-/*
- * ancient gnome-keyring returns DENIED when an entry is not found.
- * Setting NO_MATCH to DENIED will prevent us from reporting DENIED
- * errors during get and erase operations, but we will still report
- * DENIED errors during a store.
- */
-#define GNOME_KEYRING_RESULT_NO_MATCH GNOME_KEYRING_RESULT_DENIED
-
-#define gnome_keyring_memory_alloc g_malloc
-#define gnome_keyring_memory_free gnome_keyring_free_password
-#define gnome_keyring_memory_strdup g_strdup
-
-static const char *gnome_keyring_result_to_message(GnomeKeyringResult result)
-{
- switch (result) {
- case GNOME_KEYRING_RESULT_OK:
- return "OK";
- case GNOME_KEYRING_RESULT_DENIED:
- return "Denied";
- case GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON:
- return "No Keyring Daemon";
- case GNOME_KEYRING_RESULT_ALREADY_UNLOCKED:
- return "Already UnLocked";
- case GNOME_KEYRING_RESULT_NO_SUCH_KEYRING:
- return "No Such Keyring";
- case GNOME_KEYRING_RESULT_BAD_ARGUMENTS:
- return "Bad Arguments";
- case GNOME_KEYRING_RESULT_IO_ERROR:
- return "IO Error";
- case GNOME_KEYRING_RESULT_CANCELLED:
- return "Cancelled";
- case GNOME_KEYRING_RESULT_ALREADY_EXISTS:
- return "Already Exists";
- default:
- return "Unknown Error";
- }
-}
-
-/*
- * Support really ancient gnome-keyring, circ. RHEL 4.X.
- * Just a guess for the Glib version. Glib 2.8 was roughly Gnome 2.12 ?
- * Which was released with gnome-keyring 0.4.3 ??
- */
-#if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 8
-
-static void gnome_keyring_done_cb(GnomeKeyringResult result, gpointer user_data)
-{
- gpointer *data = (gpointer *)user_data;
- int *done = (int *)data[0];
- GnomeKeyringResult *r = (GnomeKeyringResult *)data[1];
-
- *r = result;
- *done = 1;
-}
-
-static void wait_for_request_completion(int *done)
-{
- GMainContext *mc = g_main_context_default();
- while (!*done)
- g_main_context_iteration(mc, TRUE);
-}
-
-static GnomeKeyringResult gnome_keyring_item_delete_sync(const char *keyring, guint32 id)
-{
- int done = 0;
- GnomeKeyringResult result;
- gpointer data[] = { &done, &result };
-
- gnome_keyring_item_delete(keyring, id, gnome_keyring_done_cb, data,
- NULL);
-
- wait_for_request_completion(&done);
-
- return result;
-}
-
-#endif
-#endif
-
-/*
- * This credential struct and API is simplified from git's credential.{h,c}
- */
-struct credential {
- char *protocol;
- char *host;
- unsigned short port;
- char *path;
- char *username;
- char *password;
-};
-
-#define CREDENTIAL_INIT { 0 }
-
-typedef int (*credential_op_cb)(struct credential *);
-
-struct credential_operation {
- char *name;
- credential_op_cb op;
-};
-
-#define CREDENTIAL_OP_END { NULL, NULL }
-
-/* ----------------- GNOME Keyring functions ----------------- */
-
-/* create a special keyring option string, if path is given */
-static char *keyring_object(struct credential *c)
-{
- if (!c->path)
- return NULL;
-
- if (c->port)
- return g_strdup_printf("%s:%hd/%s", c->host, c->port, c->path);
-
- return g_strdup_printf("%s/%s", c->host, c->path);
-}
-
-static int keyring_get(struct credential *c)
-{
- char *object = NULL;
- GList *entries;
- GnomeKeyringNetworkPasswordData *password_data;
- GnomeKeyringResult result;
-
- if (!c->protocol || !(c->host || c->path))
- return EXIT_FAILURE;
-
- object = keyring_object(c);
-
- result = gnome_keyring_find_network_password_sync(
- c->username,
- NULL /* domain */,
- c->host,
- object,
- c->protocol,
- NULL /* authtype */,
- c->port,
- &entries);
-
- g_free(object);
-
- if (result == GNOME_KEYRING_RESULT_NO_MATCH)
- return EXIT_SUCCESS;
-
- if (result == GNOME_KEYRING_RESULT_CANCELLED)
- return EXIT_SUCCESS;
-
- if (result != GNOME_KEYRING_RESULT_OK) {
- g_critical("%s", gnome_keyring_result_to_message(result));
- return EXIT_FAILURE;
- }
-
- /* pick the first one from the list */
- password_data = (GnomeKeyringNetworkPasswordData *)entries->data;
-
- gnome_keyring_memory_free(c->password);
- c->password = gnome_keyring_memory_strdup(password_data->password);
-
- if (!c->username)
- c->username = g_strdup(password_data->user);
-
- gnome_keyring_network_password_list_free(entries);
-
- return EXIT_SUCCESS;
-}
-
-
-static int keyring_store(struct credential *c)
-{
- guint32 item_id;
- char *object = NULL;
- GnomeKeyringResult result;
-
- /*
- * Sanity check that what we are storing is actually sensible.
- * In particular, we can't make a URL without a protocol field.
- * Without either a host or pathname (depending on the scheme),
- * we have no primary key. And without a username and password,
- * we are not actually storing a credential.
- */
- if (!c->protocol || !(c->host || c->path) ||
- !c->username || !c->password)
- return EXIT_FAILURE;
-
- object = keyring_object(c);
-
- result = gnome_keyring_set_network_password_sync(
- GNOME_KEYRING_DEFAULT,
- c->username,
- NULL /* domain */,
- c->host,
- object,
- c->protocol,
- NULL /* authtype */,
- c->port,
- c->password,
- &item_id);
-
- g_free(object);
-
- if (result != GNOME_KEYRING_RESULT_OK &&
- result != GNOME_KEYRING_RESULT_CANCELLED) {
- g_critical("%s", gnome_keyring_result_to_message(result));
- return EXIT_FAILURE;
- }
-
- return EXIT_SUCCESS;
-}
-
-static int keyring_erase(struct credential *c)
-{
- char *object = NULL;
- GList *entries;
- GnomeKeyringNetworkPasswordData *password_data;
- GnomeKeyringResult result;
-
- /*
- * Sanity check that we actually have something to match
- * against. The input we get is a restrictive pattern,
- * so technically a blank credential means "erase everything".
- * But it is too easy to accidentally send this, since it is equivalent
- * to empty input. So explicitly disallow it, and require that the
- * pattern have some actual content to match.
- */
- if (!c->protocol && !c->host && !c->path && !c->username)
- return EXIT_FAILURE;
-
- object = keyring_object(c);
-
- result = gnome_keyring_find_network_password_sync(
- c->username,
- NULL /* domain */,
- c->host,
- object,
- c->protocol,
- NULL /* authtype */,
- c->port,
- &entries);
-
- g_free(object);
-
- if (result == GNOME_KEYRING_RESULT_NO_MATCH)
- return EXIT_SUCCESS;
-
- if (result == GNOME_KEYRING_RESULT_CANCELLED)
- return EXIT_SUCCESS;
-
- if (result != GNOME_KEYRING_RESULT_OK) {
- g_critical("%s", gnome_keyring_result_to_message(result));
- return EXIT_FAILURE;
- }
-
- /* pick the first one from the list (delete all matches?) */
- password_data = (GnomeKeyringNetworkPasswordData *)entries->data;
-
- result = gnome_keyring_item_delete_sync(
- password_data->keyring, password_data->item_id);
-
- gnome_keyring_network_password_list_free(entries);
-
- if (result != GNOME_KEYRING_RESULT_OK) {
- g_critical("%s", gnome_keyring_result_to_message(result));
- return EXIT_FAILURE;
- }
-
- return EXIT_SUCCESS;
-}
-
-/*
- * Table with helper operation callbacks, used by generic
- * credential helper main function.
- */
-static struct credential_operation const credential_helper_ops[] = {
- { "get", keyring_get },
- { "store", keyring_store },
- { "erase", keyring_erase },
- CREDENTIAL_OP_END
-};
-
-/* ------------------ credential functions ------------------ */
-
-static void credential_init(struct credential *c)
-{
- memset(c, 0, sizeof(*c));
-}
-
-static void credential_clear(struct credential *c)
-{
- g_free(c->protocol);
- g_free(c->host);
- g_free(c->path);
- g_free(c->username);
- gnome_keyring_memory_free(c->password);
-
- credential_init(c);
-}
-
-static int credential_read(struct credential *c)
-{
- char *buf;
- size_t line_len;
- char *key;
- char *value;
-
- key = buf = gnome_keyring_memory_alloc(1024);
-
- while (fgets(buf, 1024, stdin)) {
- line_len = strlen(buf);
-
- if (line_len && buf[line_len-1] == '\n')
- buf[--line_len] = '\0';
-
- if (!line_len)
- break;
-
- value = strchr(buf, '=');
- if (!value) {
- g_warning("invalid credential line: %s", key);
- gnome_keyring_memory_free(buf);
- return -1;
- }
- *value++ = '\0';
-
- if (!strcmp(key, "protocol")) {
- g_free(c->protocol);
- c->protocol = g_strdup(value);
- } else if (!strcmp(key, "host")) {
- g_free(c->host);
- c->host = g_strdup(value);
- value = strrchr(c->host, ':');
- if (value) {
- *value++ = '\0';
- c->port = atoi(value);
- }
- } else if (!strcmp(key, "path")) {
- g_free(c->path);
- c->path = g_strdup(value);
- } else if (!strcmp(key, "username")) {
- g_free(c->username);
- c->username = g_strdup(value);
- } else if (!strcmp(key, "password")) {
- gnome_keyring_memory_free(c->password);
- c->password = gnome_keyring_memory_strdup(value);
- while (*value)
- *value++ = '\0';
- }
- /*
- * Ignore other lines; we don't know what they mean, but
- * this future-proofs us when later versions of git do
- * learn new lines, and the helpers are updated to match.
- */
- }
-
- gnome_keyring_memory_free(buf);
-
- return 0;
-}
-
-static void credential_write_item(FILE *fp, const char *key, const char *value)
-{
- if (!value)
- return;
- fprintf(fp, "%s=%s\n", key, value);
-}
-
-static void credential_write(const struct credential *c)
-{
- /* only write username/password, if set */
- credential_write_item(stdout, "username", c->username);
- credential_write_item(stdout, "password", c->password);
-}
-
-static void usage(const char *name)
-{
- struct credential_operation const *try_op = credential_helper_ops;
- const char *basename = strrchr(name, '/');
-
- basename = (basename) ? basename + 1 : name;
- fprintf(stderr, "usage: %s <", basename);
- while (try_op->name) {
- fprintf(stderr, "%s", (try_op++)->name);
- if (try_op->name)
- fprintf(stderr, "%s", "|");
- }
- fprintf(stderr, "%s", ">\n");
-}
-
-int main(int argc, char *argv[])
-{
- int ret = EXIT_SUCCESS;
-
- struct credential_operation const *try_op = credential_helper_ops;
- struct credential cred = CREDENTIAL_INIT;
-
- if (!argv[1]) {
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
-
- g_set_application_name("Git Credential Helper");
-
- /* lookup operation callback */
- while (try_op->name && strcmp(argv[1], try_op->name))
- try_op++;
-
- /* unsupported operation given -- ignore silently */
- if (!try_op->name || !try_op->op)
- goto out;
-
- ret = credential_read(&cred);
- if (ret)
- goto out;
-
- /* perform credential operation */
- ret = (*try_op->op)(&cred);
-
- credential_write(&cred);
-
-out:
- credential_clear(&cred);
- return ret;
-}
diff --git a/contrib/credential/libsecret/.gitignore b/contrib/credential/libsecret/.gitignore
new file mode 100644
index 0000000000..4fa22359e2
--- /dev/null
+++ b/contrib/credential/libsecret/.gitignore
@@ -0,0 +1 @@
+git-credential-libsecret
diff --git a/contrib/credential/libsecret/git-credential-libsecret.c b/contrib/credential/libsecret/git-credential-libsecret.c
index 2c5d76d789..ef681f29d5 100644
--- a/contrib/credential/libsecret/git-credential-libsecret.c
+++ b/contrib/credential/libsecret/git-credential-libsecret.c
@@ -244,17 +244,16 @@ static void credential_clear(struct credential *c)
static int credential_read(struct credential *c)
{
- char *buf;
- size_t line_len;
+ char *buf = NULL;
+ size_t alloc;
+ ssize_t line_len;
char *key;
char *value;
- key = buf = g_malloc(1024);
+ while ((line_len = getline(&buf, &alloc, stdin)) > 0) {
+ key = buf;
- while (fgets(buf, 1024, stdin)) {
- line_len = strlen(buf);
-
- if (line_len && buf[line_len-1] == '\n')
+ if (buf[line_len-1] == '\n')
buf[--line_len] = '\0';
if (!line_len)
@@ -298,7 +297,7 @@ static int credential_read(struct credential *c)
*/
}
- g_free(buf);
+ free(buf);
return 0;
}
diff --git a/contrib/credential/osxkeychain/git-credential-osxkeychain.c b/contrib/credential/osxkeychain/git-credential-osxkeychain.c
index e29cc28779..5f2e5f16c8 100644
--- a/contrib/credential/osxkeychain/git-credential-osxkeychain.c
+++ b/contrib/credential/osxkeychain/git-credential-osxkeychain.c
@@ -113,14 +113,16 @@ static void add_internet_password(void)
static void read_credential(void)
{
- char buf[1024];
+ char *buf = NULL;
+ size_t alloc;
+ ssize_t line_len;
- while (fgets(buf, sizeof(buf), stdin)) {
+ while ((line_len = getline(&buf, &alloc, stdin)) > 0) {
char *v;
if (!strcmp(buf, "\n"))
break;
- buf[strlen(buf)-1] = '\0';
+ buf[line_len-1] = '\0';
v = strchr(buf, '=');
if (!v)
@@ -165,6 +167,8 @@ static void read_credential(void)
* learn new lines, and the helpers are updated to match.
*/
}
+
+ free(buf);
}
int main(int argc, const char **argv)
diff --git a/contrib/credential/wincred/git-credential-wincred.c b/contrib/credential/wincred/git-credential-wincred.c
index ead6e267c7..96f10613ae 100644
--- a/contrib/credential/wincred/git-credential-wincred.c
+++ b/contrib/credential/wincred/git-credential-wincred.c
@@ -6,6 +6,7 @@
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
+#include <wincred.h>
/* common helpers */
@@ -33,65 +34,8 @@ static void *xmalloc(size_t size)
return ret;
}
-/* MinGW doesn't have wincred.h, so we need to define stuff */
-
-typedef struct _CREDENTIAL_ATTRIBUTEW {
- LPWSTR Keyword;
- DWORD Flags;
- DWORD ValueSize;
- LPBYTE Value;
-} CREDENTIAL_ATTRIBUTEW, *PCREDENTIAL_ATTRIBUTEW;
-
-typedef struct _CREDENTIALW {
- DWORD Flags;
- DWORD Type;
- LPWSTR TargetName;
- LPWSTR Comment;
- FILETIME LastWritten;
- DWORD CredentialBlobSize;
- LPBYTE CredentialBlob;
- DWORD Persist;
- DWORD AttributeCount;
- PCREDENTIAL_ATTRIBUTEW Attributes;
- LPWSTR TargetAlias;
- LPWSTR UserName;
-} CREDENTIALW, *PCREDENTIALW;
-
-#define CRED_TYPE_GENERIC 1
-#define CRED_PERSIST_LOCAL_MACHINE 2
-#define CRED_MAX_ATTRIBUTES 64
-
-typedef BOOL (WINAPI *CredWriteWT)(PCREDENTIALW, DWORD);
-typedef BOOL (WINAPI *CredEnumerateWT)(LPCWSTR, DWORD, DWORD *,
- PCREDENTIALW **);
-typedef VOID (WINAPI *CredFreeT)(PVOID);
-typedef BOOL (WINAPI *CredDeleteWT)(LPCWSTR, DWORD, DWORD);
-
-static HMODULE advapi;
-static CredWriteWT CredWriteW;
-static CredEnumerateWT CredEnumerateW;
-static CredFreeT CredFree;
-static CredDeleteWT CredDeleteW;
-
-static void load_cred_funcs(void)
-{
- /* load DLLs */
- advapi = LoadLibraryExA("advapi32.dll", NULL,
- LOAD_LIBRARY_SEARCH_SYSTEM32);
- if (!advapi)
- die("failed to load advapi32.dll");
-
- /* get function pointers */
- CredWriteW = (CredWriteWT)GetProcAddress(advapi, "CredWriteW");
- CredEnumerateW = (CredEnumerateWT)GetProcAddress(advapi,
- "CredEnumerateW");
- CredFree = (CredFreeT)GetProcAddress(advapi, "CredFree");
- CredDeleteW = (CredDeleteWT)GetProcAddress(advapi, "CredDeleteW");
- if (!CredWriteW || !CredEnumerateW || !CredFree || !CredDeleteW)
- die("failed to load functions");
-}
-
-static WCHAR *wusername, *password, *protocol, *host, *path, target[1024];
+static WCHAR *wusername, *password, *protocol, *host, *path, target[1024],
+ *password_expiry_utc;
static void write_item(const char *what, LPCWSTR wbuf, int wlen)
{
@@ -183,6 +127,7 @@ static void get_credential(void)
CREDENTIALW **creds;
DWORD num_creds;
int i;
+ CREDENTIAL_ATTRIBUTEW *attr;
if (!CredEnumerateW(L"git:*", 0, &num_creds, &creds))
return;
@@ -195,6 +140,14 @@ static void get_credential(void)
write_item("password",
(LPCWSTR)creds[i]->CredentialBlob,
creds[i]->CredentialBlobSize / sizeof(WCHAR));
+ for (int j = 0; j < creds[i]->AttributeCount; j++) {
+ attr = creds[i]->Attributes + j;
+ if (!wcscmp(attr->Keyword, L"git_password_expiry_utc")) {
+ write_item("password_expiry_utc", (LPCWSTR)attr->Value,
+ attr->ValueSize / sizeof(WCHAR));
+ break;
+ }
+ }
break;
}
@@ -204,6 +157,7 @@ static void get_credential(void)
static void store_credential(void)
{
CREDENTIALW cred;
+ CREDENTIAL_ATTRIBUTEW expiry_attr;
if (!wusername || !password)
return;
@@ -217,6 +171,14 @@ static void store_credential(void)
cred.Persist = CRED_PERSIST_LOCAL_MACHINE;
cred.AttributeCount = 0;
cred.Attributes = NULL;
+ if (password_expiry_utc != NULL) {
+ expiry_attr.Keyword = L"git_password_expiry_utc";
+ expiry_attr.Value = (LPVOID)password_expiry_utc;
+ expiry_attr.ValueSize = (wcslen(password_expiry_utc)) * sizeof(WCHAR);
+ expiry_attr.Flags = 0;
+ cred.Attributes = &expiry_attr;
+ cred.AttributeCount = 1;
+ }
cred.TargetAlias = NULL;
cred.UserName = wusername;
@@ -249,17 +211,28 @@ static WCHAR *utf8_to_utf16_dup(const char *str)
return wstr;
}
+#define KB (1024)
+
static void read_credential(void)
{
- char buf[1024];
+ size_t alloc = 100 * KB;
+ char *buf = calloc(alloc, sizeof(*buf));
- while (fgets(buf, sizeof(buf), stdin)) {
+ while (fgets(buf, alloc, stdin)) {
char *v;
- int len = strlen(buf);
+ size_t len = strlen(buf);
+ int ends_in_newline = 0;
/* strip trailing CR / LF */
- while (len && strchr("\r\n", buf[len - 1]))
+ if (len && buf[len - 1] == '\n') {
+ buf[--len] = 0;
+ ends_in_newline = 1;
+ }
+ if (len && buf[len - 1] == '\r')
buf[--len] = 0;
+ if (!ends_in_newline)
+ die("bad input: %s", buf);
+
if (!*buf)
break;
@@ -278,12 +251,16 @@ static void read_credential(void)
wusername = utf8_to_utf16_dup(v);
} else if (!strcmp(buf, "password"))
password = utf8_to_utf16_dup(v);
+ else if (!strcmp(buf, "password_expiry_utc"))
+ password_expiry_utc = utf8_to_utf16_dup(v);
/*
* Ignore other lines; we don't know what they mean, but
* this future-proofs us when later versions of git do
* learn new lines, and the helpers are updated to match.
*/
}
+
+ free(buf);
}
int main(int argc, char *argv[])
@@ -292,7 +269,7 @@ int main(int argc, char *argv[])
"usage: git credential-wincred <get|store|erase>\n";
if (!argv[1])
- die(usage);
+ die("%s", usage);
/* git use binary pipes to avoid CRLF-issues */
_setmode(_fileno(stdin), _O_BINARY);
@@ -300,8 +277,6 @@ int main(int argc, char *argv[])
read_credential();
- load_cred_funcs();
-
if (!protocol || !(host || path))
return 0;
diff --git a/convert.c b/convert.c
index 5a2ea5308d..7cf7bd0c88 100644
--- a/convert.c
+++ b/convert.c
@@ -2,6 +2,7 @@
#include "advice.h"
#include "config.h"
#include "convert.h"
+#include "copy.h"
#include "gettext.h"
#include "hex.h"
#include "object-store.h"
diff --git a/convert.h b/convert.h
index 0a6e4086b8..d925589444 100644
--- a/convert.h
+++ b/convert.h
@@ -4,7 +4,7 @@
#ifndef CONVERT_H
#define CONVERT_H
-#include "hash.h"
+#include "hash-ll.h"
#include "string-list.h"
struct index_state;
diff --git a/copy.c b/copy.c
index c3250f0822..882c79cffb 100644
--- a/copy.c
+++ b/copy.c
@@ -1,4 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "copy.h"
+#include "path.h"
#include "wrapper.h"
int copy_fd(int ifd, int ofd)
diff --git a/copy.h b/copy.h
new file mode 100644
index 0000000000..2af77cba86
--- /dev/null
+++ b/copy.h
@@ -0,0 +1,10 @@
+#ifndef COPY_H
+#define COPY_H
+
+#define COPY_READ_ERROR (-2)
+#define COPY_WRITE_ERROR (-3)
+int copy_fd(int ifd, int ofd);
+int copy_file(const char *dst, const char *src, int mode);
+int copy_file_with_time(const char *dst, const char *src, int mode);
+
+#endif /* COPY_H */
diff --git a/credential.c b/credential.c
index e6417bf880..023b59d571 100644
--- a/credential.c
+++ b/credential.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "config.h"
#include "credential.h"
@@ -8,6 +8,7 @@
#include "url.h"
#include "prompt.h"
#include "sigchain.h"
+#include "strbuf.h"
#include "urlmatch.h"
#include "git-compat-util.h"
@@ -24,6 +25,7 @@ void credential_clear(struct credential *c)
free(c->path);
free(c->username);
free(c->password);
+ free(c->oauth_refresh_token);
string_list_clear(&c->helpers, 0);
strvec_clear(&c->wwwauth_headers);
@@ -238,11 +240,16 @@ int credential_read(struct credential *c, FILE *fp)
} else if (!strcmp(key, "path")) {
free(c->path);
c->path = xstrdup(value);
+ } else if (!strcmp(key, "wwwauth[]")) {
+ strvec_push(&c->wwwauth_headers, value);
} else if (!strcmp(key, "password_expiry_utc")) {
errno = 0;
c->password_expiry_utc = parse_timestamp(value, NULL, 10);
if (c->password_expiry_utc == 0 || errno == ERANGE)
c->password_expiry_utc = TIME_MAX;
+ } else if (!strcmp(key, "oauth_refresh_token")) {
+ free(c->oauth_refresh_token);
+ c->oauth_refresh_token = xstrdup(value);
} else if (!strcmp(key, "url")) {
credential_from_url(c, value);
} else if (!strcmp(key, "quit")) {
@@ -278,6 +285,7 @@ void credential_write(const struct credential *c, FILE *fp)
credential_write_item(fp, "path", c->path, 0);
credential_write_item(fp, "username", c->username, 0);
credential_write_item(fp, "password", c->password, 0);
+ credential_write_item(fp, "oauth_refresh_token", c->oauth_refresh_token, 0);
if (c->password_expiry_utc != TIME_MAX) {
char *s = xstrfmt("%"PRItime, c->password_expiry_utc);
credential_write_item(fp, "password_expiry_utc", s, 0);
@@ -403,6 +411,7 @@ void credential_reject(struct credential *c)
FREE_AND_NULL(c->username);
FREE_AND_NULL(c->password);
+ FREE_AND_NULL(c->oauth_refresh_token);
c->password_expiry_utc = TIME_MAX;
c->approved = 0;
}
diff --git a/credential.h b/credential.h
index 2b5958cd43..b8e2936d1d 100644
--- a/credential.h
+++ b/credential.h
@@ -141,6 +141,7 @@ struct credential {
char *protocol;
char *host;
char *path;
+ char *oauth_refresh_token;
timestamp_t password_expiry_utc;
};
diff --git a/csum-file.c b/csum-file.c
index 82ae2973d3..daf9b06dff 100644
--- a/csum-file.c
+++ b/csum-file.c
@@ -10,6 +10,7 @@
#include "git-compat-util.h"
#include "progress.h"
#include "csum-file.h"
+#include "hash.h"
#include "wrapper.h"
static void verify_buffer_or_die(struct hashfile *f,
diff --git a/csum-file.h b/csum-file.h
index 566e05cbd2..bc5bec27ac 100644
--- a/csum-file.h
+++ b/csum-file.h
@@ -1,7 +1,7 @@
#ifndef CSUM_FILE_H
#define CSUM_FILE_H
-#include "hash.h"
+#include "hash-ll.h"
#include "write-or-die.h"
struct progress;
diff --git a/daemon.c b/daemon.c
index 75c3c06457..7139cc201d 100644
--- a/daemon.c
+++ b/daemon.c
@@ -1,8 +1,9 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "alloc.h"
#include "config.h"
#include "environment.h"
+#include "path.h"
#include "pkt-line.h"
#include "protocol.h"
#include "run-command.h"
diff --git a/date.c b/date.c
index e867ebf6b7..619ada5b20 100644
--- a/date.c
+++ b/date.c
@@ -4,10 +4,11 @@
* Copyright (C) Linus Torvalds, 2005
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "date.h"
#include "gettext.h"
#include "pager.h"
+#include "strbuf.h"
/*
* This is like mktime, but without normalization of tm_wday and tm_yday.
diff --git a/detect-compiler b/detect-compiler
index 50087f5670..a87650b71b 100755
--- a/detect-compiler
+++ b/detect-compiler
@@ -17,7 +17,15 @@ get_family() {
}
get_version() {
- get_version_line | sed 's/^.* version \([0-9][^ ]*\).*/\1/'
+ # A string that begins with a digit up to the next SP
+ ver=$(get_version_line | sed 's/^.* version \([0-9][^ ]*\).*/\1/')
+
+ # There are known -variant suffixes that do not affect the
+ # meaning of the main version number. Strip them.
+ ver=${ver%-win32}
+ ver=${ver%-posix}
+
+ echo "$ver"
}
print_flags() {
diff --git a/diagnose.c b/diagnose.c
index f1aebf0b50..c8c7ebcfa3 100644
--- a/diagnose.c
+++ b/diagnose.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "diagnose.h"
#include "compat/disk.h"
#include "archive.h"
diff --git a/diff-lib.c b/diff-lib.c
index d292405a26..60e979dc1b 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -14,6 +14,7 @@
#include "unpack-trees.h"
#include "refs.h"
#include "submodule.h"
+#include "symlinks.h"
#include "trace.h"
#include "dir.h"
#include "fsmonitor.h"
diff --git a/diff.c b/diff.c
index 1e83aaee6b..3c88c37908 100644
--- a/diff.c
+++ b/diff.c
@@ -4,6 +4,7 @@
#include "cache.h"
#include "abspath.h"
#include "alloc.h"
+#include "base85.h"
#include "config.h"
#include "convert.h"
#include "environment.h"
@@ -40,6 +41,7 @@
#include "object-name.h"
#include "setup.h"
#include "strmap.h"
+#include "ws.h"
#include "wrapper.h"
#ifdef NO_FAST_WORKING_DIRECTORY
@@ -3005,6 +3007,24 @@ static int dirstat_compare(const void *_a, const void *_b)
return strcmp(a->name, b->name);
}
+static void conclude_dirstat(struct diff_options *options,
+ struct dirstat_dir *dir,
+ unsigned long changed)
+{
+ struct dirstat_file *to_free = dir->files;
+
+ if (!changed) {
+ /* This can happen even with many files, if everything was renames */
+ ;
+ } else {
+ /* Show all directories with more than x% of the changes */
+ QSORT(dir->files, dir->nr, dirstat_compare);
+ gather_dirstat(options, dir, changed, "", 0);
+ }
+
+ free(to_free);
+}
+
static void show_dirstat(struct diff_options *options)
{
int i;
@@ -3094,13 +3114,7 @@ found_damage:
dir.nr++;
}
- /* This can happen even with many files, if everything was renames */
- if (!changed)
- return;
-
- /* Show all directories with more than x% of the changes */
- QSORT(dir.files, dir.nr, dirstat_compare);
- gather_dirstat(options, &dir, changed, "", 0);
+ conclude_dirstat(options, &dir, changed);
}
static void show_dirstat_by_line(struct diffstat_t *data, struct diff_options *options)
@@ -3138,13 +3152,7 @@ static void show_dirstat_by_line(struct diffstat_t *data, struct diff_options *o
dir.nr++;
}
- /* This can happen even with many files, if everything was renames */
- if (!changed)
- return;
-
- /* Show all directories with more than x% of the changes */
- QSORT(dir.files, dir.nr, dirstat_compare);
- gather_dirstat(options, &dir, changed, "", 0);
+ conclude_dirstat(options, &dir, changed);
}
static void free_diffstat_file(struct diffstat_file *f)
diff --git a/diff.h b/diff.h
index 6a0737b9c3..3a7a9e8b88 100644
--- a/diff.h
+++ b/diff.h
@@ -4,7 +4,6 @@
#ifndef DIFF_H
#define DIFF_H
-#include "tree-walk.h"
#include "pathspec.h"
#include "oidset.h"
#include "strbuf.h"
diff --git a/diffcore.h b/diffcore.h
index 1701ed50b9..5ffe4ec788 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -4,7 +4,7 @@
#ifndef DIFFCORE_H
#define DIFFCORE_H
-#include "hash.h"
+#include "hash-ll.h"
struct diff_options;
struct mem_pool;
diff --git a/dir.c b/dir.c
index aa840995c4..a7469df3ac 100644
--- a/dir.c
+++ b/dir.c
@@ -25,7 +25,9 @@
#include "fsmonitor.h"
#include "setup.h"
#include "submodule-config.h"
+#include "symlinks.h"
#include "trace2.h"
+#include "tree.h"
#include "wrapper.h"
/*
diff --git a/dir.h b/dir.h
index 3d6c87387e..79b85a01ee 100644
--- a/dir.h
+++ b/dir.h
@@ -640,4 +640,19 @@ static inline int starts_with_dot_dot_slash_native(const char *const path)
return path_match_flags(path, what | PATH_MATCH_NATIVE);
}
+
+#if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
+#define DTYPE(de) ((de)->d_type)
+#else
+#undef DT_UNKNOWN
+#undef DT_DIR
+#undef DT_REG
+#undef DT_LNK
+#define DT_UNKNOWN 0
+#define DT_DIR 1
+#define DT_REG 2
+#define DT_LNK 3
+#define DTYPE(de) DT_UNKNOWN
+#endif
+
#endif
diff --git a/editor.c b/editor.c
index b34e10606d..38c5dbbb79 100644
--- a/editor.c
+++ b/editor.c
@@ -6,6 +6,7 @@
#include "environment.h"
#include "gettext.h"
#include "pager.h"
+#include "path.h"
#include "strbuf.h"
#include "strvec.h"
#include "run-command.h"
diff --git a/entry.c b/entry.c
index d89e61fa64..91a540bd29 100644
--- a/entry.c
+++ b/entry.c
@@ -7,6 +7,7 @@
#include "hex.h"
#include "streaming.h"
#include "submodule.h"
+#include "symlinks.h"
#include "progress.h"
#include "fsmonitor.h"
#include "entry.h"
diff --git a/environment.c b/environment.c
index 8a96997539..28d18eaca8 100644
--- a/environment.c
+++ b/environment.c
@@ -7,7 +7,7 @@
* even if you might want to know where the git directory etc
* are.
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "branch.h"
#include "convert.h"
@@ -67,7 +67,6 @@ int read_replace_refs = 1;
enum eol core_eol = EOL_UNSET;
int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;
char *check_roundtrip_encoding = "SHIFT-JIS";
-unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
diff --git a/exec-cmd.c b/exec-cmd.c
index 6f61846389..1e34e48c0e 100644
--- a/exec-cmd.c
+++ b/exec-cmd.c
@@ -3,6 +3,7 @@
#include "environment.h"
#include "exec-cmd.h"
#include "gettext.h"
+#include "path.h"
#include "quote.h"
#include "strvec.h"
#include "trace.h"
diff --git a/fetch-pack.c b/fetch-pack.c
index 6fa6e8af9a..0f71054fba 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -2,6 +2,7 @@
#include "alloc.h"
#include "repository.h"
#include "config.h"
+#include "date.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
diff --git a/fsck.c b/fsck.c
index adbe8bf59e..3261ef9ec2 100644
--- a/fsck.c
+++ b/fsck.c
@@ -1,5 +1,6 @@
#include "git-compat-util.h"
#include "alloc.h"
+#include "date.h"
#include "hex.h"
#include "object-store.h"
#include "repository.h"
diff --git a/fsmonitor--daemon.h b/fsmonitor--daemon.h
index e24838f9a8..70d776c54f 100644
--- a/fsmonitor--daemon.h
+++ b/fsmonitor--daemon.h
@@ -3,7 +3,6 @@
#ifdef HAVE_FSMONITOR_DAEMON_BACKEND
-#include "cache.h"
#include "dir.h"
#include "run-command.h"
#include "simple-ipc.h"
diff --git a/fsmonitor-ipc.c b/fsmonitor-ipc.c
index 866828e299..6a6a89764a 100644
--- a/fsmonitor-ipc.c
+++ b/fsmonitor-ipc.c
@@ -3,6 +3,7 @@
#include "gettext.h"
#include "simple-ipc.h"
#include "fsmonitor-ipc.h"
+#include "repository.h"
#include "run-command.h"
#include "strbuf.h"
#include "trace2.h"
diff --git a/git-send-email.perl b/git-send-email.perl
index 66c9171109..89d8237e89 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -87,8 +87,10 @@ git send-email --dump-aliases
Automating:
--identity <str> * Use the sendemail.<id> options.
- --to-cmd <str> * Email To: via `<str> \$patch_path`
- --cc-cmd <str> * Email Cc: via `<str> \$patch_path`
+ --to-cmd <str> * Email To: via `<str> \$patch_path`.
+ --cc-cmd <str> * Email Cc: via `<str> \$patch_path`.
+ --header-cmd <str> * Add headers via `<str> \$patch_path`.
+ --no-header-cmd * Disable any header command in use.
--suppress-cc <str> * author, self, sob, cc, cccmd, body, bodycc, misc-by, all.
--[no-]cc-cover * Email Cc: addresses in the cover letter.
--[no-]to-cover * Email To: addresses in the cover letter.
@@ -202,7 +204,7 @@ my (@to,@cc,@xh,$envelope_sender,
$author,$sender,$smtp_authpass,$annotate,$compose,$time);
# Things we either get from config, *or* are overridden on the
# command-line.
-my ($no_cc, $no_to, $no_bcc, $no_identity);
+my ($no_cc, $no_to, $no_bcc, $no_identity, $no_header_cmd);
my (@config_to, @getopt_to);
my (@config_cc, @getopt_cc);
my (@config_bcc, @getopt_bcc);
@@ -269,7 +271,7 @@ sub do_edit {
# Variables with corresponding config settings
my ($suppress_from, $signed_off_by_cc);
my ($cover_cc, $cover_to);
-my ($to_cmd, $cc_cmd);
+my ($to_cmd, $cc_cmd, $header_cmd);
my ($smtp_server, $smtp_server_port, @smtp_server_options);
my ($smtp_authuser, $smtp_encryption, $smtp_ssl_cert_path);
my ($batch_size, $relogin_delay);
@@ -318,6 +320,7 @@ my %config_settings = (
"tocmd" => \$to_cmd,
"cc" => \@config_cc,
"cccmd" => \$cc_cmd,
+ "headercmd" => \$header_cmd,
"aliasfiletype" => \$aliasfiletype,
"bcc" => \@config_bcc,
"suppresscc" => \@suppress_cc,
@@ -519,6 +522,8 @@ my %options = (
"compose" => \$compose,
"quiet" => \$quiet,
"cc-cmd=s" => \$cc_cmd,
+ "header-cmd=s" => \$header_cmd,
+ "no-header-cmd" => \$no_header_cmd,
"suppress-from!" => \$suppress_from,
"no-suppress-from" => sub {$suppress_from = 0},
"suppress-cc=s" => \@suppress_cc,
@@ -792,7 +797,19 @@ if (@rev_list_opts) {
@rev_list_opts);
}
-@files = handle_backup_files(@files);
+if (defined $sender) {
+ $sender =~ s/^\s+|\s+$//g;
+ ($sender) = expand_aliases($sender);
+} else {
+ $sender = $repoauthor->() || $repocommitter->() || '';
+}
+
+# $sender could be an already sanitized address
+# (e.g. sendemail.from could be manually sanitized by user).
+# But it's a no-op to run sanitize_address on an already sanitized address.
+$sender = sanitize_address($sender);
+
+$time = time - scalar $#files;
if ($validate) {
# FIFOs can only be read once, exclude them from validation.
@@ -810,6 +827,7 @@ if ($validate) {
$ENV{GIT_SENDEMAIL_FILE_TOTAL} = "$num_files";
foreach my $r (@real_files) {
$ENV{GIT_SENDEMAIL_FILE_COUNTER} = "$num";
+ pre_process_file($r, 1);
validate_patch($r, $target_xfer_encoding);
$num += 1;
}
@@ -817,6 +835,8 @@ if ($validate) {
delete $ENV{GIT_SENDEMAIL_FILE_TOTAL};
}
+@files = handle_backup_files(@files);
+
if (@files) {
unless ($quiet) {
print $_,"\n" for (@files);
@@ -1065,18 +1085,6 @@ if (!$force) {
}
}
-if (defined $sender) {
- $sender =~ s/^\s+|\s+$//g;
- ($sender) = expand_aliases($sender);
-} else {
- $sender = $repoauthor->() || $repocommitter->() || '';
-}
-
-# $sender could be an already sanitized address
-# (e.g. sendemail.from could be manually sanitized by user).
-# But it's a no-op to run sanitize_address on an already sanitized address.
-$sender = sanitize_address($sender);
-
my $to_whom = __("To whom should the emails be sent (if anyone)?");
my $prompting = 0;
if (!@initial_to && !defined $to_cmd) {
@@ -1236,10 +1244,6 @@ sub make_message_id {
#print "new message id = $message_id\n"; # Was useful for debugging
}
-
-
-$time = time - scalar $#files;
-
sub unquote_rfc2047 {
local ($_) = @_;
my $charset;
@@ -1517,16 +1521,7 @@ sub file_name_is_absolute {
return File::Spec::Functions::file_name_is_absolute($path);
}
-# Prepares the email, then asks the user what to do.
-#
-# If the user chooses to send the email, it's sent and 1 is returned.
-# If the user chooses not to send the email, 0 is returned.
-# If the user decides they want to make further edits, -1 is returned and the
-# caller is expected to call send_message again after the edits are performed.
-#
-# If an error occurs sending the email, this just dies.
-
-sub send_message {
+sub gen_header {
my @recipients = unique_email_list(@to);
@cc = (grep { my $cc = extract_valid_address_or_die($_);
not grep { $cc eq $_ || $_ =~ /<\Q${cc}\E>$/ } @recipients
@@ -1568,6 +1563,22 @@ Message-ID: $message_id
if (@xh) {
$header .= join("\n", @xh) . "\n";
}
+ my $recipients_ref = \@recipients;
+ return ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header);
+}
+
+# Prepares the email, then asks the user what to do.
+#
+# If the user chooses to send the email, it's sent and 1 is returned.
+# If the user chooses not to send the email, 0 is returned.
+# If the user decides they want to make further edits, -1 is returned and the
+# caller is expected to call send_message again after the edits are performed.
+#
+# If an error occurs sending the email, this just dies.
+
+sub send_message {
+ my ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header) = gen_header();
+ my @recipients = @$recipients_ref;
my @sendmail_parameters = ('-i', @recipients);
my $raw_from = $sender;
@@ -1757,11 +1768,8 @@ $in_reply_to = $initial_in_reply_to;
$references = $initial_in_reply_to || '';
$message_num = 0;
-# Prepares the email, prompts the user, sends it out
-# Returns 0 if an edit was done and the function should be called again, or 1
-# otherwise.
-sub process_file {
- my ($t) = @_;
+sub pre_process_file {
+ my ($t, $quiet) = @_;
open my $fh, "<", $t or die sprintf(__("can't open file %s"), $t);
@@ -1780,16 +1788,16 @@ sub process_file {
$subject = $initial_subject;
$message = "";
$message_num++;
- # First unfold multiline header fields
+ # Retrieve and unfold header fields.
+ my @header_lines = ();
while(<$fh>) {
last if /^\s*$/;
- if (/^\s+\S/ and @header) {
- chomp($header[$#header]);
- s/^\s+/ /;
- $header[$#header] .= $_;
- } else {
- push(@header, $_);
- }
+ push(@header_lines, $_);
+ }
+ @header = unfold_headers(@header_lines);
+ # Add computed headers, if applicable.
+ unless ($no_header_cmd || ! $header_cmd) {
+ push @header, invoke_header_cmd($header_cmd, $t);
}
# Now parse the header
foreach(@header) {
@@ -1915,9 +1923,9 @@ sub process_file {
}
close $fh;
- push @to, recipients_cmd("to-cmd", "to", $to_cmd, $t)
+ push @to, recipients_cmd("to-cmd", "to", $to_cmd, $t, $quiet)
if defined $to_cmd;
- push @cc, recipients_cmd("cc-cmd", "cc", $cc_cmd, $t)
+ push @cc, recipients_cmd("cc-cmd", "cc", $cc_cmd, $t, $quiet)
if defined $cc_cmd && !$suppress_cc{'cccmd'};
if ($broken_encoding{$t} && !$has_content_type) {
@@ -1976,6 +1984,15 @@ sub process_file {
@initial_to = @to;
}
}
+}
+
+# Prepares the email, prompts the user, and sends it out
+# Returns 0 if an edit was done and the function should be called again, or 1
+# on the email being successfully sent out.
+sub process_file {
+ my ($t) = @_;
+
+ pre_process_file($t, $quiet);
my $message_was_sent = send_message();
if ($message_was_sent == -1) {
@@ -2021,15 +2038,64 @@ foreach my $t (@files) {
}
}
+# Execute a command and return its output lines as an array. Blank
+# lines which do not appear at the end of the output are reported as
+# errors.
+sub execute_cmd {
+ my ($prefix, $cmd, $file) = @_;
+ my @lines = ();
+ my $seen_blank_line = 0;
+ open my $fh, "-|", "$cmd \Q$file\E"
+ or die sprintf(__("(%s) Could not execute '%s'"), $prefix, $cmd);
+ while (my $line = <$fh>) {
+ die sprintf(__("(%s) Malformed output from '%s'"), $prefix, $cmd)
+ if $seen_blank_line;
+ if ($line =~ /^$/) {
+ $seen_blank_line = $line =~ /^$/;
+ next;
+ }
+ push @lines, $line;
+ }
+ close $fh
+ or die sprintf(__("(%s) failed to close pipe to '%s'"), $prefix, $cmd);
+ return @lines;
+}
+
+# Process headers lines, unfolding multiline headers as defined by RFC
+# 2822.
+sub unfold_headers {
+ my @headers;
+ foreach(@_) {
+ last if /^\s*$/;
+ if (/^\s+\S/ and @headers) {
+ chomp($headers[$#headers]);
+ s/^\s+/ /;
+ $headers[$#headers] .= $_;
+ } else {
+ push(@headers, $_);
+ }
+ }
+ return @headers;
+}
+
+# Invoke the provided CMD with FILE as an argument, which should
+# output RFC 2822 email headers. Fold multiline headers and return the
+# headers as an array.
+sub invoke_header_cmd {
+ my ($cmd, $file) = @_;
+ my @lines = execute_cmd("header-cmd", $header_cmd, $file);
+ return unfold_headers(@lines);
+}
+
# Execute a command (e.g. $to_cmd) to get a list of email addresses
# and return a results array
sub recipients_cmd {
- my ($prefix, $what, $cmd, $file) = @_;
-
+ my ($prefix, $what, $cmd, $file, $quiet) = @_;
+ my @lines = ();
my @addresses = ();
- open my $fh, "-|", "$cmd \Q$file\E"
- or die sprintf(__("(%s) Could not execute '%s'"), $prefix, $cmd);
- while (my $address = <$fh>) {
+
+ @lines = execute_cmd($prefix, $cmd, $file);
+ for my $address (@lines) {
$address =~ s/^\s*//g;
$address =~ s/\s*$//g;
$address = sanitize_address($address);
@@ -2038,8 +2104,6 @@ sub recipients_cmd {
printf(__("(%s) Adding %s: %s from: '%s'\n"),
$prefix, $what, $address, $cmd) unless $quiet;
}
- close $fh
- or die sprintf(__("(%s) failed to close pipe to '%s'"), $prefix, $cmd);
return @addresses;
}
@@ -2110,10 +2174,21 @@ sub validate_patch {
chdir($repo->wc_path() or $repo->repo_path())
or die("chdir: $!");
local $ENV{"GIT_DIR"} = $repo->repo_path();
+
+ my ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header) = gen_header();
+
+ require File::Temp;
+ my ($header_filehandle, $header_filename) = File::Temp::tempfile(
+ TEMPLATE => ".gitsendemail.header.XXXXXX",
+ DIR => $repo->repo_path(),
+ UNLINK => 1,
+ );
+ print $header_filehandle $header;
+
my @cmd = ("git", "hook", "run", "--ignore-missing",
$hook_name, "--");
- my @cmd_msg = (@cmd, "<patch>");
- my @cmd_run = (@cmd, $target);
+ my @cmd_msg = (@cmd, "<patch>", "<header>");
+ my @cmd_run = (@cmd, $target, $header_filename);
$hook_error = system_or_msg(\@cmd_run, undef, "@cmd_msg");
chdir($cwd_save) or die("chdir: $!");
}
diff --git a/gitk-git/gitk b/gitk-git/gitk
index 0ae7d68590..df3ba2ea99 100755
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -353,6 +353,16 @@ proc parseviewrevs {view revs} {
return $ret
}
+# Escapes a list of filter paths to be passed to git log via stdin. Note that
+# paths must not be quoted.
+proc escape_filter_paths {paths} {
+ set escaped [list]
+ foreach path $paths {
+ lappend escaped [string map {\\ \\\\ "\ " "\\\ "} $path]
+ }
+ return $escaped
+}
+
# Start off a git log process and arrange to read its output
proc start_rev_list {view} {
global startmsecs commitidx viewcomplete curview
@@ -405,14 +415,17 @@ proc start_rev_list {view} {
if {$revs eq {}} {
return 0
}
- set args [concat $vflags($view) $revs]
+ set args $vflags($view)
} else {
+ set revs {}
set args $vorigargs($view)
}
if {[catch {
set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
- --parents --boundary $args "--" $files] r]
+ --parents --boundary $args --stdin \
+ "<<[join [concat $revs "--" \
+ [escape_filter_paths $files]] "\\n"]"] r]
} err]} {
error_popup "[mc "Error executing git log:"] $err"
return 0
@@ -554,13 +567,20 @@ proc updatecommits {} {
set revs $newrevs
set vposids($view) [lsort -unique [concat $oldpos $vposids($view)]]
}
- set args [concat $vflags($view) $revs --not $oldpos]
+ set args $vflags($view)
+ foreach r $oldpos {
+ lappend revs "^$r"
+ }
} else {
+ set revs {}
set args $vorigargs($view)
}
if {[catch {
set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
- --parents --boundary $args "--" $vfilelimit($view)] r]
+ --parents --boundary $args --stdin \
+ "<<[join [concat $revs "--" \
+ [escape_filter_paths \
+ $vfilelimit($view)]] "\\n"]"] r]
} err]} {
error_popup "[mc "Error executing git log:"] $err"
return
@@ -10231,10 +10251,16 @@ proc getallcommits {} {
foreach id $seeds {
lappend ids "^$id"
}
+ lappend ids "--"
}
}
if {$ids ne {}} {
- set fd [open [concat $cmd $ids] r]
+ if {$ids eq "--all"} {
+ set cmd [concat $cmd "--all"]
+ } else {
+ set cmd [concat $cmd --stdin "<<[join $ids "\\n"]"]
+ }
+ set fd [open $cmd r]
fconfigure $fd -blocking 0
incr allcommits
nowbusy allcommits
diff --git a/gpg-interface.c b/gpg-interface.c
index f3ac5acdd9..19a3471a0b 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -1,12 +1,14 @@
#include "git-compat-util.h"
#include "commit.h"
#include "config.h"
+#include "date.h"
#include "gettext.h"
#include "run-command.h"
#include "strbuf.h"
#include "dir.h"
#include "ident.h"
#include "gpg-interface.h"
+#include "path.h"
#include "sigchain.h"
#include "tempfile.h"
#include "alias.h"
diff --git a/grep.c b/grep.c
index 073559f2cd..f00986c451 100644
--- a/grep.c
+++ b/grep.c
@@ -4,6 +4,7 @@
#include "grep.h"
#include "hex.h"
#include "object-store.h"
+#include "pretty.h"
#include "userdiff.h"
#include "xdiff-interface.h"
#include "diff.h"
diff --git a/hash-ll.h b/hash-ll.h
new file mode 100644
index 0000000000..8050925137
--- /dev/null
+++ b/hash-ll.h
@@ -0,0 +1,276 @@
+#ifndef HASH_LL_H
+#define HASH_LL_H
+
+#if defined(SHA1_APPLE)
+#include <CommonCrypto/CommonDigest.h>
+#elif defined(SHA1_OPENSSL)
+#include <openssl/sha.h>
+#elif defined(SHA1_DC)
+#include "sha1dc_git.h"
+#else /* SHA1_BLK */
+#include "block-sha1/sha1.h"
+#endif
+
+#if defined(SHA256_NETTLE)
+#include "sha256/nettle.h"
+#elif defined(SHA256_GCRYPT)
+#define SHA256_NEEDS_CLONE_HELPER
+#include "sha256/gcrypt.h"
+#elif defined(SHA256_OPENSSL)
+#include <openssl/sha.h>
+#else
+#include "sha256/block/sha256.h"
+#endif
+
+#ifndef platform_SHA_CTX
+/*
+ * platform's underlying implementation of SHA-1; could be OpenSSL,
+ * blk_SHA, Apple CommonCrypto, etc... Note that the relevant
+ * SHA-1 header may have already defined platform_SHA_CTX for our
+ * own implementations like block-sha1, so we list
+ * the default for OpenSSL compatible SHA-1 implementations here.
+ */
+#define platform_SHA_CTX SHA_CTX
+#define platform_SHA1_Init SHA1_Init
+#define platform_SHA1_Update SHA1_Update
+#define platform_SHA1_Final SHA1_Final
+#endif
+
+#define git_SHA_CTX platform_SHA_CTX
+#define git_SHA1_Init platform_SHA1_Init
+#define git_SHA1_Update platform_SHA1_Update
+#define git_SHA1_Final platform_SHA1_Final
+
+#ifndef platform_SHA256_CTX
+#define platform_SHA256_CTX SHA256_CTX
+#define platform_SHA256_Init SHA256_Init
+#define platform_SHA256_Update SHA256_Update
+#define platform_SHA256_Final SHA256_Final
+#endif
+
+#define git_SHA256_CTX platform_SHA256_CTX
+#define git_SHA256_Init platform_SHA256_Init
+#define git_SHA256_Update platform_SHA256_Update
+#define git_SHA256_Final platform_SHA256_Final
+
+#ifdef platform_SHA256_Clone
+#define git_SHA256_Clone platform_SHA256_Clone
+#endif
+
+#ifdef SHA1_MAX_BLOCK_SIZE
+#include "compat/sha1-chunked.h"
+#undef git_SHA1_Update
+#define git_SHA1_Update git_SHA1_Update_Chunked
+#endif
+
+static inline void git_SHA1_Clone(git_SHA_CTX *dst, const git_SHA_CTX *src)
+{
+ memcpy(dst, src, sizeof(*dst));
+}
+
+#ifndef SHA256_NEEDS_CLONE_HELPER
+static inline void git_SHA256_Clone(git_SHA256_CTX *dst, const git_SHA256_CTX *src)
+{
+ memcpy(dst, src, sizeof(*dst));
+}
+#endif
+
+/*
+ * Note that these constants are suitable for indexing the hash_algos array and
+ * comparing against each other, but are otherwise arbitrary, so they should not
+ * be exposed to the user or serialized to disk. To know whether a
+ * git_hash_algo struct points to some usable hash function, test the format_id
+ * field for being non-zero. Use the name field for user-visible situations and
+ * the format_id field for fixed-length fields on disk.
+ */
+/* An unknown hash function. */
+#define GIT_HASH_UNKNOWN 0
+/* SHA-1 */
+#define GIT_HASH_SHA1 1
+/* SHA-256 */
+#define GIT_HASH_SHA256 2
+/* Number of algorithms supported (including unknown). */
+#define GIT_HASH_NALGOS (GIT_HASH_SHA256 + 1)
+
+/* "sha1", big-endian */
+#define GIT_SHA1_FORMAT_ID 0x73686131
+
+/* The length in bytes and in hex digits of an object name (SHA-1 value). */
+#define GIT_SHA1_RAWSZ 20
+#define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)
+/* The block size of SHA-1. */
+#define GIT_SHA1_BLKSZ 64
+
+/* "s256", big-endian */
+#define GIT_SHA256_FORMAT_ID 0x73323536
+
+/* The length in bytes and in hex digits of an object name (SHA-256 value). */
+#define GIT_SHA256_RAWSZ 32
+#define GIT_SHA256_HEXSZ (2 * GIT_SHA256_RAWSZ)
+/* The block size of SHA-256. */
+#define GIT_SHA256_BLKSZ 64
+
+/* The length in byte and in hex digits of the largest possible hash value. */
+#define GIT_MAX_RAWSZ GIT_SHA256_RAWSZ
+#define GIT_MAX_HEXSZ GIT_SHA256_HEXSZ
+/* The largest possible block size for any supported hash. */
+#define GIT_MAX_BLKSZ GIT_SHA256_BLKSZ
+
+struct object_id {
+ unsigned char hash[GIT_MAX_RAWSZ];
+ int algo; /* XXX requires 4-byte alignment */
+};
+
+#define GET_OID_QUIETLY 01
+#define GET_OID_COMMIT 02
+#define GET_OID_COMMITTISH 04
+#define GET_OID_TREE 010
+#define GET_OID_TREEISH 020
+#define GET_OID_BLOB 040
+#define GET_OID_FOLLOW_SYMLINKS 0100
+#define GET_OID_RECORD_PATH 0200
+#define GET_OID_ONLY_TO_DIE 04000
+#define GET_OID_REQUIRE_PATH 010000
+
+#define GET_OID_DISAMBIGUATORS \
+ (GET_OID_COMMIT | GET_OID_COMMITTISH | \
+ GET_OID_TREE | GET_OID_TREEISH | \
+ GET_OID_BLOB)
+
+enum get_oid_result {
+ FOUND = 0,
+ MISSING_OBJECT = -1, /* The requested object is missing */
+ SHORT_NAME_AMBIGUOUS = -2,
+ /* The following only apply when symlinks are followed */
+ DANGLING_SYMLINK = -4, /*
+ * The initial symlink is there, but
+ * (transitively) points to a missing
+ * in-tree file
+ */
+ SYMLINK_LOOP = -5,
+ NOT_DIR = -6, /*
+ * Somewhere along the symlink chain, a path is
+ * requested which contains a file as a
+ * non-final element.
+ */
+};
+
+/* A suitably aligned type for stack allocations of hash contexts. */
+union git_hash_ctx {
+ git_SHA_CTX sha1;
+ git_SHA256_CTX sha256;
+};
+typedef union git_hash_ctx git_hash_ctx;
+
+typedef void (*git_hash_init_fn)(git_hash_ctx *ctx);
+typedef void (*git_hash_clone_fn)(git_hash_ctx *dst, const git_hash_ctx *src);
+typedef void (*git_hash_update_fn)(git_hash_ctx *ctx, const void *in, size_t len);
+typedef void (*git_hash_final_fn)(unsigned char *hash, git_hash_ctx *ctx);
+typedef void (*git_hash_final_oid_fn)(struct object_id *oid, git_hash_ctx *ctx);
+
+struct git_hash_algo {
+ /*
+ * The name of the algorithm, as appears in the config file and in
+ * messages.
+ */
+ const char *name;
+
+ /* A four-byte version identifier, used in pack indices. */
+ uint32_t format_id;
+
+ /* The length of the hash in binary. */
+ size_t rawsz;
+
+ /* The length of the hash in hex characters. */
+ size_t hexsz;
+
+ /* The block size of the hash. */
+ size_t blksz;
+
+ /* The hash initialization function. */
+ git_hash_init_fn init_fn;
+
+ /* The hash context cloning function. */
+ git_hash_clone_fn clone_fn;
+
+ /* The hash update function. */
+ git_hash_update_fn update_fn;
+
+ /* The hash finalization function. */
+ git_hash_final_fn final_fn;
+
+ /* The hash finalization function for object IDs. */
+ git_hash_final_oid_fn final_oid_fn;
+
+ /* The OID of the empty tree. */
+ const struct object_id *empty_tree;
+
+ /* The OID of the empty blob. */
+ const struct object_id *empty_blob;
+
+ /* The all-zeros OID. */
+ const struct object_id *null_oid;
+};
+extern const struct git_hash_algo hash_algos[GIT_HASH_NALGOS];
+
+/*
+ * Return a GIT_HASH_* constant based on the name. Returns GIT_HASH_UNKNOWN if
+ * the name doesn't match a known algorithm.
+ */
+int hash_algo_by_name(const char *name);
+/* Identical, except based on the format ID. */
+int hash_algo_by_id(uint32_t format_id);
+/* Identical, except based on the length. */
+int hash_algo_by_length(int len);
+/* Identical, except for a pointer to struct git_hash_algo. */
+static inline int hash_algo_by_ptr(const struct git_hash_algo *p)
+{
+ return p - hash_algos;
+}
+
+const struct object_id *null_oid(void);
+
+static inline int hashcmp_algop(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop)
+{
+ /*
+ * Teach the compiler that there are only two possibilities of hash size
+ * here, so that it can optimize for this case as much as possible.
+ */
+ if (algop->rawsz == GIT_MAX_RAWSZ)
+ return memcmp(sha1, sha2, GIT_MAX_RAWSZ);
+ return memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
+}
+
+static inline int hasheq_algop(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop)
+{
+ /*
+ * We write this here instead of deferring to hashcmp so that the
+ * compiler can properly inline it and avoid calling memcmp.
+ */
+ if (algop->rawsz == GIT_MAX_RAWSZ)
+ return !memcmp(sha1, sha2, GIT_MAX_RAWSZ);
+ return !memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
+}
+
+static inline void oidcpy(struct object_id *dst, const struct object_id *src)
+{
+ memcpy(dst->hash, src->hash, GIT_MAX_RAWSZ);
+ dst->algo = src->algo;
+}
+
+static inline struct object_id *oiddup(const struct object_id *src)
+{
+ struct object_id *dst = xmalloc(sizeof(struct object_id));
+ oidcpy(dst, src);
+ return dst;
+}
+
+static inline void oid_set_algo(struct object_id *oid, const struct git_hash_algo *algop)
+{
+ oid->algo = hash_algo_by_ptr(algop);
+}
+
+const char *empty_tree_oid_hex(void);
+const char *empty_blob_oid_hex(void);
+
+#endif
diff --git a/hash-lookup.c b/hash-lookup.c
index b98ed5e11e..bb54dfde9c 100644
--- a/hash-lookup.c
+++ b/hash-lookup.c
@@ -1,4 +1,5 @@
#include "cache.h"
+#include "hash.h"
#include "hash-lookup.h"
static uint32_t take2(const struct object_id *oid, size_t ofs)
diff --git a/hash.h b/hash.h
index d39f73618c..615ae0691d 100644
--- a/hash.h
+++ b/hash.h
@@ -1,250 +1,11 @@
#ifndef HASH_H
#define HASH_H
+#include "hash-ll.h"
#include "repository.h"
-#if defined(SHA1_APPLE)
-#include <CommonCrypto/CommonDigest.h>
-#elif defined(SHA1_OPENSSL)
-#include <openssl/sha.h>
-#elif defined(SHA1_DC)
-#include "sha1dc_git.h"
-#else /* SHA1_BLK */
-#include "block-sha1/sha1.h"
-#endif
-
-#if defined(SHA256_NETTLE)
-#include "sha256/nettle.h"
-#elif defined(SHA256_GCRYPT)
-#define SHA256_NEEDS_CLONE_HELPER
-#include "sha256/gcrypt.h"
-#elif defined(SHA256_OPENSSL)
-#include <openssl/sha.h>
-#else
-#include "sha256/block/sha256.h"
-#endif
-
-#ifndef platform_SHA_CTX
-/*
- * platform's underlying implementation of SHA-1; could be OpenSSL,
- * blk_SHA, Apple CommonCrypto, etc... Note that the relevant
- * SHA-1 header may have already defined platform_SHA_CTX for our
- * own implementations like block-sha1, so we list
- * the default for OpenSSL compatible SHA-1 implementations here.
- */
-#define platform_SHA_CTX SHA_CTX
-#define platform_SHA1_Init SHA1_Init
-#define platform_SHA1_Update SHA1_Update
-#define platform_SHA1_Final SHA1_Final
-#endif
-
-#define git_SHA_CTX platform_SHA_CTX
-#define git_SHA1_Init platform_SHA1_Init
-#define git_SHA1_Update platform_SHA1_Update
-#define git_SHA1_Final platform_SHA1_Final
-
-#ifndef platform_SHA256_CTX
-#define platform_SHA256_CTX SHA256_CTX
-#define platform_SHA256_Init SHA256_Init
-#define platform_SHA256_Update SHA256_Update
-#define platform_SHA256_Final SHA256_Final
-#endif
-
-#define git_SHA256_CTX platform_SHA256_CTX
-#define git_SHA256_Init platform_SHA256_Init
-#define git_SHA256_Update platform_SHA256_Update
-#define git_SHA256_Final platform_SHA256_Final
-
-#ifdef platform_SHA256_Clone
-#define git_SHA256_Clone platform_SHA256_Clone
-#endif
-
-#ifdef SHA1_MAX_BLOCK_SIZE
-#include "compat/sha1-chunked.h"
-#undef git_SHA1_Update
-#define git_SHA1_Update git_SHA1_Update_Chunked
-#endif
-
-static inline void git_SHA1_Clone(git_SHA_CTX *dst, const git_SHA_CTX *src)
-{
- memcpy(dst, src, sizeof(*dst));
-}
-
-#ifndef SHA256_NEEDS_CLONE_HELPER
-static inline void git_SHA256_Clone(git_SHA256_CTX *dst, const git_SHA256_CTX *src)
-{
- memcpy(dst, src, sizeof(*dst));
-}
-#endif
-
-/*
- * Note that these constants are suitable for indexing the hash_algos array and
- * comparing against each other, but are otherwise arbitrary, so they should not
- * be exposed to the user or serialized to disk. To know whether a
- * git_hash_algo struct points to some usable hash function, test the format_id
- * field for being non-zero. Use the name field for user-visible situations and
- * the format_id field for fixed-length fields on disk.
- */
-/* An unknown hash function. */
-#define GIT_HASH_UNKNOWN 0
-/* SHA-1 */
-#define GIT_HASH_SHA1 1
-/* SHA-256 */
-#define GIT_HASH_SHA256 2
-/* Number of algorithms supported (including unknown). */
-#define GIT_HASH_NALGOS (GIT_HASH_SHA256 + 1)
-
-/* "sha1", big-endian */
-#define GIT_SHA1_FORMAT_ID 0x73686131
-
-/* The length in bytes and in hex digits of an object name (SHA-1 value). */
-#define GIT_SHA1_RAWSZ 20
-#define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)
-/* The block size of SHA-1. */
-#define GIT_SHA1_BLKSZ 64
-
-/* "s256", big-endian */
-#define GIT_SHA256_FORMAT_ID 0x73323536
-
-/* The length in bytes and in hex digits of an object name (SHA-256 value). */
-#define GIT_SHA256_RAWSZ 32
-#define GIT_SHA256_HEXSZ (2 * GIT_SHA256_RAWSZ)
-/* The block size of SHA-256. */
-#define GIT_SHA256_BLKSZ 64
-
-/* The length in byte and in hex digits of the largest possible hash value. */
-#define GIT_MAX_RAWSZ GIT_SHA256_RAWSZ
-#define GIT_MAX_HEXSZ GIT_SHA256_HEXSZ
-/* The largest possible block size for any supported hash. */
-#define GIT_MAX_BLKSZ GIT_SHA256_BLKSZ
-
-struct object_id {
- unsigned char hash[GIT_MAX_RAWSZ];
- int algo; /* XXX requires 4-byte alignment */
-};
-
-#define GET_OID_QUIETLY 01
-#define GET_OID_COMMIT 02
-#define GET_OID_COMMITTISH 04
-#define GET_OID_TREE 010
-#define GET_OID_TREEISH 020
-#define GET_OID_BLOB 040
-#define GET_OID_FOLLOW_SYMLINKS 0100
-#define GET_OID_RECORD_PATH 0200
-#define GET_OID_ONLY_TO_DIE 04000
-#define GET_OID_REQUIRE_PATH 010000
-
-#define GET_OID_DISAMBIGUATORS \
- (GET_OID_COMMIT | GET_OID_COMMITTISH | \
- GET_OID_TREE | GET_OID_TREEISH | \
- GET_OID_BLOB)
-
-enum get_oid_result {
- FOUND = 0,
- MISSING_OBJECT = -1, /* The requested object is missing */
- SHORT_NAME_AMBIGUOUS = -2,
- /* The following only apply when symlinks are followed */
- DANGLING_SYMLINK = -4, /*
- * The initial symlink is there, but
- * (transitively) points to a missing
- * in-tree file
- */
- SYMLINK_LOOP = -5,
- NOT_DIR = -6, /*
- * Somewhere along the symlink chain, a path is
- * requested which contains a file as a
- * non-final element.
- */
-};
-
-/* A suitably aligned type for stack allocations of hash contexts. */
-union git_hash_ctx {
- git_SHA_CTX sha1;
- git_SHA256_CTX sha256;
-};
-typedef union git_hash_ctx git_hash_ctx;
-
-typedef void (*git_hash_init_fn)(git_hash_ctx *ctx);
-typedef void (*git_hash_clone_fn)(git_hash_ctx *dst, const git_hash_ctx *src);
-typedef void (*git_hash_update_fn)(git_hash_ctx *ctx, const void *in, size_t len);
-typedef void (*git_hash_final_fn)(unsigned char *hash, git_hash_ctx *ctx);
-typedef void (*git_hash_final_oid_fn)(struct object_id *oid, git_hash_ctx *ctx);
-
-struct git_hash_algo {
- /*
- * The name of the algorithm, as appears in the config file and in
- * messages.
- */
- const char *name;
-
- /* A four-byte version identifier, used in pack indices. */
- uint32_t format_id;
-
- /* The length of the hash in binary. */
- size_t rawsz;
-
- /* The length of the hash in hex characters. */
- size_t hexsz;
-
- /* The block size of the hash. */
- size_t blksz;
-
- /* The hash initialization function. */
- git_hash_init_fn init_fn;
-
- /* The hash context cloning function. */
- git_hash_clone_fn clone_fn;
-
- /* The hash update function. */
- git_hash_update_fn update_fn;
-
- /* The hash finalization function. */
- git_hash_final_fn final_fn;
-
- /* The hash finalization function for object IDs. */
- git_hash_final_oid_fn final_oid_fn;
-
- /* The OID of the empty tree. */
- const struct object_id *empty_tree;
-
- /* The OID of the empty blob. */
- const struct object_id *empty_blob;
-
- /* The all-zeros OID. */
- const struct object_id *null_oid;
-};
-extern const struct git_hash_algo hash_algos[GIT_HASH_NALGOS];
-
-/*
- * Return a GIT_HASH_* constant based on the name. Returns GIT_HASH_UNKNOWN if
- * the name doesn't match a known algorithm.
- */
-int hash_algo_by_name(const char *name);
-/* Identical, except based on the format ID. */
-int hash_algo_by_id(uint32_t format_id);
-/* Identical, except based on the length. */
-int hash_algo_by_length(int len);
-/* Identical, except for a pointer to struct git_hash_algo. */
-static inline int hash_algo_by_ptr(const struct git_hash_algo *p)
-{
- return p - hash_algos;
-}
-
#define the_hash_algo the_repository->hash_algo
-const struct object_id *null_oid(void);
-
-static inline int hashcmp_algop(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop)
-{
- /*
- * Teach the compiler that there are only two possibilities of hash size
- * here, so that it can optimize for this case as much as possible.
- */
- if (algop->rawsz == GIT_MAX_RAWSZ)
- return memcmp(sha1, sha2, GIT_MAX_RAWSZ);
- return memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
-}
-
static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2)
{
return hashcmp_algop(sha1, sha2, the_hash_algo);
@@ -260,17 +21,6 @@ static inline int oidcmp(const struct object_id *oid1, const struct object_id *o
return hashcmp_algop(oid1->hash, oid2->hash, algop);
}
-static inline int hasheq_algop(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop)
-{
- /*
- * We write this here instead of deferring to hashcmp so that the
- * compiler can properly inline it and avoid calling memcmp.
- */
- if (algop->rawsz == GIT_MAX_RAWSZ)
- return !memcmp(sha1, sha2, GIT_MAX_RAWSZ);
- return !memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
-}
-
static inline int hasheq(const unsigned char *sha1, const unsigned char *sha2)
{
return hasheq_algop(sha1, sha2, the_hash_algo);
@@ -296,12 +46,6 @@ static inline void hashcpy(unsigned char *sha_dst, const unsigned char *sha_src)
memcpy(sha_dst, sha_src, the_hash_algo->rawsz);
}
-static inline void oidcpy(struct object_id *dst, const struct object_id *src)
-{
- memcpy(dst->hash, src->hash, GIT_MAX_RAWSZ);
- dst->algo = src->algo;
-}
-
/* Like oidcpy() but zero-pads the unused bytes in dst's hash array. */
static inline void oidcpy_with_padding(struct object_id *dst,
const struct object_id *src)
@@ -318,13 +62,6 @@ static inline void oidcpy_with_padding(struct object_id *dst,
dst->algo = src->algo;
}
-static inline struct object_id *oiddup(const struct object_id *src)
-{
- struct object_id *dst = xmalloc(sizeof(struct object_id));
- oidcpy(dst, src);
- return dst;
-}
-
static inline void hashclr(unsigned char *hash)
{
memset(hash, 0, the_hash_algo->rawsz);
@@ -362,12 +99,4 @@ static inline int is_empty_tree_oid(const struct object_id *oid)
return oideq(oid, the_hash_algo->empty_tree);
}
-static inline void oid_set_algo(struct object_id *oid, const struct git_hash_algo *algop)
-{
- oid->algo = hash_algo_by_ptr(algop);
-}
-
-const char *empty_tree_oid_hex(void);
-const char *empty_blob_oid_hex(void);
-
#endif
diff --git a/hashmap.h b/hashmap.h
index e2cf9c78d8..2695f3d3a6 100644
--- a/hashmap.h
+++ b/hashmap.h
@@ -1,7 +1,7 @@
#ifndef HASHMAP_H
#define HASHMAP_H
-#include "hash.h"
+#include "hash-ll.h"
/*
* Generic implementation of hash-based key-value mappings.
diff --git a/hex.c b/hex.c
index 0a1bddc128..7bb440e794 100644
--- a/hex.c
+++ b/hex.c
@@ -1,4 +1,5 @@
#include "git-compat-util.h"
+#include "hash.h"
#include "hex.h"
const signed char hexval_table[256] = {
diff --git a/hex.h b/hex.h
index e2abfc56fa..7df4b3c460 100644
--- a/hex.h
+++ b/hex.h
@@ -1,7 +1,7 @@
#ifndef HEX_H
#define HEX_H
-#include "hash.h"
+#include "hash-ll.h"
extern const signed char hexval_table[256];
static inline unsigned int hexval(unsigned char c)
diff --git a/hook.c b/hook.c
index 76e322f580..3ca5e60895 100644
--- a/hook.c
+++ b/hook.c
@@ -2,6 +2,7 @@
#include "advice.h"
#include "gettext.h"
#include "hook.h"
+#include "path.h"
#include "run-command.h"
#include "config.h"
#include "strbuf.h"
diff --git a/http-push.c b/http-push.c
index 76ab5dbb09..29cf9db34e 100644
--- a/http-push.c
+++ b/http-push.c
@@ -15,6 +15,8 @@
#include "setup.h"
#include "sigchain.h"
#include "strvec.h"
+#include "tree.h"
+#include "tree-walk.h"
#include "packfile.h"
#include "object-store.h"
#include "commit-reach.h"
diff --git a/khash.h b/khash.h
index 85362718c5..56241e6a5c 100644
--- a/khash.h
+++ b/khash.h
@@ -27,6 +27,7 @@
#define __AC_KHASH_H
#include "hashmap.h"
+#include "hash.h"
#define AC_VERSION_KHASH_H "0.2.8"
diff --git a/line-log.c b/line-log.c
index 10c19daec4..6a7ac312a4 100644
--- a/line-log.c
+++ b/line-log.c
@@ -18,6 +18,7 @@
#include "setup.h"
#include "strvec.h"
#include "bloom.h"
+#include "tree-walk.h"
static void range_set_grow(struct range_set *rs, size_t extra)
{
diff --git a/ll-merge.c b/ll-merge.c
index 28bc94c45d..1993530688 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -4,7 +4,7 @@
* Copyright (c) 2007 Junio C Hamano
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "convert.h"
#include "attr.h"
@@ -12,6 +12,7 @@
#include "run-command.h"
#include "ll-merge.h"
#include "quote.h"
+#include "strbuf.h"
#include "wrapper.h"
struct ll_merge_driver;
diff --git a/log-tree.c b/log-tree.c
index 143b86fecf..f4b22a60cc 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -24,6 +24,7 @@
#include "help.h"
#include "range-diff.h"
#include "strmap.h"
+#include "tree.h"
#include "write-or-die.h"
static struct decoration name_decoration = { "object names" };
diff --git a/ls-refs.c b/ls-refs.c
index b9f3e08ec3..f385938b64 100644
--- a/ls-refs.c
+++ b/ls-refs.c
@@ -1,6 +1,7 @@
#include "git-compat-util.h"
#include "environment.h"
#include "gettext.h"
+#include "hash.h"
#include "hex.h"
#include "repository.h"
#include "refs.h"
diff --git a/match-trees.c b/match-trees.c
index 5877fc64a8..6bc8eb7647 100644
--- a/match-trees.c
+++ b/match-trees.c
@@ -1,5 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "hex.h"
+#include "match-trees.h"
#include "tree.h"
#include "tree-walk.h"
#include "object-store.h"
diff --git a/match-trees.h b/match-trees.h
new file mode 100644
index 0000000000..e3877acd58
--- /dev/null
+++ b/match-trees.h
@@ -0,0 +1,10 @@
+#ifndef MATCH_TREES_H
+#define MATCH_TREES_H
+
+struct object_id;
+struct repository;
+
+void shift_tree(struct repository *, const struct object_id *, const struct object_id *, struct object_id *, int);
+void shift_tree_by(struct repository *, const struct object_id *, const struct object_id *, struct object_id *, const char *);
+
+#endif /* MATCH_TREES_H */
diff --git a/merge-ort-wrappers.c b/merge-ort-wrappers.c
index c00dfbab1c..a550753300 100644
--- a/merge-ort-wrappers.c
+++ b/merge-ort-wrappers.c
@@ -1,7 +1,9 @@
#include "cache.h"
#include "gettext.h"
+#include "hash.h"
#include "merge-ort.h"
#include "merge-ort-wrappers.h"
+#include "tree.h"
#include "commit.h"
diff --git a/merge-ort.c b/merge-ort.c
index 34ec2675a2..a50b095c47 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -31,6 +31,7 @@
#include "hex.h"
#include "entry.h"
#include "ll-merge.h"
+#include "match-trees.h"
#include "mem-pool.h"
#include "object-name.h"
#include "object-store.h"
diff --git a/merge-ort.h b/merge-ort.h
index a994c9a5fc..ce56ec1a78 100644
--- a/merge-ort.h
+++ b/merge-ort.h
@@ -2,7 +2,7 @@
#define MERGE_ORT_H
#include "merge-recursive.h"
-#include "hash.h"
+#include "hash-ll.h"
struct commit;
struct tree;
diff --git a/merge-recursive.c b/merge-recursive.c
index 9875bdb11c..8e87b6386d 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -22,6 +22,7 @@
#include "hex.h"
#include "ll-merge.h"
#include "lockfile.h"
+#include "match-trees.h"
#include "object-file.h"
#include "object-name.h"
#include "object-store.h"
@@ -30,6 +31,7 @@
#include "string-list.h"
#include "submodule-config.h"
#include "submodule.h"
+#include "symlinks.h"
#include "tag.h"
#include "tree-walk.h"
#include "unpack-trees.h"
diff --git a/merge.c b/merge.c
index da7fa652c2..10aaec3a6c 100644
--- a/merge.c
+++ b/merge.c
@@ -7,6 +7,7 @@
#include "commit.h"
#include "run-command.h"
#include "resolve-undo.h"
+#include "tree.h"
#include "tree-walk.h"
#include "unpack-trees.h"
#include "dir.h"
diff --git a/midx.c b/midx.c
index 281a1406a8..b500174d1f 100644
--- a/midx.c
+++ b/midx.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "alloc.h"
#include "config.h"
diff --git a/negotiator/default.c b/negotiator/default.c
index f4b78eb47d..9a5b696327 100644
--- a/negotiator/default.c
+++ b/negotiator/default.c
@@ -4,6 +4,7 @@
#include "../fetch-negotiator.h"
#include "../prio-queue.h"
#include "../refs.h"
+#include "../repository.h"
#include "../tag.h"
/* Remember to update object flag allocation in object.h */
@@ -55,30 +56,49 @@ static int clear_marks(const char *refname, const struct object_id *oid,
static void mark_common(struct negotiation_state *ns, struct commit *commit,
int ancestors_only, int dont_parse)
{
- if (commit != NULL && !(commit->object.flags & COMMON)) {
- struct object *o = (struct object *)commit;
+ struct prio_queue queue = { NULL };
+
+ if (!commit || (commit->object.flags & COMMON))
+ return;
+
+ prio_queue_put(&queue, commit);
+ if (!ancestors_only) {
+ commit->object.flags |= COMMON;
- if (!ancestors_only)
- o->flags |= COMMON;
+ if ((commit->object.flags & SEEN) && !(commit->object.flags & POPPED))
+ ns->non_common_revs--;
+ }
+ while ((commit = prio_queue_get(&queue))) {
+ struct object *o = (struct object *)commit;
if (!(o->flags & SEEN))
rev_list_push(ns, commit, SEEN);
else {
struct commit_list *parents;
- if (!ancestors_only && !(o->flags & POPPED))
- ns->non_common_revs--;
if (!o->parsed && !dont_parse)
if (repo_parse_commit(the_repository, commit))
- return;
+ continue;
for (parents = commit->parents;
parents;
- parents = parents->next)
- mark_common(ns, parents->item, 0,
- dont_parse);
+ parents = parents->next) {
+ struct commit *p = parents->item;
+
+ if (p->object.flags & COMMON)
+ continue;
+
+ p->object.flags |= COMMON;
+
+ if ((p->object.flags & SEEN) && !(p->object.flags & POPPED))
+ ns->non_common_revs--;
+
+ prio_queue_put(&queue, parents->item);
+ }
}
}
+
+ clear_prio_queue(&queue);
}
/*
diff --git a/negotiator/skipping.c b/negotiator/skipping.c
index c7d6ab39bc..5b91520430 100644
--- a/negotiator/skipping.c
+++ b/negotiator/skipping.c
@@ -5,6 +5,7 @@
#include "../hex.h"
#include "../prio-queue.h"
#include "../refs.h"
+#include "../repository.h"
#include "../tag.h"
/* Remember to update object flag allocation in object.h */
@@ -85,29 +86,37 @@ static int clear_marks(const char *refname, const struct object_id *oid,
}
/*
- * Mark this SEEN commit and all its SEEN ancestors as COMMON.
+ * Mark this SEEN commit and all its parsed SEEN ancestors as COMMON.
*/
static void mark_common(struct data *data, struct commit *seen_commit)
{
struct prio_queue queue = { NULL };
struct commit *c;
+ if (seen_commit->object.flags & COMMON)
+ return;
+
prio_queue_put(&queue, seen_commit);
+ seen_commit->object.flags |= COMMON;
while ((c = prio_queue_get(&queue))) {
struct commit_list *p;
- if (c->object.flags & COMMON)
- return;
- c->object.flags |= COMMON;
+
if (!(c->object.flags & POPPED))
data->non_common_revs--;
if (!c->object.parsed)
- return;
+ continue;
for (p = c->parents; p; p = p->next) {
- if (p->item->object.flags & SEEN)
- prio_queue_put(&queue, p->item);
+ if (!(p->item->object.flags & SEEN) ||
+ (p->item->object.flags & COMMON))
+ continue;
+
+ p->item->object.flags |= COMMON;
+ prio_queue_put(&queue, p->item);
}
}
+
+ clear_prio_queue(&queue);
}
/*
diff --git a/notes-cache.c b/notes-cache.c
index fbcdfd0dfe..14288caf98 100644
--- a/notes-cache.c
+++ b/notes-cache.c
@@ -1,6 +1,7 @@
#include "git-compat-util.h"
#include "notes-cache.h"
#include "object-store.h"
+#include "pretty.h"
#include "repository.h"
#include "commit.h"
#include "refs.h"
diff --git a/notes-utils.c b/notes-utils.c
index cb88171b7b..4a793eb347 100644
--- a/notes-utils.c
+++ b/notes-utils.c
@@ -6,6 +6,7 @@
#include "refs.h"
#include "notes-utils.h"
#include "repository.h"
+#include "strbuf.h"
void create_notes_commit(struct repository *r,
struct notes_tree *t,
diff --git a/object-file.c b/object-file.c
index af18e38527..7c1af5c8db 100644
--- a/object-file.c
+++ b/object-file.c
@@ -6,7 +6,7 @@
* This handles basic git object files - packing, unpacking,
* creation etc.
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "alloc.h"
#include "config.h"
@@ -38,6 +38,7 @@
#include "packfile.h"
#include "object-file.h"
#include "object-store.h"
+#include "oidtree.h"
#include "promisor-remote.h"
#include "setup.h"
#include "submodule.h"
diff --git a/object-file.h b/object-file.h
index e0cfc3a5db..d6414610f8 100644
--- a/object-file.h
+++ b/object-file.h
@@ -4,6 +4,8 @@
#include "git-zlib.h"
#include "object.h"
+struct index_state;
+
/*
* Set this to 0 to prevent oid_object_info_extended() from fetching missing
* blobs. This has a difference only if extensions.partialClone is set.
diff --git a/object-name.c b/object-name.c
index 538e8a8f62..6fc3fa595b 100644
--- a/object-name.c
+++ b/object-name.c
@@ -14,7 +14,9 @@
#include "remote.h"
#include "dir.h"
#include "oid-array.h"
+#include "oidtree.h"
#include "packfile.h"
+#include "pretty.h"
#include "object-store.h"
#include "repository.h"
#include "setup.h"
diff --git a/object-store.h b/object-store.h
index 4ac91e375d..12415e5ea7 100644
--- a/object-store.h
+++ b/object-store.h
@@ -2,16 +2,16 @@
#define OBJECT_STORE_H
#include "object.h"
-#include "oidmap.h"
#include "list.h"
-#include "oid-array.h"
-#include "strbuf.h"
#include "thread-utils.h"
#include "khash.h"
#include "dir.h"
-#include "oidtree.h"
#include "oidset.h"
+struct oidmap;
+struct oidtree;
+struct strbuf;
+
struct object_directory {
struct object_directory *next;
diff --git a/object.h b/object.h
index 96e52e24fb..5871615fee 100644
--- a/object.h
+++ b/object.h
@@ -1,9 +1,10 @@
#ifndef OBJECT_H
#define OBJECT_H
-#include "hash.h"
+#include "hash-ll.h"
struct buffer_slab;
+struct repository;
struct parsed_object_pool {
struct object **obj_hash;
diff --git a/oidmap.c b/oidmap.c
index 8c1a139c97..8b1bc4dec9 100644
--- a/oidmap.c
+++ b/oidmap.c
@@ -1,4 +1,5 @@
#include "git-compat-util.h"
+#include "hash.h"
#include "oidmap.h"
static int oidmap_neq(const void *hashmap_cmp_fn_data UNUSED,
diff --git a/oidtree.h b/oidtree.h
index 77898f510a..55c83513fd 100644
--- a/oidtree.h
+++ b/oidtree.h
@@ -2,7 +2,7 @@
#define OIDTREE_H
#include "cbtree.h"
-#include "hash.h"
+#include "hash-ll.h"
#include "mem-pool.h"
struct oidtree {
diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c
index faf67c94d3..cdffe2ce47 100644
--- a/pack-bitmap-write.c
+++ b/pack-bitmap-write.c
@@ -18,6 +18,8 @@
#include "commit-reach.h"
#include "prio-queue.h"
#include "trace2.h"
+#include "tree.h"
+#include "tree-walk.h"
struct bitmapped_commit {
struct commit *commit;
diff --git a/pack-bitmap.c b/pack-bitmap.c
index e0fad723bf..999f962602 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -2346,3 +2346,48 @@ int bitmap_is_preferred_refname(struct repository *r, const char *refname)
return 0;
}
+
+static int verify_bitmap_file(const char *name)
+{
+ struct stat st;
+ unsigned char *data;
+ int fd = git_open(name);
+ int res = 0;
+
+ /* It is OK to not have the file. */
+ if (fd < 0 || fstat(fd, &st)) {
+ if (fd >= 0)
+ close(fd);
+ return 0;
+ }
+
+ data = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ close(fd);
+ if (!hashfile_checksum_valid(data, st.st_size))
+ res = error(_("bitmap file '%s' has invalid checksum"),
+ name);
+
+ munmap(data, st.st_size);
+ return res;
+}
+
+int verify_bitmap_files(struct repository *r)
+{
+ int res = 0;
+
+ for (struct multi_pack_index *m = get_multi_pack_index(r);
+ m; m = m->next) {
+ char *midx_bitmap_name = midx_bitmap_filename(m);
+ res |= verify_bitmap_file(midx_bitmap_name);
+ free(midx_bitmap_name);
+ }
+
+ for (struct packed_git *p = get_all_packs(r);
+ p; p = p->next) {
+ char *pack_bitmap_name = pack_bitmap_filename(p);
+ res |= verify_bitmap_file(pack_bitmap_name);
+ free(pack_bitmap_name);
+ }
+
+ return res;
+}
diff --git a/pack-bitmap.h b/pack-bitmap.h
index f0180b5276..84591f041b 100644
--- a/pack-bitmap.h
+++ b/pack-bitmap.h
@@ -111,4 +111,6 @@ int bitmap_is_midx(struct bitmap_index *bitmap_git);
const struct string_list *bitmap_preferred_tips(struct repository *r);
int bitmap_is_preferred_refname(struct repository *r, const char *refname);
+int verify_bitmap_files(struct repository *r);
+
#endif
diff --git a/packfile.c b/packfile.c
index 57df0c1956..fd083c86e0 100644
--- a/packfile.c
+++ b/packfile.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "environment.h"
#include "gettext.h"
diff --git a/packfile.h b/packfile.h
index 665603b696..c3692308b8 100644
--- a/packfile.h
+++ b/packfile.h
@@ -6,10 +6,22 @@
/* in object-store.h */
struct packed_git;
-struct pack_entry;
-struct pack_window;
struct object_info;
+struct pack_window {
+ struct pack_window *next;
+ unsigned char *base;
+ off_t offset;
+ size_t len;
+ unsigned int last_used;
+ unsigned int inuse_cnt;
+};
+
+struct pack_entry {
+ off_t offset;
+ struct packed_git *p;
+};
+
/*
* Generate the filename to be used for a pack file with checksum "sha1" and
* extension "ext". The result is written into the strbuf "buf", overwriting
diff --git a/parallel-checkout.c b/parallel-checkout.c
index 50fd7fe31e..69d569f352 100644
--- a/parallel-checkout.c
+++ b/parallel-checkout.c
@@ -3,6 +3,7 @@
#include "config.h"
#include "entry.h"
#include "gettext.h"
+#include "hash.h"
#include "hex.h"
#include "parallel-checkout.h"
#include "pkt-line.h"
@@ -10,6 +11,7 @@
#include "run-command.h"
#include "sigchain.h"
#include "streaming.h"
+#include "symlinks.h"
#include "thread-utils.h"
#include "trace2.h"
#include "wrapper.h"
diff --git a/parse-options-cb.c b/parse-options-cb.c
index 298decf48f..a24521dee0 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -3,6 +3,7 @@
#include "branch.h"
#include "commit.h"
#include "color.h"
+#include "date.h"
#include "environment.h"
#include "gettext.h"
#include "object-name.h"
diff --git a/parse-options.c b/parse-options.c
index b6803647d0..f8a155ee13 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -5,6 +5,7 @@
#include "commit.h"
#include "color.h"
#include "gettext.h"
+#include "strbuf.h"
#include "utf8.h"
static int disallow_abbreviated_options;
diff --git a/pathspec.c b/pathspec.c
index 6972d515f0..1e57b6c667 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -6,8 +6,10 @@
#include "gettext.h"
#include "pathspec.h"
#include "attr.h"
+#include "repository.h"
#include "setup.h"
#include "strvec.h"
+#include "symlinks.h"
#include "quote.h"
/*
diff --git a/pkt-line.c b/pkt-line.c
index 3561d85358..62b4208b66 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -1,4 +1,5 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "copy.h"
#include "pkt-line.h"
#include "gettext.h"
#include "hex.h"
diff --git a/pkt-line.h b/pkt-line.h
index 8e9846f315..7c23a4bfaf 100644
--- a/pkt-line.h
+++ b/pkt-line.h
@@ -246,4 +246,6 @@ void packet_writer_error(struct packet_writer *writer, const char *fmt, ...);
void packet_writer_delim(struct packet_writer *writer);
void packet_writer_flush(struct packet_writer *writer);
+void packet_trace_identity(const char *prog);
+
#endif
diff --git a/preload-index.c b/preload-index.c
index 4abf9c983b..7a26b08c21 100644
--- a/preload-index.c
+++ b/preload-index.c
@@ -11,6 +11,7 @@
#include "progress.h"
#include "thread-utils.h"
#include "repository.h"
+#include "symlinks.h"
#include "trace2.h"
/*
diff --git a/progress.c b/progress.c
index 72d5e0c73c..f695798aca 100644
--- a/progress.c
+++ b/progress.c
@@ -12,6 +12,7 @@
#include "git-compat-util.h"
#include "pager.h"
#include "progress.h"
+#include "repository.h"
#include "strbuf.h"
#include "trace.h"
#include "trace2.h"
diff --git a/protocol-caps.c b/protocol-caps.c
index 94c51862c5..a90c48852e 100644
--- a/protocol-caps.c
+++ b/protocol-caps.c
@@ -4,7 +4,7 @@
#include "hex.h"
#include "pkt-line.h"
#include "strvec.h"
-#include "hash.h"
+#include "hash-ll.h"
#include "hex.h"
#include "object.h"
#include "object-store.h"
diff --git a/range-diff.c b/range-diff.c
index a1e0cffb9f..6a704e6f47 100644
--- a/range-diff.c
+++ b/range-diff.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "environment.h"
#include "gettext.h"
#include "range-diff.h"
diff --git a/read-cache.c b/read-cache.c
index e919af3c77..f4c31a68c8 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -6,6 +6,7 @@
#include "cache.h"
#include "alloc.h"
#include "config.h"
+#include "date.h"
#include "diff.h"
#include "diffcore.h"
#include "hex.h"
@@ -30,6 +31,7 @@
#include "trace2.h"
#include "varint.h"
#include "split-index.h"
+#include "symlinks.h"
#include "utf8.h"
#include "fsmonitor.h"
#include "thread-utils.h"
@@ -498,87 +500,30 @@ int ie_modified(struct index_state *istate,
return 0;
}
-int base_name_compare(const char *name1, size_t len1, int mode1,
- const char *name2, size_t len2, int mode2)
+static int cache_name_stage_compare(const char *name1, int len1, int stage1,
+ const char *name2, int len2, int stage2)
{
- unsigned char c1, c2;
- size_t len = len1 < len2 ? len1 : len2;
int cmp;
- cmp = memcmp(name1, name2, len);
- if (cmp)
- return cmp;
- c1 = name1[len];
- c2 = name2[len];
- if (!c1 && S_ISDIR(mode1))
- c1 = '/';
- if (!c2 && S_ISDIR(mode2))
- c2 = '/';
- return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0;
-}
-
-/*
- * df_name_compare() is identical to base_name_compare(), except it
- * compares conflicting directory/file entries as equal. Note that
- * while a directory name compares as equal to a regular file, they
- * then individually compare _differently_ to a filename that has
- * a dot after the basename (because '\0' < '.' < '/').
- *
- * This is used by routines that want to traverse the git namespace
- * but then handle conflicting entries together when possible.
- */
-int df_name_compare(const char *name1, size_t len1, int mode1,
- const char *name2, size_t len2, int mode2)
-{
- unsigned char c1, c2;
- size_t len = len1 < len2 ? len1 : len2;
- int cmp;
-
- cmp = memcmp(name1, name2, len);
+ cmp = name_compare(name1, len1, name2, len2);
if (cmp)
return cmp;
- /* Directories and files compare equal (same length, same name) */
- if (len1 == len2)
- return 0;
- c1 = name1[len];
- if (!c1 && S_ISDIR(mode1))
- c1 = '/';
- c2 = name2[len];
- if (!c2 && S_ISDIR(mode2))
- c2 = '/';
- if (c1 == '/' && !c2)
- return 0;
- if (c2 == '/' && !c1)
- return 0;
- return c1 - c2;
-}
-int name_compare(const char *name1, size_t len1, const char *name2, size_t len2)
-{
- size_t min_len = (len1 < len2) ? len1 : len2;
- int cmp = memcmp(name1, name2, min_len);
- if (cmp)
- return cmp;
- if (len1 < len2)
+ if (stage1 < stage2)
return -1;
- if (len1 > len2)
+ if (stage1 > stage2)
return 1;
return 0;
}
-int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2)
+int cmp_cache_name_compare(const void *a_, const void *b_)
{
- int cmp;
+ const struct cache_entry *ce1, *ce2;
- cmp = name_compare(name1, len1, name2, len2);
- if (cmp)
- return cmp;
-
- if (stage1 < stage2)
- return -1;
- if (stage1 > stage2)
- return 1;
- return 0;
+ ce1 = *((const struct cache_entry **)a_);
+ ce2 = *((const struct cache_entry **)b_);
+ return cache_name_stage_compare(ce1->name, ce1->ce_namelen, ce_stage(ce1),
+ ce2->name, ce2->ce_namelen, ce_stage(ce2));
}
static int index_name_stage_pos(struct index_state *istate,
diff --git a/rebase-interactive.c b/rebase-interactive.c
index 789f407361..852a331318 100644
--- a/rebase-interactive.c
+++ b/rebase-interactive.c
@@ -5,6 +5,7 @@
#include "gettext.h"
#include "sequencer.h"
#include "rebase-interactive.h"
+#include "repository.h"
#include "strbuf.h"
#include "commit-slab.h"
#include "config.h"
diff --git a/ref-filter.c b/ref-filter.c
index 10aab14f03..4991cd4f7a 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1,7 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "environment.h"
#include "gettext.h"
+#include "gpg-interface.h"
#include "hex.h"
#include "parse-options.h"
#include "refs.h"
@@ -19,6 +20,7 @@
#include "revision.h"
#include "utf8.h"
#include "version.h"
+#include "versioncmp.h"
#include "trailer.h"
#include "wt-status.h"
#include "commit-slab.h"
diff --git a/reflog.c b/reflog.c
index 9c09443088..ee1bf5d032 100644
--- a/reflog.c
+++ b/reflog.c
@@ -4,6 +4,8 @@
#include "reflog.h"
#include "refs.h"
#include "revision.h"
+#include "tree.h"
+#include "tree-walk.h"
#include "worktree.h"
/* Remember to update object flag allocation in object.h */
diff --git a/refs/debug.c b/refs/debug.c
index adc34c836f..6f11e6de46 100644
--- a/refs/debug.c
+++ b/refs/debug.c
@@ -1,6 +1,7 @@
#include "git-compat-util.h"
#include "hex.h"
#include "refs-internal.h"
+#include "string-list.h"
#include "trace.h"
static struct trace_key trace_refs = TRACE_KEY_INIT(REFS);
diff --git a/refs/files-backend.c b/refs/files-backend.c
index d0581ee41a..bca7b851c5 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1,7 +1,9 @@
#include "../cache.h"
#include "../config.h"
+#include "../copy.h"
#include "../environment.h"
#include "../gettext.h"
+#include "../hash.h"
#include "../hex.h"
#include "../refs.h"
#include "refs-internal.h"
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index 34c0c4e20f..5b412a133b 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -2,6 +2,7 @@
#include "../alloc.h"
#include "../config.h"
#include "../gettext.h"
+#include "../hash.h"
#include "../hex.h"
#include "../refs.h"
#include "refs-internal.h"
diff --git a/refs/ref-cache.c b/refs/ref-cache.c
index dc1ca49c85..2294c4564f 100644
--- a/refs/ref-cache.c
+++ b/refs/ref-cache.c
@@ -1,6 +1,8 @@
#include "../git-compat-util.h"
#include "../alloc.h"
+#include "../hash.h"
#include "../refs.h"
+#include "../repository.h"
#include "refs-internal.h"
#include "ref-cache.h"
#include "../iterator.h"
diff --git a/refs/ref-cache.h b/refs/ref-cache.h
index cf4ad9070b..95c76e27c8 100644
--- a/refs/ref-cache.h
+++ b/refs/ref-cache.h
@@ -1,10 +1,11 @@
#ifndef REFS_REF_CACHE_H
#define REFS_REF_CACHE_H
-#include "hash.h"
+#include "hash-ll.h"
struct ref_dir;
struct ref_store;
+struct repository;
/*
* If this ref_cache is filled lazily, this function is used to load
diff --git a/refspec.c b/refspec.c
index 7b5c305514..57f6c2aaf9 100644
--- a/refspec.c
+++ b/refspec.c
@@ -1,10 +1,12 @@
#include "git-compat-util.h"
#include "alloc.h"
#include "gettext.h"
+#include "hash.h"
#include "hex.h"
#include "strvec.h"
#include "refs.h"
#include "refspec.h"
+#include "strbuf.h"
static struct refspec_item s_tag_refspec = {
.force = 0,
diff --git a/reftable/dump.c b/reftable/dump.c
index 155953d1b8..ce936b4e18 100644
--- a/reftable/dump.c
+++ b/reftable/dump.c
@@ -7,7 +7,7 @@ https://developers.google.com/open-source/licenses/bsd
*/
#include "git-compat-util.h"
-#include "hash.h"
+#include "hash-ll.h"
#include "reftable-blocksource.h"
#include "reftable-error.h"
diff --git a/reftable/error.c b/reftable/error.c
index 93941f2145..0d1766735e 100644
--- a/reftable/error.c
+++ b/reftable/error.c
@@ -6,6 +6,7 @@ license that can be found in the LICENSE file or at
https://developers.google.com/open-source/licenses/bsd
*/
+#include "system.h"
#include "reftable-error.h"
#include <stdio.h>
diff --git a/reftable/publicbasics.c b/reftable/publicbasics.c
index 0ad7d5c0ff..bcb82530d6 100644
--- a/reftable/publicbasics.c
+++ b/reftable/publicbasics.c
@@ -6,10 +6,10 @@ license that can be found in the LICENSE file or at
https://developers.google.com/open-source/licenses/bsd
*/
+#include "system.h"
#include "reftable-malloc.h"
#include "basics.h"
-#include "system.h"
static void *(*reftable_malloc_ptr)(size_t sz);
static void *(*reftable_realloc_ptr)(void *, size_t);
diff --git a/reftable/system.h b/reftable/system.h
index 18f9207dfe..6b74a81514 100644
--- a/reftable/system.h
+++ b/reftable/system.h
@@ -13,7 +13,7 @@ https://developers.google.com/open-source/licenses/bsd
#include "git-compat-util.h"
#include "strbuf.h"
-#include "hash.h" /* hash ID, sizes.*/
+#include "hash-ll.h" /* hash ID, sizes.*/
#include "dir.h" /* remove_dir_recursively, for tests.*/
int hash_size(uint32_t id);
diff --git a/reftable/tree.c b/reftable/tree.c
index b8899e060a..a5bf880985 100644
--- a/reftable/tree.c
+++ b/reftable/tree.c
@@ -6,10 +6,10 @@ license that can be found in the LICENSE file or at
https://developers.google.com/open-source/licenses/bsd
*/
+#include "system.h"
#include "tree.h"
#include "basics.h"
-#include "system.h"
struct tree_node *tree_search(void *key, struct tree_node **rootp,
int (*compare)(const void *, const void *),
diff --git a/reftable/tree_test.c b/reftable/tree_test.c
index cbff125588..ac3a045ad4 100644
--- a/reftable/tree_test.c
+++ b/reftable/tree_test.c
@@ -6,6 +6,7 @@ license that can be found in the LICENSE file or at
https://developers.google.com/open-source/licenses/bsd
*/
+#include "system.h"
#include "tree.h"
#include "basics.h"
diff --git a/rerere.c b/rerere.c
index 7abc94bf44..e968d413d6 100644
--- a/rerere.c
+++ b/rerere.c
@@ -2,6 +2,7 @@
#include "abspath.h"
#include "alloc.h"
#include "config.h"
+#include "copy.h"
#include "gettext.h"
#include "hex.h"
#include "lockfile.h"
diff --git a/reset.h b/reset.h
index a28f81829d..10708d8ddc 100644
--- a/reset.h
+++ b/reset.h
@@ -1,7 +1,7 @@
#ifndef RESET_H
#define RESET_H
-#include "hash.h"
+#include "hash-ll.h"
#include "repository.h"
#define GIT_REFLOG_ACTION_ENVIRONMENT "GIT_REFLOG_ACTION"
diff --git a/resolve-undo.c b/resolve-undo.c
index e81096e2d4..70a6db526d 100644
--- a/resolve-undo.c
+++ b/resolve-undo.c
@@ -1,5 +1,6 @@
#include "cache.h"
#include "dir.h"
+#include "hash.h"
#include "resolve-undo.h"
#include "string-list.h"
diff --git a/resolve-undo.h b/resolve-undo.h
index d1ea972771..c5deafc92f 100644
--- a/resolve-undo.h
+++ b/resolve-undo.h
@@ -6,7 +6,7 @@ struct index_state;
struct pathspec;
struct string_list;
-#include "hash.h"
+#include "hash-ll.h"
struct resolve_undo_info {
unsigned int mode[3];
diff --git a/revision.h b/revision.h
index e8f6de9684..31828748dc 100644
--- a/revision.h
+++ b/revision.h
@@ -7,6 +7,7 @@
#include "pretty.h"
#include "diff.h"
#include "commit-slab-decl.h"
+#include "decorate.h"
#include "ident.h"
#include "list-objects-filter-options.h"
diff --git a/run-command.c b/run-command.c
index e64bb08a5b..d4247d5fcc 100644
--- a/run-command.c
+++ b/run-command.c
@@ -5,6 +5,7 @@
#include "gettext.h"
#include "sigchain.h"
#include "strvec.h"
+#include "symlinks.h"
#include "thread-utils.h"
#include "strbuf.h"
#include "string-list.h"
diff --git a/send-pack.c b/send-pack.c
index 2089143555..0c7ccaef68 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -1,6 +1,7 @@
#include "git-compat-util.h"
#include "config.h"
#include "commit.h"
+#include "date.h"
#include "gettext.h"
#include "hex.h"
#include "refs.h"
diff --git a/sequencer.c b/sequencer.c
index c88d1d9553..b553b49fbb 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -3,6 +3,7 @@
#include "advice.h"
#include "alloc.h"
#include "config.h"
+#include "copy.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
@@ -3625,14 +3626,14 @@ static int do_exec(struct repository *r, const char *command_line)
" git rebase --continue\n"
"\n"),
command_line,
- dirty ? N_("and made changes to the index and/or the "
- "working tree\n") : "");
+ dirty ? _("and made changes to the index and/or the "
+ "working tree.\n") : "");
if (status == 127)
/* command not found */
status = 1;
} else if (dirty) {
warning(_("execution succeeded: %s\nbut "
- "left changes to the index and/or the working tree\n"
+ "left changes to the index and/or the working tree.\n"
"Commit or stash your changes, and then run\n"
"\n"
" git rebase --continue\n"
diff --git a/server-info.c b/server-info.c
index 68098ddd1a..55aa04f00a 100644
--- a/server-info.c
+++ b/server-info.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "dir.h"
#include "environment.h"
@@ -11,6 +11,7 @@
#include "packfile.h"
#include "object-file.h"
#include "object-store.h"
+#include "server-info.h"
#include "strbuf.h"
#include "wrapper.h"
diff --git a/server-info.h b/server-info.h
new file mode 100644
index 0000000000..13bbde2c55
--- /dev/null
+++ b/server-info.h
@@ -0,0 +1,7 @@
+#ifndef SERVER_INFO_H
+#define SERVER_INFO_H
+
+/* Dumb servers support */
+int update_server_info(int);
+
+#endif /* SERVER_INFO_H */
diff --git a/setup.c b/setup.c
index 59abc16ba6..458582207e 100644
--- a/setup.c
+++ b/setup.c
@@ -1352,6 +1352,7 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
}
if (is_git_directory(dir->buf)) {
+ trace2_data_string("setup", NULL, "implicit-bare-repository", dir->buf);
if (get_allowed_bare_repo() == ALLOWED_BARE_REPO_EXPLICIT)
return GIT_DIR_DISALLOWED_BARE;
if (!ensure_valid_ownership(NULL, NULL, dir->buf, report))
diff --git a/split-index.c b/split-index.c
index 5602b74994..40e54760b3 100644
--- a/split-index.c
+++ b/split-index.c
@@ -1,8 +1,10 @@
#include "cache.h"
#include "alloc.h"
#include "gettext.h"
+#include "hash.h"
#include "mem-pool.h"
#include "split-index.h"
+#include "strbuf.h"
#include "ewah/ewok.h"
struct split_index *init_split_index(struct index_state *istate)
diff --git a/split-index.h b/split-index.h
index 1a153f47ba..15a29cd08c 100644
--- a/split-index.h
+++ b/split-index.h
@@ -1,7 +1,7 @@
#ifndef SPLIT_INDEX_H
#define SPLIT_INDEX_H
-#include "hash.h"
+#include "hash-ll.h"
struct index_state;
struct strbuf;
diff --git a/strbuf.c b/strbuf.c
index 729378ec82..08eec8f1d8 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -6,6 +6,7 @@
#include "hex.h"
#include "object-name.h"
#include "refs.h"
+#include "repository.h"
#include "string-list.h"
#include "utf8.h"
#include "date.h"
diff --git a/submodule-config.c b/submodule-config.c
index 7fc0812b64..58dfbde9ae 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -12,6 +12,7 @@
#include "object-name.h"
#include "object-store.h"
#include "parse-options.h"
+#include "thread-utils.h"
#include "tree-walk.h"
/*
diff --git a/symlinks.c b/symlinks.c
index 27ecc93693..b29e340c2d 100644
--- a/symlinks.c
+++ b/symlinks.c
@@ -1,6 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "gettext.h"
#include "setup.h"
+#include "symlinks.h"
static int threaded_check_leading_path(struct cache_def *cache, const char *name,
int len, int warn_on_lstat_err);
diff --git a/symlinks.h b/symlinks.h
new file mode 100644
index 0000000000..7ae3d5b856
--- /dev/null
+++ b/symlinks.h
@@ -0,0 +1,28 @@
+#ifndef SYMLINKS_H
+#define SYMLINKS_H
+
+#include "strbuf.h"
+
+struct cache_def {
+ struct strbuf path;
+ int flags;
+ int track_flags;
+ int prefix_len_stat_func;
+};
+#define CACHE_DEF_INIT { \
+ .path = STRBUF_INIT, \
+}
+static inline void cache_def_clear(struct cache_def *cache)
+{
+ strbuf_release(&cache->path);
+}
+
+int has_symlink_leading_path(const char *name, int len);
+int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
+int check_leading_path(const char *name, int len, int warn_on_lstat_err);
+int has_dirs_only_path(const char *name, int len, int prefix_len);
+void invalidate_lstat_cache(void);
+void schedule_dir_for_removal(const char *name, int len);
+void remove_scheduled_dirs(void);
+
+#endif /* SYMLINKS_H */
diff --git a/t/helper/test-bloom.c b/t/helper/test-bloom.c
index d2b30d644d..aabe31d724 100644
--- a/t/helper/test-bloom.c
+++ b/t/helper/test-bloom.c
@@ -2,6 +2,7 @@
#include "bloom.h"
#include "hex.h"
#include "commit.h"
+#include "repository.h"
#include "setup.h"
static struct bloom_filter_settings settings = DEFAULT_BLOOM_FILTER_SETTINGS;
diff --git a/t/helper/test-cache-tree.c b/t/helper/test-cache-tree.c
index cdaf5046f5..9507b356e2 100644
--- a/t/helper/test-cache-tree.c
+++ b/t/helper/test-cache-tree.c
@@ -6,6 +6,7 @@
#include "tree.h"
#include "cache-tree.h"
#include "parse-options.h"
+#include "repository.h"
#include "setup.h"
static char const * const test_cache_tree_usage[] = {
diff --git a/t/helper/test-ctype.c b/t/helper/test-ctype.c
index 71a1a5c9b0..e5659df40b 100644
--- a/t/helper/test-ctype.c
+++ b/t/helper/test-ctype.c
@@ -27,6 +27,8 @@ static int is_in(const char *s, int ch)
if (is_in(s, i) != t(i)) \
report_error(#t, i); \
} \
+ if (t(EOF)) \
+ report_error(#t, EOF); \
}
#define DIGIT "0123456789"
diff --git a/t/helper/test-dump-cache-tree.c b/t/helper/test-dump-cache-tree.c
index 2041ca1857..f22f7bd84a 100644
--- a/t/helper/test-dump-cache-tree.c
+++ b/t/helper/test-dump-cache-tree.c
@@ -1,9 +1,11 @@
#define USE_THE_INDEX_VARIABLE
#include "test-tool.h"
#include "cache.h"
+#include "hash.h"
#include "hex.h"
#include "tree.h"
#include "cache-tree.h"
+#include "repository.h"
#include "setup.h"
static void dump_one(struct cache_tree *it, const char *pfx, const char *x)
diff --git a/t/helper/test-dump-fsmonitor.c b/t/helper/test-dump-fsmonitor.c
index 7c6f50158b..9a098a25cb 100644
--- a/t/helper/test-dump-fsmonitor.c
+++ b/t/helper/test-dump-fsmonitor.c
@@ -1,5 +1,6 @@
#include "test-tool.h"
#include "cache.h"
+#include "repository.h"
#include "setup.h"
int cmd__dump_fsmonitor(int ac UNUSED, const char **av UNUSED)
diff --git a/t/helper/test-dump-untracked-cache.c b/t/helper/test-dump-untracked-cache.c
index 9225ced534..df70be549f 100644
--- a/t/helper/test-dump-untracked-cache.c
+++ b/t/helper/test-dump-untracked-cache.c
@@ -3,6 +3,7 @@
#include "cache.h"
#include "dir.h"
#include "hex.h"
+#include "repository.h"
#include "setup.h"
static int compare_untracked(const void *a_, const void *b_)
diff --git a/t/helper/test-example-decorate.c b/t/helper/test-example-decorate.c
index 2cf302ffcb..2ed910adaa 100644
--- a/t/helper/test-example-decorate.c
+++ b/t/helper/test-example-decorate.c
@@ -2,6 +2,7 @@
#include "git-compat-util.h"
#include "object.h"
#include "decorate.h"
+#include "repository.h"
int cmd__example_decorate(int argc UNUSED, const char **argv UNUSED)
{
diff --git a/t/helper/test-fsmonitor-client.c b/t/helper/test-fsmonitor-client.c
index 14522b4c47..9f18c685b7 100644
--- a/t/helper/test-fsmonitor-client.c
+++ b/t/helper/test-fsmonitor-client.c
@@ -7,6 +7,7 @@
#include "cache.h"
#include "parse-options.h"
#include "fsmonitor-ipc.h"
+#include "repository.h"
#include "setup.h"
#include "thread-utils.h"
#include "trace2.h"
diff --git a/t/helper/test-lazy-init-name-hash.c b/t/helper/test-lazy-init-name-hash.c
index f23d983c11..b83a75d19f 100644
--- a/t/helper/test-lazy-init-name-hash.c
+++ b/t/helper/test-lazy-init-name-hash.c
@@ -3,6 +3,7 @@
#include "cache.h"
#include "environment.h"
#include "parse-options.h"
+#include "repository.h"
#include "setup.h"
#include "trace.h"
diff --git a/t/helper/test-match-trees.c b/t/helper/test-match-trees.c
index 35a2b8005c..d0db5ff26f 100644
--- a/t/helper/test-match-trees.c
+++ b/t/helper/test-match-trees.c
@@ -1,7 +1,8 @@
#include "test-tool.h"
-#include "cache.h"
#include "hex.h"
+#include "match-trees.h"
#include "object-name.h"
+#include "repository.h"
#include "setup.h"
#include "tree.h"
diff --git a/t/helper/test-mergesort.c b/t/helper/test-mergesort.c
index 737e0c5235..42ccc87051 100644
--- a/t/helper/test-mergesort.c
+++ b/t/helper/test-mergesort.c
@@ -1,7 +1,7 @@
#include "test-tool.h"
-#include "cache.h"
#include "mem-pool.h"
#include "mergesort.h"
+#include "strbuf.h"
static uint32_t minstd_rand(uint32_t *state)
{
diff --git a/t/helper/test-oid-array.c b/t/helper/test-oid-array.c
index 30e1947b90..eef68833b7 100644
--- a/t/helper/test-oid-array.c
+++ b/t/helper/test-oid-array.c
@@ -1,8 +1,8 @@
#include "test-tool.h"
-#include "cache.h"
#include "hex.h"
#include "oid-array.h"
#include "setup.h"
+#include "strbuf.h"
static int print_oid(const struct object_id *oid, void *data)
{
diff --git a/t/helper/test-oidmap.c b/t/helper/test-oidmap.c
index d9931544a8..bd30244a54 100644
--- a/t/helper/test-oidmap.c
+++ b/t/helper/test-oidmap.c
@@ -2,6 +2,7 @@
#include "hex.h"
#include "object-name.h"
#include "oidmap.h"
+#include "repository.h"
#include "setup.h"
#include "strbuf.h"
#include "string-list.h"
diff --git a/t/helper/test-oidtree.c b/t/helper/test-oidtree.c
index 5b98f2f70a..c7a1d4c642 100644
--- a/t/helper/test-oidtree.c
+++ b/t/helper/test-oidtree.c
@@ -1,8 +1,8 @@
#include "test-tool.h"
-#include "cache.h"
#include "hex.h"
#include "oidtree.h"
#include "setup.h"
+#include "strbuf.h"
static enum cb_next print_oid(const struct object_id *oid, void *data UNUSED)
{
diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
index b66039e575..00fa281a9c 100644
--- a/t/helper/test-parse-options.c
+++ b/t/helper/test-parse-options.c
@@ -1,6 +1,6 @@
#include "test-tool.h"
-#include "cache.h"
#include "parse-options.h"
+#include "strbuf.h"
#include "string-list.h"
#include "trace2.h"
diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c
index 6355c9e4b6..2ef53d5f7a 100644
--- a/t/helper/test-path-utils.c
+++ b/t/helper/test-path-utils.c
@@ -2,6 +2,7 @@
#include "cache.h"
#include "abspath.h"
#include "environment.h"
+#include "path.h"
#include "setup.h"
#include "string-list.h"
#include "trace.h"
diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c
index a4c24d0e42..c1ae276395 100644
--- a/t/helper/test-read-cache.c
+++ b/t/helper/test-read-cache.c
@@ -2,6 +2,7 @@
#include "test-tool.h"
#include "cache.h"
#include "config.h"
+#include "repository.h"
#include "setup.h"
#include "wrapper.h"
diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c
index 05c4f2b262..211addaa00 100644
--- a/t/helper/test-read-midx.c
+++ b/t/helper/test-read-midx.c
@@ -1,10 +1,10 @@
#include "test-tool.h"
-#include "cache.h"
#include "hex.h"
#include "midx.h"
#include "repository.h"
#include "object-store.h"
#include "pack-bitmap.h"
+#include "packfile.h"
#include "setup.h"
static int read_midx_file(const char *object_dir, int show_objects)
diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c
index 1f0a28cbb6..00237ef0d9 100644
--- a/t/helper/test-reftable.c
+++ b/t/helper/test-reftable.c
@@ -1,3 +1,4 @@
+#include "reftable/system.h"
#include "reftable/reftable-tests.h"
#include "test-tool.h"
diff --git a/t/helper/test-scrap-cache-tree.c b/t/helper/test-scrap-cache-tree.c
index 3fecd06d17..6e17f50d22 100644
--- a/t/helper/test-scrap-cache-tree.c
+++ b/t/helper/test-scrap-cache-tree.c
@@ -2,6 +2,7 @@
#include "test-tool.h"
#include "cache.h"
#include "lockfile.h"
+#include "repository.h"
#include "setup.h"
#include "tree.h"
#include "cache-tree.h"
diff --git a/t/helper/test-string-list.c b/t/helper/test-string-list.c
index 63df88575c..e2aad611d1 100644
--- a/t/helper/test-string-list.c
+++ b/t/helper/test-string-list.c
@@ -1,5 +1,5 @@
#include "test-tool.h"
-#include "cache.h"
+#include "strbuf.h"
#include "string-list.h"
/*
diff --git a/t/helper/test-submodule-config.c b/t/helper/test-submodule-config.c
index 5e462faa9d..9df2f03ac8 100644
--- a/t/helper/test-submodule-config.c
+++ b/t/helper/test-submodule-config.c
@@ -1,6 +1,8 @@
#include "test-tool.h"
#include "config.h"
+#include "hash.h"
#include "object-name.h"
+#include "repository.h"
#include "setup.h"
#include "submodule-config.h"
#include "submodule.h"
diff --git a/t/helper/test-submodule-nested-repo-config.c b/t/helper/test-submodule-nested-repo-config.c
index d31f5e48ab..ecd40ded99 100644
--- a/t/helper/test-submodule-nested-repo-config.c
+++ b/t/helper/test-submodule-nested-repo-config.c
@@ -1,4 +1,5 @@
#include "test-tool.h"
+#include "repository.h"
#include "setup.h"
#include "submodule-config.h"
diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
index 7cbd59922a..356e0a26c5 100644
--- a/t/helper/test-submodule.c
+++ b/t/helper/test-submodule.c
@@ -2,6 +2,7 @@
#include "test-tool-utils.h"
#include "parse-options.h"
#include "remote.h"
+#include "repository.h"
#include "setup.h"
#include "submodule-config.h"
#include "submodule.h"
diff --git a/t/helper/test-trace2.c b/t/helper/test-trace2.c
index 98f071452a..20c7495f38 100644
--- a/t/helper/test-trace2.c
+++ b/t/helper/test-trace2.c
@@ -3,6 +3,7 @@
#include "run-command.h"
#include "exec-cmd.h"
#include "config.h"
+#include "repository.h"
#include "trace2.h"
typedef int(fn_unit_test)(int argc, const char **argv);
diff --git a/t/helper/test-write-cache.c b/t/helper/test-write-cache.c
index a93417ed3a..eace08072d 100644
--- a/t/helper/test-write-cache.c
+++ b/t/helper/test-write-cache.c
@@ -2,6 +2,7 @@
#include "test-tool.h"
#include "cache.h"
#include "lockfile.h"
+#include "repository.h"
#include "setup.h"
int cmd__write_cache(int argc, const char **argv)
diff --git a/t/lib-credential.sh b/t/lib-credential.sh
index 5ea8bc9f1d..f1ab92ba35 100644
--- a/t/lib-credential.sh
+++ b/t/lib-credential.sh
@@ -43,6 +43,7 @@ helper_test_clean() {
reject $1 https example.com store-user
reject $1 https example.com user1
reject $1 https example.com user2
+ reject $1 https example.com user4
reject $1 http path.tld user
reject $1 https timeout.tld user
reject $1 https sso.tld
@@ -270,6 +271,35 @@ helper_test() {
password=
EOF
'
+
+ : ${GIT_TEST_LONG_CRED_BUFFER:=1024}
+ # 23 bytes accounts for "wwwauth[]=basic realm=" plus NUL
+ LONG_VALUE_LEN=$((GIT_TEST_LONG_CRED_BUFFER - 23))
+ LONG_VALUE=$(perl -e 'print "a" x shift' $LONG_VALUE_LEN)
+
+ test_expect_success "helper ($HELPER) not confused by long header" '
+ check approve $HELPER <<-\EOF &&
+ protocol=https
+ host=victim.example.com
+ username=user
+ password=to-be-stolen
+ EOF
+
+ check fill $HELPER <<-EOF
+ protocol=https
+ host=badguy.example.com
+ wwwauth[]=basic realm=${LONG_VALUE}host=victim.example.com
+ --
+ protocol=https
+ host=badguy.example.com
+ username=askpass-username
+ password=askpass-password
+ wwwauth[]=basic realm=${LONG_VALUE}host=victim.example.com
+ --
+ askpass: Username for '\''https://badguy.example.com'\'':
+ askpass: Password for '\''https://askpass-username@badguy.example.com'\'':
+ EOF
+ '
}
helper_test_timeout() {
@@ -298,6 +328,35 @@ helper_test_timeout() {
'
}
+helper_test_oauth_refresh_token() {
+ HELPER=$1
+
+ test_expect_success "helper ($HELPER) stores oauth_refresh_token" '
+ check approve $HELPER <<-\EOF
+ protocol=https
+ host=example.com
+ username=user4
+ password=pass
+ oauth_refresh_token=xyzzy
+ EOF
+ '
+
+ test_expect_success "helper ($HELPER) gets oauth_refresh_token" '
+ check fill $HELPER <<-\EOF
+ protocol=https
+ host=example.com
+ username=user4
+ --
+ protocol=https
+ host=example.com
+ username=user4
+ password=pass
+ oauth_refresh_token=xyzzy
+ --
+ EOF
+ '
+}
+
write_script askpass <<\EOF
echo >&2 askpass: $*
what=$(echo $1 | cut -d" " -f1 | tr A-Z a-z | tr -cd a-z)
diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh
index 35cc8c3b39..81946e87cc 100755
--- a/t/t0020-crlf.sh
+++ b/t/t0020-crlf.sh
@@ -125,7 +125,7 @@ test_expect_success 'update with autocrlf=input' '
munge_cr append dir/two &&
git update-index -- one dir/two &&
differs=$(git diff-index --cached HEAD) &&
- verbose test -z "$differs"
+ test -z "$differs"
'
@@ -138,7 +138,7 @@ test_expect_success 'update with autocrlf=true' '
munge_cr append dir/two &&
git update-index -- one dir/two &&
differs=$(git diff-index --cached HEAD) &&
- verbose test -z "$differs"
+ test -z "$differs"
'
@@ -153,7 +153,7 @@ test_expect_success 'checkout with autocrlf=true' '
test "$one" = $(git hash-object --stdin <one) &&
test "$two" = $(git hash-object --stdin <dir/two) &&
differs=$(git diff-index --cached HEAD) &&
- verbose test -z "$differs"
+ test -z "$differs"
'
test_expect_success 'checkout with autocrlf=input' '
@@ -167,7 +167,7 @@ test_expect_success 'checkout with autocrlf=input' '
test "$one" = $(git hash-object --stdin <one) &&
test "$two" = $(git hash-object --stdin <dir/two) &&
differs=$(git diff-index --cached HEAD) &&
- verbose test -z "$differs"
+ test -z "$differs"
'
test_expect_success 'apply patch (autocrlf=input)' '
@@ -177,7 +177,7 @@ test_expect_success 'apply patch (autocrlf=input)' '
git read-tree --reset -u HEAD &&
git apply patch.file &&
- verbose test "$patched" = "$(git hash-object --stdin <one)"
+ test "$patched" = "$(git hash-object --stdin <one)"
'
test_expect_success 'apply patch --cached (autocrlf=input)' '
@@ -187,7 +187,7 @@ test_expect_success 'apply patch --cached (autocrlf=input)' '
git read-tree --reset -u HEAD &&
git apply --cached patch.file &&
- verbose test "$patched" = $(git rev-parse :one)
+ test "$patched" = $(git rev-parse :one)
'
test_expect_success 'apply patch --index (autocrlf=input)' '
@@ -197,8 +197,8 @@ test_expect_success 'apply patch --index (autocrlf=input)' '
git read-tree --reset -u HEAD &&
git apply --index patch.file &&
- verbose test "$patched" = $(git rev-parse :one) &&
- verbose test "$patched" = $(git hash-object --stdin <one)
+ test "$patched" = $(git rev-parse :one) &&
+ test "$patched" = $(git hash-object --stdin <one)
'
test_expect_success 'apply patch (autocrlf=true)' '
@@ -208,7 +208,7 @@ test_expect_success 'apply patch (autocrlf=true)' '
git read-tree --reset -u HEAD &&
git apply patch.file &&
- verbose test "$patched" = "$(remove_cr <one | git hash-object --stdin)"
+ test "$patched" = "$(remove_cr <one | git hash-object --stdin)"
'
test_expect_success 'apply patch --cached (autocrlf=true)' '
@@ -218,7 +218,7 @@ test_expect_success 'apply patch --cached (autocrlf=true)' '
git read-tree --reset -u HEAD &&
git apply --cached patch.file &&
- verbose test "$patched" = $(git rev-parse :one)
+ test "$patched" = $(git rev-parse :one)
'
test_expect_success 'apply patch --index (autocrlf=true)' '
@@ -228,8 +228,8 @@ test_expect_success 'apply patch --index (autocrlf=true)' '
git read-tree --reset -u HEAD &&
git apply --index patch.file &&
- verbose test "$patched" = $(git rev-parse :one) &&
- verbose test "$patched" = "$(remove_cr <one | git hash-object --stdin)"
+ test "$patched" = $(git rev-parse :one) &&
+ test "$patched" = "$(remove_cr <one | git hash-object --stdin)"
'
test_expect_success '.gitattributes says two is binary' '
@@ -240,7 +240,7 @@ test_expect_success '.gitattributes says two is binary' '
git read-tree --reset -u HEAD &&
! has_cr dir/two &&
- verbose has_cr one &&
+ has_cr one &&
! has_cr three
'
@@ -259,8 +259,8 @@ test_expect_success '.gitattributes says two and three are text' '
echo "t* crlf" >.gitattributes &&
git read-tree --reset -u HEAD &&
- verbose has_cr dir/two &&
- verbose has_cr three
+ has_cr dir/two &&
+ has_cr three
'
test_expect_success 'in-tree .gitattributes (1)' '
@@ -273,7 +273,7 @@ test_expect_success 'in-tree .gitattributes (1)' '
git read-tree --reset -u HEAD &&
! has_cr one &&
- verbose has_cr three
+ has_cr three
'
test_expect_success 'in-tree .gitattributes (2)' '
@@ -283,7 +283,7 @@ test_expect_success 'in-tree .gitattributes (2)' '
git checkout-index -f -q -u -a &&
! has_cr one &&
- verbose has_cr three
+ has_cr three
'
test_expect_success 'in-tree .gitattributes (3)' '
@@ -294,7 +294,7 @@ test_expect_success 'in-tree .gitattributes (3)' '
git checkout-index -u one dir/two three &&
! has_cr one &&
- verbose has_cr three
+ has_cr three
'
test_expect_success 'in-tree .gitattributes (4)' '
@@ -305,7 +305,7 @@ test_expect_success 'in-tree .gitattributes (4)' '
git checkout-index -u .gitattributes &&
! has_cr one &&
- verbose has_cr three
+ has_cr three
'
test_expect_success 'checkout with existing .gitattributes' '
diff --git a/t/t0035-safe-bare-repository.sh b/t/t0035-safe-bare-repository.sh
index 11c15a48aa..038b8b788d 100755
--- a/t/t0035-safe-bare-repository.sh
+++ b/t/t0035-safe-bare-repository.sh
@@ -7,13 +7,26 @@ TEST_PASSES_SANITIZE_LEAK=true
pwd="$(pwd)"
-expect_accepted () {
- git "$@" rev-parse --git-dir
+expect_accepted_implicit () {
+ test_when_finished 'rm "$pwd/trace.perf"' &&
+ GIT_TRACE2_PERF="$pwd/trace.perf" git "$@" rev-parse --git-dir &&
+ # Note: we're intentionally only checking that the bare repo has a
+ # directory *prefix* of $pwd
+ grep -F "implicit-bare-repository:$pwd" "$pwd/trace.perf"
+}
+
+expect_accepted_explicit () {
+ test_when_finished 'rm "$pwd/trace.perf"' &&
+ GIT_DIR="$1" GIT_TRACE2_PERF="$pwd/trace.perf" git rev-parse --git-dir &&
+ ! grep -F "implicit-bare-repository:$pwd" "$pwd/trace.perf"
}
expect_rejected () {
- test_must_fail git "$@" rev-parse --git-dir 2>err &&
- grep -F "cannot use bare repository" err
+ test_when_finished 'rm "$pwd/trace.perf"' &&
+ test_env GIT_TRACE2_PERF="$pwd/trace.perf" \
+ test_must_fail git "$@" rev-parse --git-dir 2>err &&
+ grep -F "cannot use bare repository" err &&
+ grep -F "implicit-bare-repository:$pwd" "$pwd/trace.perf"
}
test_expect_success 'setup bare repo in worktree' '
@@ -22,12 +35,13 @@ test_expect_success 'setup bare repo in worktree' '
'
test_expect_success 'safe.bareRepository unset' '
- expect_accepted -C outer-repo/bare-repo
+ test_unconfig --global safe.bareRepository &&
+ expect_accepted_implicit -C outer-repo/bare-repo
'
test_expect_success 'safe.bareRepository=all' '
test_config_global safe.bareRepository all &&
- expect_accepted -C outer-repo/bare-repo
+ expect_accepted_implicit -C outer-repo/bare-repo
'
test_expect_success 'safe.bareRepository=explicit' '
@@ -47,7 +61,7 @@ test_expect_success 'safe.bareRepository in the repository' '
test_expect_success 'safe.bareRepository on the command line' '
test_config_global safe.bareRepository explicit &&
- expect_accepted -C outer-repo/bare-repo \
+ expect_accepted_implicit -C outer-repo/bare-repo \
-c safe.bareRepository=all
'
@@ -60,4 +74,8 @@ test_expect_success 'safe.bareRepository in included file' '
expect_rejected -C outer-repo/bare-repo
'
+test_expect_success 'no trace when GIT_DIR is explicitly provided' '
+ expect_accepted_explicit "$pwd/outer-repo/bare-repo"
+'
+
test_done
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
index c66d91e82d..a4f5bba507 100755
--- a/t/t0300-credentials.sh
+++ b/t/t0300-credentials.sh
@@ -214,6 +214,24 @@ test_expect_success 'credential_approve stores password expiry' '
EOF
'
+test_expect_success 'credential_approve stores oauth refresh token' '
+ check approve useless <<-\EOF
+ protocol=http
+ host=example.com
+ username=foo
+ password=bar
+ oauth_refresh_token=xyzzy
+ --
+ --
+ useless: store
+ useless: protocol=http
+ useless: host=example.com
+ useless: username=foo
+ useless: password=bar
+ useless: oauth_refresh_token=xyzzy
+ EOF
+'
+
test_expect_success 'do not bother storing password-less credential' '
check approve useless <<-\EOF
protocol=http
@@ -808,7 +826,7 @@ test_expect_success 'credential config with partial URLs' '
git -c credential.$partial.helper=yep \
-c credential.with%0anewline.username=uh-oh \
- credential fill <stdin >stdout 2>stderr &&
+ credential fill <stdin 2>stderr &&
test_i18ngrep "skipping credential lookup for key" stderr
'
diff --git a/t/t0301-credential-cache.sh b/t/t0301-credential-cache.sh
index 698b7159f0..c02a3b5969 100755
--- a/t/t0301-credential-cache.sh
+++ b/t/t0301-credential-cache.sh
@@ -29,6 +29,7 @@ test_atexit 'git credential-cache exit'
# test that the daemon works with no special setup
helper_test cache
+helper_test_oauth_refresh_token cache
test_expect_success 'socket defaults to ~/.cache/git/credential/socket' '
test_when_finished "
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index f1d42b62b0..86bfbc2b36 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -98,6 +98,23 @@ test_expect_success 'subsections are not canonicalized by git-config' '
test_cmp_config two section.SubSection.key
'
+test_missing_key () {
+ local key="$1" &&
+ local title="$2" &&
+ test_expect_success "value for $title is not printed" '
+ test_must_fail git config "$key" >out 2>err &&
+ test_must_be_empty out &&
+ test_must_be_empty err
+ '
+}
+
+test_missing_key 'missingsection.missingkey' 'missing section and missing key'
+test_missing_key 'missingsection.penguin' 'missing section and existing key'
+test_missing_key 'section.missingkey' 'existing section and missing key'
+test_missing_key 'section.MissingSubSection.missingkey' 'missing subsection and missing key'
+test_missing_key 'section.SubSection.missingkey' 'existing subsection and missing key'
+test_missing_key 'section.MissingSubSection.key' 'missing subsection and existing key'
+
cat > .git/config <<\EOF
[alpha]
bar = foo
@@ -1488,35 +1505,29 @@ test_expect_success 'git config ignores pairs without count' '
test_must_be_empty error
'
-test_expect_success 'git config ignores pairs with zero count' '
- test_must_fail env \
- GIT_CONFIG_COUNT=0 \
- GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \
- git config pair.one
-'
-
test_expect_success 'git config ignores pairs exceeding count' '
GIT_CONFIG_COUNT=1 \
GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \
GIT_CONFIG_KEY_1="pair.two" GIT_CONFIG_VALUE_1="value" \
- git config --get-regexp "pair.*" >actual &&
+ git config --get-regexp "pair.*" >actual 2>error &&
cat >expect <<-EOF &&
pair.one value
EOF
- test_cmp expect actual
+ test_cmp expect actual &&
+ test_must_be_empty error
'
test_expect_success 'git config ignores pairs with zero count' '
test_must_fail env \
GIT_CONFIG_COUNT=0 GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \
- git config pair.one >error &&
+ git config pair.one 2>error &&
test_must_be_empty error
'
test_expect_success 'git config ignores pairs with empty count' '
test_must_fail env \
GIT_CONFIG_COUNT= GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \
- git config pair.one >error &&
+ git config pair.one 2>error &&
test_must_be_empty error
'
@@ -1601,11 +1612,11 @@ test_expect_success 'git config --edit respects core.editor' '
# malformed configuration files
test_expect_success 'barf on syntax error' '
cat >.git/config <<-\EOF &&
- # broken section line
+ # broken key=value
[section]
key garbage
EOF
- test_must_fail git config --get section.key >actual 2>error &&
+ test_must_fail git config --get section.key 2>error &&
test_i18ngrep " line 3 " error
'
@@ -1615,17 +1626,17 @@ test_expect_success 'barf on incomplete section header' '
[section
key = value
EOF
- test_must_fail git config --get section.key >actual 2>error &&
+ test_must_fail git config --get section.key 2>error &&
test_i18ngrep " line 2 " error
'
test_expect_success 'barf on incomplete string' '
cat >.git/config <<-\EOF &&
- # broken section line
+ # broken value string
[section]
key = "value string
EOF
- test_must_fail git config --get section.key >actual 2>error &&
+ test_must_fail git config --get section.key 2>error &&
test_i18ngrep " line 3 " error
'
diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh
index 1b6437ec07..ae5cd3f5a0 100755
--- a/t/t1301-shared-repo.sh
+++ b/t/t1301-shared-repo.sh
@@ -89,7 +89,7 @@ do
rm -f .git/info/refs &&
git update-server-info &&
actual="$(test_modebits .git/info/refs)" &&
- verbose test "x$actual" = "x-$y"
+ test "x$actual" = "x-$y"
'
@@ -99,7 +99,7 @@ do
rm -f .git/info/refs &&
git update-server-info &&
actual="$(test_modebits .git/info/refs)" &&
- verbose test "x$actual" = "x-$x"
+ test "x$actual" = "x-$x"
'
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index bca46378b2..8c442adb1a 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -989,10 +989,7 @@ test_expect_success 'fsck error and recovery on invalid object type' '
garbage_blob=$(git hash-object --stdin -w -t garbage --literally </dev/null) &&
- cat >err.expect <<-\EOF &&
- fatal: invalid object type
- EOF
- test_must_fail git fsck >out 2>err &&
+ test_must_fail git fsck 2>err &&
grep -e "^error" -e "^fatal" err >errors &&
test_line_count = 1 errors &&
grep "$garbage_blob: object is of unknown type '"'"'garbage'"'"':" err
diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh
index de1d48f3ba..dd811b7fb4 100755
--- a/t/t1502-rev-parse-parseopt.sh
+++ b/t/t1502-rev-parse-parseopt.sh
@@ -302,14 +302,14 @@ test_expect_success 'test --parseopt help output: "wrapped" options normal "or:"
|EOF
END_EXPECT
- test_must_fail git rev-parse --parseopt -- -h >out <spec >actual &&
+ test_must_fail git rev-parse --parseopt -- -h <spec >actual &&
test_cmp expect actual
'
test_expect_success 'test --parseopt invalid opt-spec' '
test_write_lines x -- "=, x" >spec &&
echo "fatal: missing opt-spec before option flags" >expect &&
- test_must_fail git rev-parse --parseopt -- >out <spec 2>err &&
+ test_must_fail git rev-parse --parseopt -- <spec 2>err &&
test_cmp expect err
'
@@ -339,7 +339,7 @@ test_expect_success 'test --parseopt help output: multi-line blurb after empty l
|EOF
END_EXPECT
- test_must_fail git rev-parse --parseopt -- -h >out <spec >actual &&
+ test_must_fail git rev-parse --parseopt -- -h <spec >actual &&
test_cmp expect actual
'
diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh
index d94c72c672..cb9ef7e329 100755
--- a/t/t1507-rev-parse-upstream.sh
+++ b/t/t1507-rev-parse-upstream.sh
@@ -97,7 +97,8 @@ test_expect_success 'my-side@{u} resolves to correct commit' '
commit_subject my-side >actual &&
test_cmp expect actual &&
echo 5 >expect &&
- commit_subject my-side@{u} >actual
+ commit_subject my-side@{u} >actual &&
+ test_cmp expect actual
'
test_expect_success 'not-tracking@{u} fails' '
diff --git a/t/t2019-checkout-ambiguous-ref.sh b/t/t2019-checkout-ambiguous-ref.sh
index 2c8c926b4d..9540588664 100755
--- a/t/t2019-checkout-ambiguous-ref.sh
+++ b/t/t2019-checkout-ambiguous-ref.sh
@@ -16,7 +16,7 @@ test_expect_success 'setup ambiguous refs' '
'
test_expect_success 'checkout ambiguous ref succeeds' '
- git checkout ambiguity >stdout 2>stderr
+ git checkout ambiguity 2>stderr
'
test_expect_success 'checkout produces ambiguity warning' '
@@ -37,7 +37,7 @@ test_expect_success 'checkout reports switch to branch' '
'
test_expect_success 'checkout vague ref succeeds' '
- git checkout vagueness >stdout 2>stderr &&
+ git checkout vagueness 2>stderr &&
test_set_prereq VAGUENESS_SUCCESS
'
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 5a8a48287c..98b6c8ac34 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -239,6 +239,21 @@ test_expect_success 'git branch -M baz bam should succeed when baz is checked ou
git worktree prune
'
+test_expect_success 'git branch -M fails if updating any linked working tree fails' '
+ git worktree add -b baz bazdir1 &&
+ git worktree add -f bazdir2 baz &&
+ touch .git/worktrees/bazdir1/HEAD.lock &&
+ test_must_fail git branch -M baz bam &&
+ test $(git -C bazdir2 rev-parse --abbrev-ref HEAD) = bam &&
+ git branch -M bam baz &&
+ rm .git/worktrees/bazdir1/HEAD.lock &&
+ touch .git/worktrees/bazdir2/HEAD.lock &&
+ test_must_fail git branch -M baz bam &&
+ test $(git -C bazdir1 rev-parse --abbrev-ref HEAD) = bam &&
+ rm -rf bazdir1 bazdir2 &&
+ git worktree prune
+'
+
test_expect_success 'git branch -M baz bam should succeed within a worktree in which baz is checked out' '
git checkout -b baz &&
git worktree add -f bazdir baz &&
@@ -283,6 +298,20 @@ test_expect_success 'git branch -M and -C fail on detached HEAD' '
test_cmp expect err
'
+test_expect_success 'git branch -m should work with orphan branches' '
+ test_when_finished git checkout - &&
+ test_when_finished git worktree remove -f wt &&
+ git worktree add wt --detach &&
+ # rename orphan in another worktreee
+ git -C wt checkout --orphan orphan-foo-wt &&
+ git branch -m orphan-foo-wt orphan-bar-wt &&
+ test orphan-bar-wt=$(git -C orphan-worktree branch --show-current) &&
+ # rename orphan in the current worktree
+ git checkout --orphan orphan-foo &&
+ git branch -m orphan-foo orphan-bar &&
+ test orphan-bar=$(git branch --show-current)
+'
+
test_expect_success 'git branch -d on orphan HEAD (merged)' '
test_when_finished git checkout main &&
git checkout --orphan orphan &&
diff --git a/t/t3202-show-branch.sh b/t/t3202-show-branch.sh
index ea7cfd1951..be20ebe1d5 100755
--- a/t/t3202-show-branch.sh
+++ b/t/t3202-show-branch.sh
@@ -221,4 +221,22 @@ test_expect_success 'fatal descriptions on non-existent branch' '
test_cmp expect actual
'
+test_expect_success 'error descriptions on orphan branch' '
+ test_when_finished git worktree remove -f wt &&
+ git worktree add wt --detach &&
+ git -C wt checkout --orphan orphan-branch &&
+ test_branch_op_in_wt() {
+ test_orphan_error() {
+ test_must_fail git $* 2>actual &&
+ test_i18ngrep "No commit on branch .orphan-branch. yet.$" actual
+ } &&
+ test_orphan_error -C wt branch $1 $2 && # implicit branch
+ test_orphan_error -C wt branch $1 orphan-branch $2 && # explicit branch
+ test_orphan_error branch $1 orphan-branch $2 # different worktree
+ } &&
+ test_branch_op_in_wt --edit-description &&
+ test_branch_op_in_wt --set-upstream-to=ne &&
+ test_branch_op_in_wt -c new-branch
+'
+
test_done
diff --git a/t/t3427-rebase-subtree.sh b/t/t3427-rebase-subtree.sh
index 48b76f8232..1b3e97c875 100755
--- a/t/t3427-rebase-subtree.sh
+++ b/t/t3427-rebase-subtree.sh
@@ -74,9 +74,9 @@ test_expect_success 'Rebase -Xsubtree --empty=ask --onto commit' '
test_must_fail git rebase -Xsubtree=files_subtree --empty=ask --onto files-main main &&
: first pick results in no changes &&
git rebase --skip &&
- verbose test "$(commit_message HEAD~2)" = "topic_4" &&
- verbose test "$(commit_message HEAD~)" = "files_subtree/topic_5" &&
- verbose test "$(commit_message HEAD)" = "Empty commit"
+ test "$(commit_message HEAD~2)" = "topic_4" &&
+ test "$(commit_message HEAD~)" = "files_subtree/topic_5" &&
+ test "$(commit_message HEAD)" = "Empty commit"
'
test_expect_success 'Rebase -Xsubtree --empty=ask --rebase-merges --onto commit' '
@@ -85,9 +85,9 @@ test_expect_success 'Rebase -Xsubtree --empty=ask --rebase-merges --onto commit'
test_must_fail git rebase -Xsubtree=files_subtree --empty=ask --rebase-merges --onto files-main --root &&
: first pick results in no changes &&
git rebase --skip &&
- verbose test "$(commit_message HEAD~2)" = "topic_4" &&
- verbose test "$(commit_message HEAD~)" = "files_subtree/topic_5" &&
- verbose test "$(commit_message HEAD)" = "Empty commit"
+ test "$(commit_message HEAD~2)" = "topic_4" &&
+ test "$(commit_message HEAD~)" = "files_subtree/topic_5" &&
+ test "$(commit_message HEAD)" = "Empty commit"
'
test_done
diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh
index 2f3e3e2416..e2ef619323 100755
--- a/t/t3501-revert-cherry-pick.sh
+++ b/t/t3501-revert-cherry-pick.sh
@@ -1,14 +1,6 @@
#!/bin/sh
-test_description='test cherry-pick and revert with renames
-
- --
- + rename2: renames oops to opos
- + rename1: renames oops to spoo
- + added: adds extra line to oops
- ++ initial: has lines in oops
-
-'
+test_description='miscellaneous basic tests for cherry-pick and revert'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
@@ -63,6 +55,14 @@ test_expect_success 'revert --nonsense' '
test_i18ngrep "[Uu]sage:" msg
'
+# the following two test cherry-pick and revert with renames
+#
+# --
+# + rename2: renames oops to opos
+# + rename1: renames oops to spoo
+# + added: adds extra line to oops
+# ++ initial: has lines in oops
+
test_expect_success 'cherry-pick after renaming branch' '
git checkout rename2 &&
diff --git a/t/t4022-diff-rewrite.sh b/t/t4022-diff-rewrite.sh
index 1c89050a97..6fed993ea0 100755
--- a/t/t4022-diff-rewrite.sh
+++ b/t/t4022-diff-rewrite.sh
@@ -24,7 +24,7 @@ test_expect_success setup '
test_expect_success 'detect rewrite' '
actual=$(git diff-files -B --summary test) &&
- verbose expr "$actual" : " rewrite test ([0-9]*%)$"
+ expr "$actual" : " rewrite test ([0-9]*%)$"
'
diff --git a/t/t4047-diff-dirstat.sh b/t/t4047-diff-dirstat.sh
index 7fec2cb9cd..70224c3da1 100755
--- a/t/t4047-diff-dirstat.sh
+++ b/t/t4047-diff-dirstat.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='diff --dirstat tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# set up two commits where the second commit has these files
diff --git a/t/t4062-diff-pickaxe.sh b/t/t4062-diff-pickaxe.sh
index 9aaa068ed9..a90b46b678 100755
--- a/t/t4062-diff-pickaxe.sh
+++ b/t/t4062-diff-pickaxe.sh
@@ -24,7 +24,7 @@ test_expect_success '-G matches' '
test_expect_success '-S --pickaxe-regex' '
git diff --name-only -S0 --pickaxe-regex HEAD^ >out &&
- verbose test 4096-zeroes.txt = "$(cat out)"
+ test 4096-zeroes.txt = "$(cat out)"
'
test_done
diff --git a/t/t4212-log-corrupt.sh b/t/t4212-log-corrupt.sh
index e89e1f54b6..85e90acb09 100755
--- a/t/t4212-log-corrupt.sh
+++ b/t/t4212-log-corrupt.sh
@@ -8,8 +8,9 @@ TEST_PASSES_SANITIZE_LEAK=true
test_expect_success 'setup' '
test_commit foo &&
- git cat-file commit HEAD |
- sed "/^author /s/>/>-<>/" >broken_email.commit &&
+ git cat-file commit HEAD >ok.commit &&
+ sed "s/>/>-<>/" <ok.commit >broken_email.commit &&
+
git hash-object --literally -w -t commit broken_email.commit >broken_email.hash &&
git update-ref refs/heads/broken_email $(cat broken_email.hash)
'
@@ -43,6 +44,11 @@ test_expect_success 'git log --format with broken author email' '
test_must_be_empty actual.err
'
+test_expect_success '--until handles broken email' '
+ git rev-list --until=1980-01-01 broken_email >actual &&
+ test_must_be_empty actual
+'
+
munge_author_date () {
git cat-file commit "$1" >commit.orig &&
sed "s/^\(author .*>\) [0-9]*/\1 $2/" <commit.orig >commit.munge &&
@@ -86,4 +92,45 @@ test_expect_success 'absurdly far-in-future date' '
git log -1 --format=%ad $commit
'
+test_expect_success 'create commits with whitespace committer dates' '
+ # It is important that this subject line is numeric, since we want to
+ # be sure we are not confused by skipping whitespace and accidentally
+ # parsing the subject as a timestamp.
+ #
+ # Do not use munge_author_date here. Besides not hitting the committer
+ # line, it leaves the timezone intact, and we want nothing but
+ # whitespace.
+ #
+ # We will make two munged commits here. The first, ws_commit, will
+ # be purely spaces. The second contains a vertical tab, which is
+ # considered a space by strtoumax(), but not by our isspace().
+ test_commit 1234567890 &&
+ git cat-file commit HEAD >commit.orig &&
+ sed "s/>.*/> /" <commit.orig >commit.munge &&
+ ws_commit=$(git hash-object --literally -w -t commit commit.munge) &&
+ sed "s/>.*/> $(printf "\013")/" <commit.orig >commit.munge &&
+ vt_commit=$(git hash-object --literally -w -t commit commit.munge)
+'
+
+test_expect_success '--until treats whitespace date as sentinel' '
+ echo $ws_commit >expect &&
+ git rev-list --until=1980-01-01 $ws_commit >actual &&
+ test_cmp expect actual &&
+
+ echo $vt_commit >expect &&
+ git rev-list --until=1980-01-01 $vt_commit >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'pretty-printer handles whitespace date' '
+ # as with the %ad test above, we will show these as the empty string,
+ # not the 1970 epoch date. This is intentional; see 7d9a281941 (t4212:
+ # test bogus timestamps with git-log, 2014-02-24) for more discussion.
+ echo : >expect &&
+ git log -1 --format="%at:%ct" $ws_commit >actual &&
+ test_cmp expect actual &&
+ git log -1 --format="%at:%ct" $vt_commit >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh
index 662ae9b152..f367327441 100755
--- a/t/t5304-prune.sh
+++ b/t/t5304-prune.sh
@@ -16,7 +16,7 @@ add_blob() {
before=$(git count-objects | sed "s/ .*//") &&
BLOB=$(echo aleph_0 | git hash-object -w --stdin) &&
BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") &&
- verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
+ test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE &&
test-tool chmtime =+0 $BLOB_FILE
}
@@ -51,11 +51,11 @@ test_expect_success 'prune stale packs' '
test_expect_success 'prune --expire' '
add_blob &&
git prune --expire=1.hour.ago &&
- verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
+ test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE &&
test-tool chmtime =-86500 $BLOB_FILE &&
git prune --expire 1.day &&
- verbose test $before = $(git count-objects | sed "s/ .*//") &&
+ test $before = $(git count-objects | sed "s/ .*//") &&
test_path_is_missing $BLOB_FILE
'
@@ -63,11 +63,11 @@ test_expect_success 'gc: implicit prune --expire' '
add_blob &&
test-tool chmtime =-$((2*$week-30)) $BLOB_FILE &&
git gc --no-cruft &&
- verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
+ test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE &&
test-tool chmtime =-$((2*$week+1)) $BLOB_FILE &&
git gc --no-cruft &&
- verbose test $before = $(git count-objects | sed "s/ .*//") &&
+ test $before = $(git count-objects | sed "s/ .*//") &&
test_path_is_missing $BLOB_FILE
'
@@ -138,7 +138,7 @@ test_expect_success 'gc --no-prune' '
test-tool chmtime =-$((5001*$day)) $BLOB_FILE &&
git config gc.pruneExpire 2.days.ago &&
git gc --no-prune --no-cruft &&
- verbose test 1 = $(git count-objects | sed "s/ .*//") &&
+ test 1 = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE
'
@@ -192,10 +192,10 @@ test_expect_success 'gc: prune old objects after local clone' '
git clone --no-hardlinks . aclone &&
(
cd aclone &&
- verbose test 1 = $(git count-objects | sed "s/ .*//") &&
+ test 1 = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE &&
git gc --prune --no-cruft &&
- verbose test 0 = $(git count-objects | sed "s/ .*//") &&
+ test 0 = $(git count-objects | sed "s/ .*//") &&
test_path_is_missing $BLOB_FILE
)
'
diff --git a/t/t5326-multi-pack-bitmaps.sh b/t/t5326-multi-pack-bitmaps.sh
index 0882cbb6e4..f771c442d4 100755
--- a/t/t5326-multi-pack-bitmaps.sh
+++ b/t/t5326-multi-pack-bitmaps.sh
@@ -434,4 +434,48 @@ test_expect_success 'tagged commits are selected for bitmapping' '
)
'
+corrupt_file () {
+ chmod a+w "$1" &&
+ printf "bogus" | dd of="$1" bs=1 seek="12" conv=notrunc
+}
+
+test_expect_success 'git fsck correctly identifies good and bad bitmaps' '
+ git init valid &&
+ test_when_finished rm -rf valid &&
+
+ test_commit_bulk 20 &&
+ git repack -adbf &&
+
+ # Move pack-bitmap aside so it is not deleted
+ # in next repack.
+ packbitmap=$(ls .git/objects/pack/pack-*.bitmap) &&
+ mv "$packbitmap" "$packbitmap.bak" &&
+
+ test_commit_bulk 10 &&
+ git repack -b --write-midx &&
+ midxbitmap=$(ls .git/objects/pack/multi-pack-index-*.bitmap) &&
+
+ # Copy MIDX bitmap to backup. Copy pack bitmap from backup.
+ cp "$midxbitmap" "$midxbitmap.bak" &&
+ cp "$packbitmap.bak" "$packbitmap" &&
+
+ # fsck works at first
+ git fsck 2>err &&
+ test_must_be_empty err &&
+
+ corrupt_file "$packbitmap" &&
+ test_must_fail git fsck 2>err &&
+ grep "bitmap file '\''$packbitmap'\'' has invalid checksum" err &&
+
+ cp "$packbitmap.bak" "$packbitmap" &&
+ corrupt_file "$midxbitmap" &&
+ test_must_fail git fsck 2>err &&
+ grep "bitmap file '\''$midxbitmap'\'' has invalid checksum" err &&
+
+ corrupt_file "$packbitmap" &&
+ test_must_fail git fsck 2>err &&
+ grep "bitmap file '\''$midxbitmap'\'' has invalid checksum" err &&
+ grep "bitmap file '\''$packbitmap'\'' has invalid checksum" err
+'
+
test_done
diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh
index c9acc07635..1b8d609879 100755
--- a/t/t5523-push-upstream.sh
+++ b/t/t5523-push-upstream.sh
@@ -61,12 +61,20 @@ test_expect_success 'push -u :topic_2' '
check_config topic_2 upstream refs/heads/other2
'
-test_expect_success 'push -u --all' '
+test_expect_success 'push -u --all(the same behavior with--branches)' '
git branch all1 &&
git branch all2 &&
git push -u --all &&
check_config all1 upstream refs/heads/all1 &&
- check_config all2 upstream refs/heads/all2
+ check_config all2 upstream refs/heads/all2 &&
+ git config --get-regexp branch.all* > expect &&
+ git config --remove-section branch.all1 &&
+ git config --remove-section branch.all2 &&
+ git push -u --branches &&
+ check_config all1 upstream refs/heads/all1 &&
+ check_config all2 upstream refs/heads/all2 &&
+ git config --get-regexp branch.all* > actual &&
+ test_cmp expect actual
'
test_expect_success 'push -u HEAD' '
diff --git a/t/t5543-atomic-push.sh b/t/t5543-atomic-push.sh
index 70431122a4..04b47ad84a 100755
--- a/t/t5543-atomic-push.sh
+++ b/t/t5543-atomic-push.sh
@@ -117,7 +117,10 @@ test_expect_success 'atomic push fails if one branch fails' '
test_commit five &&
git checkout main &&
test_commit six &&
- test_must_fail git push --atomic --all up
+ test_must_fail git push --atomic --all up >output-all 2>&1 &&
+ # --all and --branches have the same behavior when be combined with --atomic
+ test_must_fail git push --atomic --branches up >output-branches 2>&1 &&
+ test_cmp output-all output-branches
) &&
test_refs main HEAD@{7} &&
test_refs second HEAD@{4}
diff --git a/t/t5583-push-branches.sh b/t/t5583-push-branches.sh
new file mode 100755
index 0000000000..e7e1b6dab6
--- /dev/null
+++ b/t/t5583-push-branches.sh
@@ -0,0 +1,115 @@
+#!/bin/sh
+
+test_description='check the consisitency of behavior of --all and --branches'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+delete_refs() {
+ dir=$1
+ shift
+ rm -rf deletes
+ for arg in $*
+ do
+ echo "delete ${arg}" >>deletes
+ done
+ git -C $dir update-ref --stdin < deletes
+}
+
+test_expect_success 'setup bare remote' '
+ git init --bare remote-1 &&
+ git -C remote-1 config gc.auto 0 &&
+ test_commit one &&
+ git push remote-1 HEAD
+'
+
+test_expect_success 'setup different types of references' '
+ cat >refs <<-EOF &&
+ update refs/heads/branch-1 HEAD
+ update refs/heads/branch-2 HEAD
+ EOF
+
+ git tag -a -m "annotated" annotated-1 HEAD &&
+ git tag -a -m "annotated" annotated-2 HEAD &&
+ git update-ref --stdin < refs
+'
+
+test_expect_success '--all and --branches have the same behavior' '
+ test_when_finished "delete_refs remote-1 \
+ refs/heads/branch-1 \
+ refs/heads/branch-2" &&
+ git push remote-1 --all &&
+ commit=$(git rev-parse HEAD) &&
+ cat >expect <<-EOF &&
+ $commit refs/heads/branch-1
+ $commit refs/heads/branch-2
+ $commit refs/heads/main
+ EOF
+
+ git -C remote-1 show-ref --heads >actual.all &&
+ delete_refs remote-1 refs/heads/branch-1 refs/heads/branch-2 &&
+ git push remote-1 --branches &&
+ git -C remote-1 show-ref --heads >actual.branches &&
+ test_cmp actual.all actual.branches &&
+ test_cmp expect actual.all
+'
+
+test_expect_success '--all or --branches can not be combined with refspecs' '
+ test_must_fail git push remote-1 --all main >actual.all 2>&1 &&
+ test_must_fail git push remote-1 --branches main >actual.branches 2>&1 &&
+ test_cmp actual.all actual.branches &&
+ grep "be combined with refspecs" actual.all
+'
+
+test_expect_success '--all or --branches can not be combined with --mirror' '
+ test_must_fail git push remote-1 --all --mirror >actual.all 2>&1 &&
+ test_must_fail git push remote-1 --branches --mirror >actual.branches 2>&1 &&
+ test_cmp actual.all actual.branches &&
+ grep "cannot be used together" actual.all
+'
+
+test_expect_success '--all or --branches can not be combined with --tags' '
+ test_must_fail git push remote-1 --all --tags >actual.all 2>&1 &&
+ test_must_fail git push remote-1 --branches --tags >actual.branches 2>&1 &&
+ test_cmp actual.all actual.branches &&
+ grep "cannot be used together" actual.all
+'
+
+
+test_expect_success '--all or --branches can not be combined with --delete' '
+ test_must_fail git push remote-1 --all --delete >actual.all 2>&1 &&
+ test_must_fail git push remote-1 --branches --delete >actual.branches 2>&1 &&
+ test_cmp actual.all actual.branches &&
+ grep "cannot be used together" actual.all
+'
+
+test_expect_success '--all or --branches combines with --follow-tags have same behavior' '
+ test_when_finished "delete_refs remote-1 \
+ refs/heads/branch-1 \
+ refs/heads/branch-2 \
+ refs/tags/annotated-1 \
+ refs/tags/annotated-2" &&
+ git push remote-1 --all --follow-tags &&
+ git -C remote-1 show-ref > actual.all &&
+ cat >expect <<-EOF &&
+ $commit refs/heads/branch-1
+ $commit refs/heads/branch-2
+ $commit refs/heads/main
+ $(git rev-parse annotated-1) refs/tags/annotated-1
+ $(git rev-parse annotated-2) refs/tags/annotated-2
+ EOF
+
+ delete_refs remote-1 \
+ refs/heads/branch-1 \
+ refs/heads/branch-2 \
+ refs/tags/annotated-1 \
+ refs/tags/annotated-2 &&
+ git push remote-1 --branches --follow-tags &&
+ git -C remote-1 show-ref >actual.branches &&
+ test_cmp actual.all actual.branches &&
+ test_cmp expect actual.all
+'
+
+test_done
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index 41d0ca00b1..573eb97a0f 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -493,7 +493,7 @@ test_expect_success 'empty email' '
test_tick &&
C=$(GIT_AUTHOR_EMAIL= git commit-tree HEAD^{tree} </dev/null) &&
A=$(git show --pretty=format:%an,%ae,%ad%n -s $C) &&
- verbose test "$A" = "$GIT_AUTHOR_NAME,,Thu Apr 7 15:14:13 2005 -0700"
+ test "$A" = "$GIT_AUTHOR_NAME,,Thu Apr 7 15:14:13 2005 -0700"
'
test_expect_success 'del LF before empty (1)' '
diff --git a/t/t6501-freshen-objects.sh b/t/t6501-freshen-objects.sh
index dbfa8a4d4c..4521508b83 100755
--- a/t/t6501-freshen-objects.sh
+++ b/t/t6501-freshen-objects.sh
@@ -152,7 +152,7 @@ test_expect_success 'do not complain about existing broken links (commit)' '
EOF
commit=$(git hash-object -t commit -w broken-commit) &&
git gc --no-cruft -q 2>stderr &&
- verbose git cat-file -e $commit &&
+ git cat-file -e $commit &&
test_must_be_empty stderr
'
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index d72cef8826..898a920532 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -4,6 +4,10 @@ test_description='git mv in subdirs'
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-diff-data.sh
+index_at_path () {
+ git ls-files --format='%(objectmode) %(objectname) %(stage)' "$@"
+}
+
test_expect_success 'mv -f refreshes updated index entry' '
echo test >bar &&
git add bar &&
@@ -187,7 +191,8 @@ test_expect_success "Michael Cassar's test case" '
git mv papers/unsorted/Thesis.pdf papers/all-papers/moo-blah.pdf &&
T=$(git write-tree) &&
- git ls-tree -r $T | verbose grep partA/outline.txt
+ git ls-tree -r $T >out &&
+ grep partA/outline.txt out
'
rm -fr papers partA path?
@@ -260,12 +265,12 @@ test_expect_success 'git mv should not change sha1 of moved cache entry' '
git init &&
echo 1 >dirty &&
git add dirty &&
- entry="$(git ls-files --stage dirty | cut -f 1)" &&
+ entry="$(index_at_path dirty)" &&
git mv dirty dirty2 &&
- test "$entry" = "$(git ls-files --stage dirty2 | cut -f 1)" &&
+ test "$entry" = "$(index_at_path dirty2)" &&
echo 2 >dirty2 &&
git mv dirty2 dirty &&
- test "$entry" = "$(git ls-files --stage dirty | cut -f 1)"
+ test "$entry" = "$(index_at_path dirty)"
'
rm -f dirty dirty2
@@ -342,7 +347,7 @@ test_expect_success 'git mv cannot move a submodule in a file' '
'
test_expect_success 'git mv moves a submodule with a .git directory and no .gitmodules' '
- entry="$(git ls-files --stage sub | cut -f 1)" &&
+ entry="$(index_at_path sub)" &&
git rm .gitmodules &&
(
cd sub &&
@@ -353,7 +358,7 @@ test_expect_success 'git mv moves a submodule with a .git directory and no .gitm
mkdir mod &&
git mv sub mod/sub &&
test_path_is_missing sub &&
- test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+ test "$entry" = "$(index_at_path mod/sub)" &&
git -C mod/sub status &&
git update-index --refresh &&
git diff-files --quiet
@@ -363,7 +368,7 @@ test_expect_success 'git mv moves a submodule with a .git directory and .gitmodu
rm -rf mod &&
git reset --hard &&
git submodule update &&
- entry="$(git ls-files --stage sub | cut -f 1)" &&
+ entry="$(index_at_path sub)" &&
(
cd sub &&
rm -f .git &&
@@ -373,7 +378,7 @@ test_expect_success 'git mv moves a submodule with a .git directory and .gitmodu
mkdir mod &&
git mv sub mod/sub &&
test_path_is_missing sub &&
- test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+ test "$entry" = "$(index_at_path mod/sub)" &&
git -C mod/sub status &&
echo mod/sub >expected &&
git config -f .gitmodules submodule.sub.path >actual &&
@@ -386,11 +391,11 @@ test_expect_success 'git mv moves a submodule with gitfile' '
rm -rf mod &&
git reset --hard &&
git submodule update &&
- entry="$(git ls-files --stage sub | cut -f 1)" &&
+ entry="$(index_at_path sub)" &&
mkdir mod &&
git -C mod mv ../sub/ . &&
test_path_is_missing sub &&
- test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+ test "$entry" = "$(index_at_path mod/sub)" &&
git -C mod/sub status &&
echo mod/sub >expected &&
git config -f .gitmodules submodule.sub.path >actual &&
@@ -404,12 +409,12 @@ test_expect_success 'mv does not complain when no .gitmodules file is found' '
git reset --hard &&
git submodule update &&
git rm .gitmodules &&
- entry="$(git ls-files --stage sub | cut -f 1)" &&
+ entry="$(index_at_path sub)" &&
mkdir mod &&
git mv sub mod/sub 2>actual.err &&
test_must_be_empty actual.err &&
test_path_is_missing sub &&
- test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+ test "$entry" = "$(index_at_path mod/sub)" &&
git -C mod/sub status &&
git update-index --refresh &&
git diff-files --quiet
@@ -420,7 +425,7 @@ test_expect_success 'mv will error out on a modified .gitmodules file unless sta
git reset --hard &&
git submodule update &&
git config -f .gitmodules foo.bar true &&
- entry="$(git ls-files --stage sub | cut -f 1)" &&
+ entry="$(index_at_path sub)" &&
mkdir mod &&
test_must_fail git mv sub mod/sub 2>actual.err &&
test_file_not_empty actual.err &&
@@ -430,7 +435,7 @@ test_expect_success 'mv will error out on a modified .gitmodules file unless sta
git mv sub mod/sub 2>actual.err &&
test_must_be_empty actual.err &&
test_path_is_missing sub &&
- test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+ test "$entry" = "$(index_at_path mod/sub)" &&
git -C mod/sub status &&
git update-index --refresh &&
git diff-files --quiet
@@ -442,13 +447,13 @@ test_expect_success 'mv issues a warning when section is not found in .gitmodule
git submodule update &&
git config -f .gitmodules --remove-section submodule.sub &&
git add .gitmodules &&
- entry="$(git ls-files --stage sub | cut -f 1)" &&
+ entry="$(index_at_path sub)" &&
echo "warning: Could not find section in .gitmodules where path=sub" >expect.err &&
mkdir mod &&
git mv sub mod/sub 2>actual.err &&
test_cmp expect.err actual.err &&
test_path_is_missing sub &&
- test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" &&
+ test "$entry" = "$(index_at_path mod/sub)" &&
git -C mod/sub status &&
git update-index --refresh &&
git diff-files --quiet
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index c975eb54d2..0ef7b78457 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -120,7 +120,7 @@ test_expect_success 'git clean with relative prefix' '
grep part3 |
sed -n -e "s|^Would remove ||p"
) &&
- verbose test "$would_clean" = ../src/part3.c
+ test "$would_clean" = ../src/part3.c
'
test_expect_success 'git clean with absolute path' '
@@ -133,7 +133,7 @@ test_expect_success 'git clean with absolute path' '
grep part3 |
sed -n -e "s|^Would remove ||p"
) &&
- verbose test "$would_clean" = ../src/part3.c
+ test "$would_clean" = ../src/part3.c
'
test_expect_success 'git clean with out of work tree relative path' '
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 6520346246..b77726c320 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -374,13 +374,16 @@ test_expect_success $PREREQ,!AUTOIDENT 'broken implicit ident aborts send-email'
)
'
-test_expect_success $PREREQ 'setup tocmd and cccmd scripts' '
+test_expect_success $PREREQ 'setup cmd scripts' '
write_script tocmd-sed <<-\EOF &&
sed -n -e "s/^tocmd--//p" "$1"
EOF
- write_script cccmd-sed <<-\EOF
+ write_script cccmd-sed <<-\EOF &&
sed -n -e "s/^cccmd--//p" "$1"
EOF
+ write_script headercmd-sed <<-\EOF
+ sed -n -e "s/^headercmd--//p" "$1"
+ EOF
'
test_expect_success $PREREQ 'tocmd works' '
@@ -410,6 +413,70 @@ test_expect_success $PREREQ 'cccmd works' '
grep "^ cccmd@example.com" msgtxt1
'
+test_expect_success $PREREQ 'headercmd works' '
+ clean_fake_sendmail &&
+ cp $patches headercmd.patch &&
+ echo "headercmd--X-Debbugs-CC: dummy@example.com" >>headercmd.patch &&
+ git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --header-cmd=./headercmd-sed \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ headercmd.patch \
+ &&
+ grep "^X-Debbugs-CC: dummy@example.com" msgtxt1
+'
+
+test_expect_success $PREREQ '--no-header-cmd works' '
+ clean_fake_sendmail &&
+ cp $patches headercmd.patch &&
+ echo "headercmd--X-Debbugs-CC: dummy@example.com" >>headercmd.patch &&
+ git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --header-cmd=./headercmd-sed \
+ --no-header-cmd \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ headercmd.patch \
+ &&
+ ! grep "^X-Debbugs-CC: dummy@example.com" msgtxt1
+'
+
+test_expect_success $PREREQ 'multiline fields are correctly unfolded' '
+ clean_fake_sendmail &&
+ cp $patches headercmd.patch &&
+ write_script headercmd-multiline <<-\EOF &&
+ echo "X-Debbugs-CC: someone@example.com
+FoldedField: This is a tale
+ best told using
+ multiple lines."
+ EOF
+ git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --header-cmd=./headercmd-multiline \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ headercmd.patch &&
+ grep "^FoldedField: This is a tale best told using multiple lines.$" msgtxt1
+'
+
+# Blank lines in the middle of the output of a command are invalid.
+test_expect_success $PREREQ 'malform output reported on blank lines in command output' '
+ clean_fake_sendmail &&
+ cp $patches headercmd.patch &&
+ write_script headercmd-malformed-output <<-\EOF &&
+ echo "X-Debbugs-CC: someone@example.com
+
+SomeOtherField: someone-else@example.com"
+ EOF
+ ! git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --header-cmd=./headercmd-malformed-output \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ headercmd.patch
+'
+
test_expect_success $PREREQ 'reject long lines' '
z8=zzzzzzzz &&
z64=$z8$z8$z8$z8$z8$z8$z8$z8 &&
@@ -540,7 +607,7 @@ test_expect_success $PREREQ "--validate respects relative core.hooksPath path" '
test_path_is_file my-hooks.ran &&
cat >expect <<-EOF &&
fatal: longline.patch: rejected by sendemail-validate hook
- fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch>'"'"' died with exit code 1
+ fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch> <header>'"'"' died with exit code 1
warning: no patches were sent
EOF
test_cmp expect actual
@@ -559,12 +626,35 @@ test_expect_success $PREREQ "--validate respects absolute core.hooksPath path" '
test_path_is_file my-hooks.ran &&
cat >expect <<-EOF &&
fatal: longline.patch: rejected by sendemail-validate hook
- fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch>'"'"' died with exit code 1
+ fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch> <header>'"'"' died with exit code 1
warning: no patches were sent
EOF
test_cmp expect actual
'
+test_expect_success $PREREQ "--validate hook supports header argument" '
+ write_script my-hooks/sendemail-validate <<-\EOF &&
+ if test "$#" -ge 2
+ then
+ grep "X-test-header: v1.0" "$2"
+ else
+ echo "No header arg passed"
+ exit 1
+ fi
+ EOF
+ test_config core.hooksPath "my-hooks" &&
+ rm -fr outdir &&
+ git format-patch \
+ --add-header="X-test-header: v1.0" \
+ -n HEAD^1 -o outdir &&
+ git send-email \
+ --dry-run \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ --validate \
+ outdir/000?-*.patch
+'
+
for enc in 7bit 8bit quoted-printable base64
do
test_expect_success $PREREQ "--transfer-encoding=$enc produces correct header" '
diff --git a/t/t9800-git-p4-basic.sh b/t/t9800-git-p4-basic.sh
index dc88d0e064..a4b3cb9492 100755
--- a/t/t9800-git-p4-basic.sh
+++ b/t/t9800-git-p4-basic.sh
@@ -330,7 +330,7 @@ test_expect_success 'initial import time from top change time' '
test_when_finished cleanup_git &&
(
cd "$git" &&
- gittime=$(git show -s --raw --pretty=format:%at HEAD) &&
+ gittime=$(git show -s --pretty=format:%at HEAD) &&
echo $p4time $gittime &&
test $p4time = $gittime
)
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index d6c0478d98..8835e16e81 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -405,40 +405,40 @@ test_expect_success '__gitdir - remote as argument' '
test_expect_success '__git_dequote - plain unquoted word' '
__git_dequote unquoted-word &&
- verbose test unquoted-word = "$dequoted_word"
+ test unquoted-word = "$dequoted_word"
'
# input: b\a\c\k\'\\\"s\l\a\s\h\es
# expected: back'\"slashes
test_expect_success '__git_dequote - backslash escaped' '
__git_dequote "b\a\c\k\\'\''\\\\\\\"s\l\a\s\h\es" &&
- verbose test "back'\''\\\"slashes" = "$dequoted_word"
+ test "back'\''\\\"slashes" = "$dequoted_word"
'
# input: sin'gle\' '"quo'ted
# expected: single\ "quoted
test_expect_success '__git_dequote - single quoted' '
__git_dequote "'"sin'gle\\\\' '\\\"quo'ted"'" &&
- verbose test '\''single\ "quoted'\'' = "$dequoted_word"
+ test '\''single\ "quoted'\'' = "$dequoted_word"
'
# input: dou"ble\\" "\"\quot"ed
# expected: double\ "\quoted
test_expect_success '__git_dequote - double quoted' '
__git_dequote '\''dou"ble\\" "\"\quot"ed'\'' &&
- verbose test '\''double\ "\quoted'\'' = "$dequoted_word"
+ test '\''double\ "\quoted'\'' = "$dequoted_word"
'
# input: 'open single quote
test_expect_success '__git_dequote - open single quote' '
__git_dequote "'\''open single quote" &&
- verbose test "open single quote" = "$dequoted_word"
+ test "open single quote" = "$dequoted_word"
'
# input: "open double quote
test_expect_success '__git_dequote - open double quote' '
__git_dequote "\"open double quote" &&
- verbose test "open double quote" = "$dequoted_word"
+ test "open double quote" = "$dequoted_word"
'
@@ -616,7 +616,7 @@ test_expect_success '__git_is_configured_remote' '
test_when_finished "git remote remove remote_2" &&
git remote add remote_2 git://remote_2 &&
(
- verbose __git_is_configured_remote remote_2 &&
+ __git_is_configured_remote remote_2 &&
test_must_fail __git_is_configured_remote non-existent
)
'
@@ -2596,30 +2596,30 @@ test_expect_success 'options with value' '
test_expect_success 'sourcing the completion script clears cached commands' '
(
__git_compute_all_commands &&
- verbose test -n "$__git_all_commands" &&
+ test -n "$__git_all_commands" &&
. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
- verbose test -z "$__git_all_commands"
+ test -z "$__git_all_commands"
)
'
test_expect_success 'sourcing the completion script clears cached merge strategies' '
(
__git_compute_merge_strategies &&
- verbose test -n "$__git_merge_strategies" &&
+ test -n "$__git_merge_strategies" &&
. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
- verbose test -z "$__git_merge_strategies"
+ test -z "$__git_merge_strategies"
)
'
test_expect_success 'sourcing the completion script clears cached --options' '
(
__gitcomp_builtin checkout &&
- verbose test -n "$__gitcomp_builtin_checkout" &&
+ test -n "$__gitcomp_builtin_checkout" &&
__gitcomp_builtin notes_edit &&
- verbose test -n "$__gitcomp_builtin_notes_edit" &&
+ test -n "$__gitcomp_builtin_notes_edit" &&
. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
- verbose test -z "$__gitcomp_builtin_checkout" &&
- verbose test -z "$__gitcomp_builtin_notes_edit"
+ test -z "$__gitcomp_builtin_checkout" &&
+ test -z "$__gitcomp_builtin_notes_edit"
)
'
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 999d46fafe..6e19ebc922 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -1227,15 +1227,6 @@ test_i18ngrep () {
return 1
}
-# Call any command "$@" but be more verbose about its
-# failure. This is handy for commands like "test" which do
-# not output anything when they fail.
-verbose () {
- "$@" && return 0
- echo >&4 "command failed: $(git rev-parse --sq-quote "$@")"
- return 1
-}
-
# Check if the file expected to be empty is indeed empty, and barfs
# otherwise.
diff --git a/trace2.c b/trace2.c
index 21264df71b..0efc4e7b95 100644
--- a/trace2.c
+++ b/trace2.c
@@ -2,6 +2,7 @@
#include "config.h"
#include "json-writer.h"
#include "quote.h"
+#include "repository.h"
#include "run-command.h"
#include "sigchain.h"
#include "thread-utils.h"
diff --git a/trace2/tr2_tgt_event.c b/trace2/tr2_tgt_event.c
index 9e7aab6d51..2af53e5d4d 100644
--- a/trace2/tr2_tgt_event.c
+++ b/trace2/tr2_tgt_event.c
@@ -1,6 +1,7 @@
#include "git-compat-util.h"
#include "config.h"
#include "json-writer.h"
+#include "repository.h"
#include "run-command.h"
#include "version.h"
#include "trace2/tr2_dst.h"
diff --git a/trace2/tr2_tgt_normal.c b/trace2/tr2_tgt_normal.c
index 8672c2c2d0..1ebfb464d5 100644
--- a/trace2/tr2_tgt_normal.c
+++ b/trace2/tr2_tgt_normal.c
@@ -1,5 +1,6 @@
#include "git-compat-util.h"
#include "config.h"
+#include "repository.h"
#include "run-command.h"
#include "quote.h"
#include "version.h"
diff --git a/trace2/tr2_tgt_perf.c b/trace2/tr2_tgt_perf.c
index 3f2b2d5311..328e483a05 100644
--- a/trace2/tr2_tgt_perf.c
+++ b/trace2/tr2_tgt_perf.c
@@ -1,5 +1,6 @@
#include "git-compat-util.h"
#include "config.h"
+#include "repository.h"
#include "run-command.h"
#include "quote.h"
#include "version.h"
diff --git a/tree-diff.c b/tree-diff.c
index 69031d7cba..20bb15f38d 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -1,10 +1,24 @@
/*
* Helper functions for tree diff generation
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "diff.h"
#include "diffcore.h"
#include "tree.h"
+#include "tree-walk.h"
+
+/*
+ * Some mode bits are also used internally for computations.
+ *
+ * They *must* not overlap with any valid modes, and they *must* not be emitted
+ * to outside world - i.e. appear on disk or network. In other words, it's just
+ * temporary fields, which we internally use, but they have to stay in-house.
+ *
+ * ( such approach is valid, as standard S_IF* fits into 16 bits, and in Git
+ * codebase mode is `unsigned int` which is assumed to be at least 32 bits )
+ */
+
+#define S_DIFFTREE_IFXMIN_NEQ 0x80000000
/*
* internal mode marker, saying a tree entry != entry of tp[imin]
diff --git a/tree-walk.c b/tree-walk.c
index 2993c48c2f..d3c48e06df 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "tree-walk.h"
#include "alloc.h"
#include "dir.h"
diff --git a/tree-walk.h b/tree-walk.h
index 25fe27e352..01a9d8eb44 100644
--- a/tree-walk.h
+++ b/tree-walk.h
@@ -1,9 +1,10 @@
#ifndef TREE_WALK_H
#define TREE_WALK_H
-#include "hash.h"
+#include "hash-ll.h"
struct index_state;
+struct repository;
#define MAX_TRAVERSE_TREES 8
diff --git a/tree.c b/tree.c
index e9d51ce2e0..0dd2029a8a 100644
--- a/tree.c
+++ b/tree.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "cache-tree.h"
#include "hex.h"
#include "tree.h"
@@ -94,14 +94,72 @@ int read_tree(struct repository *r,
return ret;
}
-int cmp_cache_name_compare(const void *a_, const void *b_)
+int base_name_compare(const char *name1, size_t len1, int mode1,
+ const char *name2, size_t len2, int mode2)
{
- const struct cache_entry *ce1, *ce2;
+ unsigned char c1, c2;
+ size_t len = len1 < len2 ? len1 : len2;
+ int cmp;
+
+ cmp = memcmp(name1, name2, len);
+ if (cmp)
+ return cmp;
+ c1 = name1[len];
+ c2 = name2[len];
+ if (!c1 && S_ISDIR(mode1))
+ c1 = '/';
+ if (!c2 && S_ISDIR(mode2))
+ c2 = '/';
+ return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0;
+}
+
+/*
+ * df_name_compare() is identical to base_name_compare(), except it
+ * compares conflicting directory/file entries as equal. Note that
+ * while a directory name compares as equal to a regular file, they
+ * then individually compare _differently_ to a filename that has
+ * a dot after the basename (because '\0' < '.' < '/').
+ *
+ * This is used by routines that want to traverse the git namespace
+ * but then handle conflicting entries together when possible.
+ */
+int df_name_compare(const char *name1, size_t len1, int mode1,
+ const char *name2, size_t len2, int mode2)
+{
+ unsigned char c1, c2;
+ size_t len = len1 < len2 ? len1 : len2;
+ int cmp;
+
+ cmp = memcmp(name1, name2, len);
+ if (cmp)
+ return cmp;
+ /* Directories and files compare equal (same length, same name) */
+ if (len1 == len2)
+ return 0;
+ c1 = name1[len];
+ if (!c1 && S_ISDIR(mode1))
+ c1 = '/';
+ c2 = name2[len];
+ if (!c2 && S_ISDIR(mode2))
+ c2 = '/';
+ if (c1 == '/' && !c2)
+ return 0;
+ if (c2 == '/' && !c1)
+ return 0;
+ return c1 - c2;
+}
- ce1 = *((const struct cache_entry **)a_);
- ce2 = *((const struct cache_entry **)b_);
- return cache_name_stage_compare(ce1->name, ce1->ce_namelen, ce_stage(ce1),
- ce2->name, ce2->ce_namelen, ce_stage(ce2));
+int name_compare(const char *name1, size_t len1, const char *name2, size_t len2)
+{
+ size_t min_len = (len1 < len2) ? len1 : len2;
+ int cmp = memcmp(name1, name2, min_len);
+ if (cmp)
+ return cmp;
+ if (len1 < len2)
+ return -1;
+ if (len1 > len2)
+ return 1;
+ return 0;
}
struct tree *lookup_tree(struct repository *r, const struct object_id *oid)
diff --git a/tree.h b/tree.h
index 6efff003e2..1b5ecbda6b 100644
--- a/tree.h
+++ b/tree.h
@@ -3,6 +3,7 @@
#include "object.h"
+struct pathspec;
struct repository;
struct strbuf;
@@ -28,7 +29,15 @@ void free_tree_buffer(struct tree *tree);
/* Parses and returns the tree in the given ent, chasing tags and commits. */
struct tree *parse_tree_indirect(const struct object_id *oid);
-int cmp_cache_name_compare(const void *a_, const void *b_);
+/*
+ * Functions for comparing pathnames
+ */
+int base_name_compare(const char *name1, size_t len1, int mode1,
+ const char *name2, size_t len2, int mode2);
+int df_name_compare(const char *name1, size_t len1, int mode1,
+ const char *name2, size_t len2, int mode2);
+int name_compare(const char *name1, size_t len1,
+ const char *name2, size_t len2);
#define READ_TREE_RECURSIVE 1
typedef int (*read_tree_fn_t)(const struct object_id *, struct strbuf *, const char *, unsigned int, void *);
diff --git a/unpack-trees.c b/unpack-trees.c
index c0732aa0c2..e8c32a40dc 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -18,6 +18,7 @@
#include "sparse-index.h"
#include "submodule.h"
#include "submodule-config.h"
+#include "symlinks.h"
#include "trace2.h"
#include "fsmonitor.h"
#include "object-store.h"
diff --git a/versioncmp.c b/versioncmp.c
index 7498da96e0..74cc7c43f0 100644
--- a/versioncmp.c
+++ b/versioncmp.c
@@ -1,6 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "string-list.h"
+#include "versioncmp.h"
/*
* versioncmp(): copied from string/strverscmp.c in glibc commit
diff --git a/versioncmp.h b/versioncmp.h
new file mode 100644
index 0000000000..879b510e82
--- /dev/null
+++ b/versioncmp.h
@@ -0,0 +1,6 @@
+#ifndef VERSIONCMP_H
+#define VERSIONCMP_H
+
+int versioncmp(const char *s1, const char *s2);
+
+#endif /* VERSIONCMP_H */
diff --git a/wrapper.c b/wrapper.c
index c130d7518b..67f5f5dbe1 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -1,10 +1,13 @@
/*
* Various trivial helper wrappers around standard functions
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "config.h"
#include "gettext.h"
+#include "object.h"
+#include "repository.h"
+#include "strbuf.h"
#include "trace2.h"
#include "wrapper.h"
diff --git a/ws.c b/ws.c
index da3d0e28cb..d356d4ec9e 100644
--- a/ws.c
+++ b/ws.c
@@ -3,8 +3,12 @@
*
* Copyright (c) 2007 Junio C Hamano
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "attr.h"
+#include "strbuf.h"
+#include "ws.h"
+
+unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
static struct whitespace_rule {
const char *rule_name;
diff --git a/ws.h b/ws.h
new file mode 100644
index 0000000000..5ba676c559
--- /dev/null
+++ b/ws.h
@@ -0,0 +1,33 @@
+#ifndef WS_H
+#define WS_H
+
+struct index_state;
+struct strbuf;
+
+/*
+ * whitespace rules.
+ * used by both diff and apply
+ * last two digits are tab width
+ */
+#define WS_BLANK_AT_EOL 0100
+#define WS_SPACE_BEFORE_TAB 0200
+#define WS_INDENT_WITH_NON_TAB 0400
+#define WS_CR_AT_EOL 01000
+#define WS_BLANK_AT_EOF 02000
+#define WS_TAB_IN_INDENT 04000
+#define WS_TRAILING_SPACE (WS_BLANK_AT_EOL|WS_BLANK_AT_EOF)
+#define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB|8)
+#define WS_TAB_WIDTH_MASK 077
+/* All WS_* -- when extended, adapt diff.c emit_symbol */
+#define WS_RULE_MASK 07777
+extern unsigned whitespace_rule_cfg;
+unsigned whitespace_rule(struct index_state *, const char *);
+unsigned parse_whitespace_rule(const char *);
+unsigned ws_check(const char *line, int len, unsigned ws_rule);
+void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws);
+char *whitespace_error_string(unsigned ws);
+void ws_fix_copy(struct strbuf *, const char *, int, unsigned, int *);
+int ws_blank_line(const char *line, int len);
+#define ws_tab_width(rule) ((rule) & WS_TAB_WIDTH_MASK)
+
+#endif /* WS_H */
diff --git a/wt-status.c b/wt-status.c
index 97b9c1c035..068b76ef6d 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -22,6 +22,7 @@
#include "strbuf.h"
#include "trace.h"
#include "trace2.h"
+#include "tree.h"
#include "utf8.h"
#include "worktree.h"
#include "lockfile.h"
diff --git a/xdiff-interface.h b/xdiff-interface.h
index 3750794afe..733c364d26 100644
--- a/xdiff-interface.h
+++ b/xdiff-interface.h
@@ -1,7 +1,7 @@
#ifndef XDIFF_INTERFACE_H
#define XDIFF_INTERFACE_H
-#include "hash.h"
+#include "hash-ll.h"
#include "xdiff/xdiff.h"
/*