summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/Makefile6
-rw-r--r--Documentation/RelNotes/2.30.9.txt43
-rw-r--r--Documentation/RelNotes/2.31.8.txt6
-rw-r--r--Documentation/RelNotes/2.32.7.txt7
-rw-r--r--Documentation/RelNotes/2.33.8.txt7
-rw-r--r--Documentation/RelNotes/2.34.8.txt7
-rw-r--r--Documentation/RelNotes/2.35.8.txt7
-rw-r--r--Documentation/RelNotes/2.36.6.txt7
-rw-r--r--Documentation/RelNotes/2.37.7.txt7
-rw-r--r--Documentation/RelNotes/2.38.5.txt8
-rw-r--r--Documentation/RelNotes/2.39.3.txt12
-rw-r--r--Documentation/RelNotes/2.40.1.txt8
-rw-r--r--Documentation/RelNotes/2.41.0.txt118
-rw-r--r--Documentation/blame-options.txt8
-rw-r--r--Documentation/config/feature.txt3
-rw-r--r--Documentation/config/gc.txt12
-rw-r--r--Documentation/config/pack.txt8
-rw-r--r--Documentation/config/sendemail.txt1
-rwxr-xr-xDocumentation/doc-diff2
-rw-r--r--Documentation/git-branch.txt4
-rw-r--r--Documentation/git-checkout.txt54
-rw-r--r--Documentation/git-clone.txt5
-rw-r--r--Documentation/git-credential.txt6
-rw-r--r--Documentation/git-for-each-ref.txt4
-rw-r--r--Documentation/git-format-patch.txt3
-rw-r--r--Documentation/git-gc.txt12
-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-tag.txt4
-rw-r--r--Documentation/git.txt6
-rw-r--r--Documentation/gitattributes.txt59
-rw-r--r--Documentation/gitformat-pack.txt4
-rw-r--r--Documentation/githooks.txt49
-rw-r--r--Documentation/gitignore.txt4
-rw-r--r--Documentation/gittutorial.txt129
-rw-r--r--Documentation/manpage-normal.xsl16
-rw-r--r--Makefile2
-rw-r--r--add-interactive.c1
-rw-r--r--add-patch.c3
-rw-r--r--alloc.c1
-rw-r--r--apply.c19
-rw-r--r--apply.h2
-rw-r--r--archive-tar.c1
-rw-r--r--archive-zip.c3
-rw-r--r--archive.c78
-rw-r--r--archive.h3
-rw-r--r--attr.c1
-rw-r--r--banned.h4
-rw-r--r--base85.c3
-rw-r--r--base85.h7
-rw-r--r--bisect.c3
-rw-r--r--blame.c10
-rw-r--r--bloom.c1
-rw-r--r--branch.c31
-rw-r--r--branch.h8
-rw-r--r--builtin/add.c2
-rw-r--r--builtin/am.c4
-rw-r--r--builtin/apply.c1
-rw-r--r--builtin/archive.c1
-rw-r--r--builtin/bisect.c3
-rw-r--r--builtin/blame.c2
-rw-r--r--builtin/branch.c79
-rw-r--r--builtin/bugreport.c2
-rw-r--r--builtin/bundle.c2
-rw-r--r--builtin/cat-file.c3
-rw-r--r--builtin/check-attr.c2
-rw-r--r--builtin/check-ignore.c1
-rw-r--r--builtin/checkout-index.c1
-rw-r--r--builtin/checkout.c4
-rw-r--r--builtin/clean.c1
-rw-r--r--builtin/clone.c17
-rw-r--r--builtin/commit-graph.c1
-rw-r--r--builtin/commit-tree.c1
-rw-r--r--builtin/commit.c3
-rw-r--r--builtin/config.c2
-rw-r--r--builtin/credential-cache--daemon.c4
-rw-r--r--builtin/credential-cache.c1
-rw-r--r--builtin/credential-store.c1
-rw-r--r--builtin/describe.c3
-rw-r--r--builtin/diagnose.c1
-rw-r--r--builtin/diff-files.c4
-rw-r--r--builtin/diff-tree.c1
-rw-r--r--builtin/diff.c1
-rw-r--r--builtin/difftool.c2
-rw-r--r--builtin/fast-export.c1
-rw-r--r--builtin/fast-import.c2
-rw-r--r--builtin/fetch-pack.c1
-rw-r--r--builtin/fetch.c7
-rw-r--r--builtin/for-each-ref.c7
-rw-r--r--builtin/for-each-repo.c2
-rw-r--r--builtin/fsck.c42
-rw-r--r--builtin/fsmonitor--daemon.c1
-rw-r--r--builtin/gc.c15
-rw-r--r--builtin/get-tar-commit-id.c2
-rw-r--r--builtin/grep.c3
-rw-r--r--builtin/hash-object.c1
-rw-r--r--builtin/help.c2
-rw-r--r--builtin/index-pack.c8
-rw-r--r--builtin/init-db.c3
-rw-r--r--builtin/log.c5
-rw-r--r--builtin/ls-files.c2
-rw-r--r--builtin/ls-remote.c1
-rw-r--r--builtin/ls-tree.c1
-rw-r--r--builtin/merge-base.c1
-rw-r--r--builtin/merge-index.c1
-rw-r--r--builtin/merge-recursive.c4
-rw-r--r--builtin/merge-tree.c5
-rw-r--r--builtin/merge.c3
-rw-r--r--builtin/mktag.c1
-rw-r--r--builtin/mv.c3
-rw-r--r--builtin/name-rev.c8
-rw-r--r--builtin/notes.c2
-rw-r--r--builtin/pack-objects.c16
-rw-r--r--builtin/prune.c2
-rw-r--r--builtin/pull.c4
-rw-r--r--builtin/push.c11
-rw-r--r--builtin/range-diff.c1
-rw-r--r--builtin/read-tree.c2
-rw-r--r--builtin/rebase.c3
-rw-r--r--builtin/receive-pack.c6
-rw-r--r--builtin/repack.c65
-rw-r--r--builtin/replace.c3
-rw-r--r--builtin/rerere.c1
-rw-r--r--builtin/reset.c4
-rw-r--r--builtin/rev-list.c2
-rw-r--r--builtin/rev-parse.c1
-rw-r--r--builtin/rm.c3
-rw-r--r--builtin/show-branch.c3
-rw-r--r--builtin/show-index.c2
-rw-r--r--builtin/show-ref.c1
-rw-r--r--builtin/sparse-checkout.c2
-rw-r--r--builtin/stash.c1
-rw-r--r--builtin/submodule--helper.c2
-rw-r--r--builtin/tag.c9
-rw-r--r--builtin/unpack-file.c1
-rw-r--r--builtin/unpack-objects.c1
-rw-r--r--builtin/update-index.c4
-rw-r--r--builtin/update-ref.c3
-rw-r--r--builtin/update-server-info.c1
-rw-r--r--builtin/upload-archive.c1
-rw-r--r--builtin/var.c2
-rw-r--r--builtin/verify-commit.c1
-rw-r--r--builtin/verify-tag.c1
-rw-r--r--builtin/worktree.c4
-rw-r--r--builtin/write-tree.c1
-rw-r--r--bulk-checkin.c4
-rw-r--r--bundle-uri.c7
-rw-r--r--bundle.c2
-rw-r--r--cache-tree.c3
-rw-r--r--cache.h473
-rw-r--r--chdir-notify.c4
-rw-r--r--checkout.c5
-rw-r--r--checkout.h2
-rw-r--r--chunk-format.c1
-rw-r--r--chunk-format.h2
-rwxr-xr-xci/run-build-and-tests.sh2
-rw-r--r--color.c5
-rw-r--r--column.c3
-rw-r--r--combine-diff.c6
-rw-r--r--commit-graph.c5
-rw-r--r--commit.c61
-rw-r--r--commit.h11
-rw-r--r--common-main.c5
-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/fsmonitor/fsm-listen-win32.c1
-rw-r--r--compat/mingw.c2
-rw-r--r--compat/pread.c1
-rw-r--r--compat/precompose_utf8.c1
-rw-r--r--compat/simple-ipc/ipc-unix-socket.c3
-rw-r--r--compat/simple-ipc/ipc-win32.c2
-rw-r--r--compat/win32/trace2_win32_process_info.c2
-rw-r--r--config.c45
-rw-r--r--connect.c32
-rw-r--r--connect.h4
-rw-r--r--contrib/completion/git-prompt.sh2
-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
-rwxr-xr-xcontrib/subtree/git-subtree.sh4
-rw-r--r--convert.c4
-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.c4
-rw-r--r--date.c18
-rw-r--r--date.h1
-rw-r--r--delta-islands.c2
-rwxr-xr-xdetect-compiler10
-rw-r--r--diagnose.c2
-rw-r--r--diff-lib.c3
-rw-r--r--diff-no-index.c2
-rw-r--r--diff.c43
-rw-r--r--diff.h1
-rw-r--r--diffcore.h2
-rw-r--r--dir.c5
-rw-r--r--dir.h15
-rw-r--r--editor.c35
-rw-r--r--editor.h34
-rw-r--r--entry.c1
-rw-r--r--environment.c7
-rw-r--r--exec-cmd.c3
-rw-r--r--fetch-pack.c8
-rw-r--r--fmt-merge-msg.c3
-rw-r--r--fsck.c3
-rw-r--r--fsmonitor--daemon.h1
-rw-r--r--fsmonitor-ipc.c1
-rw-r--r--fsmonitor.c1
-rw-r--r--fsmonitor.h1
-rw-r--r--gettext.c4
-rw-r--r--gettext.h6
-rw-r--r--git-compat-util.h6
-rwxr-xr-xgit-send-email.perl202
-rw-r--r--git-zlib.c (renamed from zlib.c)3
-rw-r--r--git-zlib.h28
-rw-r--r--git.c3
-rwxr-xr-xgitk-git/gitk36
-rw-r--r--gpg-interface.c4
-rw-r--r--grep.c2
-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-backend.c3
-rw-r--r--http-fetch.c2
-rw-r--r--http-push.c4
-rw-r--r--http-walker.c2
-rw-r--r--http.c2
-rw-r--r--http.h4
-rw-r--r--khash.h1
-rw-r--r--line-log.c1
-rw-r--r--list-objects-filter.c3
-rw-r--r--list-objects.c2
-rw-r--r--ll-merge.c4
-rw-r--r--log-tree.c4
-rw-r--r--ls-refs.c1
-rw-r--r--mailmap.c3
-rw-r--r--mailmap.h3
-rw-r--r--match-trees.c3
-rw-r--r--match-trees.h10
-rw-r--r--merge-ort-wrappers.c2
-rw-r--r--merge-ort.c13
-rw-r--r--merge-ort.h2
-rw-r--r--merge-recursive.c4
-rw-r--r--merge.c1
-rw-r--r--midx.c9
-rw-r--r--name-hash.c1
-rw-r--r--negotiator/default.c40
-rw-r--r--negotiator/skipping.c23
-rw-r--r--notes-cache.c1
-rw-r--r--notes-merge.c6
-rw-r--r--notes-utils.c1
-rw-r--r--notes.c9
-rw-r--r--object-file.c11
-rw-r--r--object-file.h131
-rw-r--r--object-name.c4
-rw-r--r--object-name.h121
-rw-r--r--object-store.h9
-rw-r--r--object.c1
-rw-r--r--object.h47
-rw-r--r--oidmap.c1
-rw-r--r--oidtree.h2
-rw-r--r--pack-bitmap-write.c4
-rw-r--r--pack-bitmap.c76
-rw-r--r--pack-bitmap.h2
-rw-r--r--pack-check.c3
-rw-r--r--pack-mtimes.c3
-rw-r--r--pack-revindex.c59
-rw-r--r--pack-revindex.h22
-rw-r--r--pack-write.c19
-rw-r--r--packfile.c7
-rw-r--r--packfile.h16
-rw-r--r--pager.c6
-rw-r--r--pager.h17
-rw-r--r--parallel-checkout.c2
-rw-r--r--parse-options-cb.c3
-rw-r--r--parse-options.c1
-rw-r--r--path.c1
-rw-r--r--pathspec.c2
-rw-r--r--pkt-line.c4
-rw-r--r--pkt-line.h2
-rw-r--r--preload-index.c2
-rw-r--r--pretty.c3
-rw-r--r--progress.c5
-rw-r--r--promisor-remote.c3
-rw-r--r--protocol-caps.c2
-rw-r--r--protocol.c3
-rw-r--r--protocol.h21
-rw-r--r--quote.c3
-rw-r--r--quote.h2
-rw-r--r--range-diff.c4
-rw-r--r--read-cache.c86
-rw-r--r--rebase-interactive.c5
-rw-r--r--ref-filter.c6
-rw-r--r--reflog.c2
-rw-r--r--refs.c4
-rw-r--r--refs/debug.c1
-rw-r--r--refs/files-backend.c3
-rw-r--r--refs/packed-backend.c4
-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--remote-curl.c1
-rw-r--r--remote.c3
-rw-r--r--repo-settings.c5
-rw-r--r--repository.c1
-rw-r--r--repository.h2
-rw-r--r--rerere.c4
-rw-r--r--reset.c1
-rw-r--r--reset.h2
-rw-r--r--resolve-undo.c1
-rw-r--r--resolve-undo.h7
-rw-r--r--revision.c5
-rw-r--r--revision.h1
-rw-r--r--run-command.c3
-rw-r--r--scalar.c3
-rw-r--r--send-pack.c4
-rw-r--r--sequencer.c11
-rw-r--r--server-info.c4
-rw-r--r--server-info.h7
-rw-r--r--setup.c6
-rw-r--r--shallow.c1
-rw-r--r--sideband.c3
-rw-r--r--split-index.c3
-rw-r--r--split-index.h2
-rw-r--r--strbuf.c32
-rw-r--r--strbuf.h24
-rw-r--r--streaming.c4
-rw-r--r--string-list.c13
-rw-r--r--string-list.h12
-rw-r--r--submodule-config.c4
-rw-r--r--submodule.c3
-rw-r--r--symlinks.c3
-rw-r--r--symlinks.h28
-rw-r--r--t/README2
-rw-r--r--t/annotate-tests.sh11
-rw-r--r--t/helper/test-bloom.c1
-rw-r--r--t/helper/test-cache-tree.c1
-rw-r--r--t/helper/test-chmtime.c2
-rw-r--r--t/helper/test-ctype.c2
-rw-r--r--t/helper/test-date.c6
-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-fast-rebase.c1
-rw-r--r--t/helper/test-fsmonitor-client.c1
-rw-r--r--t/helper/test-hashmap.c22
-rw-r--r--t/helper/test-json-writer.c76
-rw-r--r--t/helper/test-lazy-init-name-hash.c2
-rw-r--r--t/helper/test-match-trees.c4
-rw-r--r--t/helper/test-mergesort.c3
-rw-r--r--t/helper/test-oid-array.c2
-rw-r--r--t/helper/test-oidmap.c23
-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.c2
-rw-r--r--t/helper/test-reach.c2
-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.c6
-rw-r--r--t/helper/test-submodule-config.c4
-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/perf/p2000-sparse-operations.sh5
-rwxr-xr-xt/perf/p5312-pack-bitmaps-revs.sh3
-rwxr-xr-xt/t0020-crlf.sh38
-rwxr-xr-xt/t0035-safe-bare-repository.sh32
-rwxr-xr-xt/t0063-string-list.sh51
-rwxr-xr-xt/t0300-credentials.sh20
-rwxr-xr-xt/t0301-credential-cache.sh1
-rwxr-xr-xt/t1092-sparse-checkout-compatibility.sh91
-rwxr-xr-xt/t1300-config.sh73
-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/t2024-checkout-dwim.sh7
-rwxr-xr-xt/t3200-branch.sh29
-rwxr-xr-xt/t3202-show-branch.sh18
-rwxr-xr-xt/t3203-branch-output.sh24
-rwxr-xr-xt/t3427-rebase-subtree.sh12
-rwxr-xr-xt/t3501-revert-cherry-pick.sh18
-rwxr-xr-xt/t4014-format-patch.sh5
-rwxr-xr-xt/t4022-diff-rewrite.sh2
-rwxr-xr-xt/t4034-diff-words.sh4
-rwxr-xr-xt/t4047-diff-dirstat.sh2
-rwxr-xr-xt/t4062-diff-pickaxe.sh2
-rwxr-xr-xt/t4115-apply-symlink.sh15
-rwxr-xr-xt/t4212-log-corrupt.sh51
-rwxr-xr-xt/t4300-merge-tree.sh18
-rwxr-xr-xt/t5000-tar-tree.sh13
-rwxr-xr-xt/t5001-archive-attr.sh16
-rwxr-xr-xt/t5300-pack-object.sh135
-rwxr-xr-xt/t5304-prune.sh44
-rwxr-xr-xt/t5319-multi-pack-index.sh12
-rwxr-xr-xt/t5325-reverse-index.sh90
-rwxr-xr-xt/t5326-multi-pack-bitmaps.sh44
-rwxr-xr-xt/t5331-pack-objects-stdin.sh240
-rwxr-xr-xt/t5512-ls-remote.sh156
-rwxr-xr-xt/t5523-push-upstream.sh12
-rwxr-xr-xt/t5543-atomic-push.sh5
-rwxr-xr-xt/t5583-push-branches.sh115
-rwxr-xr-xt/t5604-clone-reference.sh2
-rwxr-xr-xt/t6006-rev-list-format.sh2
-rwxr-xr-xt/t6300-for-each-ref.sh8
-rwxr-xr-xt/t6500-gc.sh133
-rwxr-xr-xt/t6501-freshen-objects.sh12
-rwxr-xr-xt/t7001-mv.sh37
-rwxr-xr-xt/t7004-tag.sh16
-rwxr-xr-xt/t7300-clean.sh4
-rwxr-xr-xt/t7510-signed-commit.sh21
-rwxr-xr-xt/t7700-repack.sh17
-rwxr-xr-xt/t7703-repack-geometric.sh164
-rwxr-xr-xt/t9001-send-email.sh129
-rwxr-xr-xt/t9300-fast-import.sh13
-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--tag.c3
-rwxr-xr-xtemplates/hooks--sendemail-validate.sample77
-rw-r--r--tmp-objdir.c3
-rw-r--r--trace.c3
-rw-r--r--trace2.c2
-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--transport-helper.c3
-rw-r--r--transport.c7
-rw-r--r--tree-diff.c16
-rw-r--r--tree-walk.c4
-rw-r--r--tree-walk.h3
-rw-r--r--tree.c73
-rw-r--r--tree.h11
-rw-r--r--unpack-trees.c3
-rw-r--r--unpack-trees.h1
-rw-r--r--upload-pack.c7
-rw-r--r--userdiff.c31
-rw-r--r--userdiff.h1
-rw-r--r--versioncmp.c3
-rw-r--r--versioncmp.h6
-rw-r--r--walker.c2
-rw-r--r--wrapper.c6
-rw-r--r--ws.c6
-rw-r--r--ws.h33
-rw-r--r--wt-status.c5
-rw-r--r--xdiff-interface.h2
474 files changed, 4903 insertions, 2629 deletions
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 5cd35df61c..b629176d7d 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -144,14 +144,16 @@ man5dir = $(mandir)/man5
man7dir = $(mandir)/man7
# DESTDIR =
+GIT_DATE := $(shell git show --quiet --pretty='%as')
+
ASCIIDOC = asciidoc
ASCIIDOC_EXTRA =
ASCIIDOC_HTML = xhtml11
ASCIIDOC_DOCBOOK = docbook
ASCIIDOC_CONF = -f asciidoc.conf
ASCIIDOC_COMMON = $(ASCIIDOC) $(ASCIIDOC_EXTRA) $(ASCIIDOC_CONF) \
- -amanversion=$(GIT_VERSION) \
- -amanmanual='Git Manual' -amansource='Git'
+ -amanmanual='Git Manual' -amansource='Git $(GIT_VERSION)' \
+ -arevdate='$(GIT_DATE)'
ASCIIDOC_DEPS = asciidoc.conf GIT-ASCIIDOCFLAGS
TXT_TO_HTML = $(ASCIIDOC_COMMON) -b $(ASCIIDOC_HTML)
TXT_TO_XML = $(ASCIIDOC_COMMON) -b $(ASCIIDOC_DOCBOOK)
diff --git a/Documentation/RelNotes/2.30.9.txt b/Documentation/RelNotes/2.30.9.txt
new file mode 100644
index 0000000000..708d626ce6
--- /dev/null
+++ b/Documentation/RelNotes/2.30.9.txt
@@ -0,0 +1,43 @@
+Git v2.30.9 Release Notes
+=========================
+
+This release addresses the security issues CVE-2023-25652,
+CVE-2023-25815, and CVE-2023-29007.
+
+
+Fixes since v2.30.8
+-------------------
+
+ * CVE-2023-25652:
+
+ By feeding specially crafted input to `git apply --reject`, a
+ path outside the working tree can be overwritten with partially
+ controlled contents (corresponding to the rejected hunk(s) from
+ the given patch).
+
+ * CVE-2023-25815:
+
+ When Git is compiled with runtime prefix support and runs without
+ translated messages, it still used the gettext machinery to
+ display messages, which subsequently potentially looked for
+ translated messages in unexpected places. This allowed for
+ malicious placement of crafted messages.
+
+ * CVE-2023-29007:
+
+ When renaming or deleting a section from a configuration file,
+ certain malicious configuration values may be misinterpreted as
+ the beginning of a new configuration section, leading to arbitrary
+ configuration injection.
+
+Credit for finding CVE-2023-25652 goes to Ry0taK, and the fix was
+developed by Taylor Blau, Junio C Hamano and Johannes Schindelin,
+with the help of Linus Torvalds.
+
+Credit for finding CVE-2023-25815 goes to Maxime Escourbiac and
+Yassine BENGANA of Michelin, and the fix was developed by Johannes
+Schindelin.
+
+Credit for finding CVE-2023-29007 goes to André Baptista and Vítor Pinho
+of Ethiack, and the fix was developed by Taylor Blau, and Johannes
+Schindelin, with help from Jeff King, and Patrick Steinhardt.
diff --git a/Documentation/RelNotes/2.31.8.txt b/Documentation/RelNotes/2.31.8.txt
new file mode 100644
index 0000000000..0aa3080780
--- /dev/null
+++ b/Documentation/RelNotes/2.31.8.txt
@@ -0,0 +1,6 @@
+Git v2.31.8 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9 to address the
+security issues CVE-2023-25652, CVE-2023-25815, and CVE-2023-29007;
+see the release notes for that version for details.
diff --git a/Documentation/RelNotes/2.32.7.txt b/Documentation/RelNotes/2.32.7.txt
new file mode 100644
index 0000000000..7bb35388b5
--- /dev/null
+++ b/Documentation/RelNotes/2.32.7.txt
@@ -0,0 +1,7 @@
+Git v2.32.7 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9 and v2.31.8 to
+address the security issues CVE-2023-25652, CVE-2023-25815, and
+CVE-2023-29007; see the release notes for these versions for
+details.
diff --git a/Documentation/RelNotes/2.33.8.txt b/Documentation/RelNotes/2.33.8.txt
new file mode 100644
index 0000000000..d8cf4c7f3a
--- /dev/null
+++ b/Documentation/RelNotes/2.33.8.txt
@@ -0,0 +1,7 @@
+Git v2.33.8 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9, v2.31.8 and
+v2.32.7 to address the security issues CVE-2023-25652,
+CVE-2023-25815, and CVE-2023-29007; see the release notes for these
+versions for details.
diff --git a/Documentation/RelNotes/2.34.8.txt b/Documentation/RelNotes/2.34.8.txt
new file mode 100644
index 0000000000..2b5bd7d9a3
--- /dev/null
+++ b/Documentation/RelNotes/2.34.8.txt
@@ -0,0 +1,7 @@
+Git v2.34.8 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9, v2.31.8,
+v2.32.7 and v2.33.8 to address the security issues CVE-2023-25652,
+CVE-2023-25815, and CVE-2023-29007; see the release notes for these
+versions for details.
diff --git a/Documentation/RelNotes/2.35.8.txt b/Documentation/RelNotes/2.35.8.txt
new file mode 100644
index 0000000000..3c9c094c2b
--- /dev/null
+++ b/Documentation/RelNotes/2.35.8.txt
@@ -0,0 +1,7 @@
+Git v2.35.8 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8 and v2.34.8 to address the security issues
+CVE-2023-25652, CVE-2023-25815, and CVE-2023-29007; see the release
+notes for these versions for details.
diff --git a/Documentation/RelNotes/2.36.6.txt b/Documentation/RelNotes/2.36.6.txt
new file mode 100644
index 0000000000..e1edebcc43
--- /dev/null
+++ b/Documentation/RelNotes/2.36.6.txt
@@ -0,0 +1,7 @@
+Git v2.36.6 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8, v2.34.8 and v2.35.8 to address the security issues
+CVE-2023-25652, CVS-2023-25815, and CVE-2023-29007; see the release
+notes for these versions for details.
diff --git a/Documentation/RelNotes/2.37.7.txt b/Documentation/RelNotes/2.37.7.txt
new file mode 100644
index 0000000000..4b8165f4b5
--- /dev/null
+++ b/Documentation/RelNotes/2.37.7.txt
@@ -0,0 +1,7 @@
+Git v2.37.7 Release Notes
+=========================
+
+This release merges up the fix that appears in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8, v2.34.8, v2.35.8 and v2.36.6 to address the
+security issues CVE-2023-25652, CVE-2023-25815, and CVE-2023-29007;
+see the release notes for these versions for details.
diff --git a/Documentation/RelNotes/2.38.5.txt b/Documentation/RelNotes/2.38.5.txt
new file mode 100644
index 0000000000..2d1f3b1249
--- /dev/null
+++ b/Documentation/RelNotes/2.38.5.txt
@@ -0,0 +1,8 @@
+Git v2.38.5 Release Notes
+=========================
+
+This release merges up the fix that appears in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8, v2.34.8, v2.35.8, v2.36.6 and v2.37.7 to address
+the security issues CVE-2023-25652, CVE-2023-25815, and
+CVE-2023-29007; see the release notes for these versions for
+details.
diff --git a/Documentation/RelNotes/2.39.3.txt b/Documentation/RelNotes/2.39.3.txt
index dddff53627..66351b65c2 100644
--- a/Documentation/RelNotes/2.39.3.txt
+++ b/Documentation/RelNotes/2.39.3.txt
@@ -1,9 +1,15 @@
Git v2.39.3 Release Notes
=========================
-This release is primarily to merge fixes accumulated on the 'master'
-front to prepare for 2.40 release that are still relevant to 2.39.x
-maintenance track.
+This release merges up the fix that appears in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8, v2.34.8, v2.35.8, v2.36.6, v2.37.7 and v2.38.5 to
+address the security issues CVE-2023-25652, CVE-2023-25815, and
+CVE-2023-29007; see the release notes for these versions for
+details.
+
+This release also merges fixes that have accumulated on the 'master'
+front to prepare for the 2.40 release that are still relevant to
+2.39.x maintenance track.
Fixes since v2.39.2
-------------------
diff --git a/Documentation/RelNotes/2.40.1.txt b/Documentation/RelNotes/2.40.1.txt
new file mode 100644
index 0000000000..e72f6b1b25
--- /dev/null
+++ b/Documentation/RelNotes/2.40.1.txt
@@ -0,0 +1,8 @@
+Git v2.40.1 Release Notes
+=========================
+
+This release merges up the fix that appears in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8, v2.34.8, v2.35.8, v2.36.6, v2.37.7, v2.38.5
+and v2.39.3 to address the security issues CVE-2023-25652,
+CVE-2023-25815, and CVE-2023-29007; see the release notes for these
+versions for details.
diff --git a/Documentation/RelNotes/2.41.0.txt b/Documentation/RelNotes/2.41.0.txt
index 5767623197..fa2834bd72 100644
--- a/Documentation/RelNotes/2.41.0.txt
+++ b/Documentation/RelNotes/2.41.0.txt
@@ -61,6 +61,36 @@ UI, Workflows & Features
* Clean-up of the code path that deals with merge strategy option
handling in "git rebase".
+ * "git clone --local" stops copying from an original repository that
+ has symbolic links inside its $GIT_DIR; an error message when that
+ happens has been updated.
+
+ * "git branch --format=..." and "git format-patch --format=..."
+ learns "--omit-empty" to hide refs that whose formatting result
+ becomes an empty string from the output.
+
+ * The sendemail-validate validate hook learned to pass the total
+ number of input files and where in the sequence each invocation is
+ via environment variables.
+
+ * When "gc" needs to retain unreachable objects, packing them into
+ cruft packs (instead of exploding them into loose object files) has
+ been offered as a more efficient option for some time. Now the use
+ of cruft packs has been made the default and no longer considered
+ an experimental feature.
+
+ * The output given by "git blame" that attributes a line to contents
+ 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.
@@ -101,6 +131,34 @@ Performance, Internal Implementation, Development Support etc.
* "git write-tree" learns to work better with sparse-index.
+ * The on-disk reverse index that allows mapping from the pack offset
+ to the object name for the object stored at the offset has been
+ enabled by default.
+
+ * "git fsck" learned to validate the on-disk pack reverse index files.
+
+ * 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
@@ -213,6 +271,60 @@ Fixes since v2.40
* Doc toolchain update to remove old workaround for AsciiDoc.
(merge 8806120de6 fc/remove-header-workarounds-for-asciidoc later to maint).
+ * The userdiff regexp patterns for various filetypes that are built
+ into the system have been updated to avoid triggering regexp errors
+ from UTF-8 aware regex engines.
+ (merge be39144954 rs/userdiff-multibyte-regex later to maint).
+
+ * The approxidate() API has been simplified by losing an extra
+ function that did the same thing as another one.
+ (merge 8a7f0b666f rs/remove-approxidate-relative later to maint).
+
+ * Code clean-up to replace a hardcoded constant with a CPP macro.
+ (merge c870de6502 rs/get-tar-commit-id-use-defined-const later to maint).
+
+ * Doc build simplification.
+ (merge 9a09ed3229 fc/doc-stop-using-manversion later to maint).
+
+ * "git archive" run from a subdirectory mishandled attributes and
+ paths outside the current directory.
+ (merge 92b1dd1b9e rs/archive-from-subdirectory-fixes later to maint).
+
+ * The code to parse capability list for v0 on-wire protocol fell into
+ an infinite loop when a capability appears multiple times, which
+ has been corrected.
+
+ * Geometric repacking ("git repack --geometric=<n>") in a repository
+ that borrows from an alternate object database had various corner
+ case bugs, which have been corrected.
+ (merge d85cd18777 ps/fix-geom-repack-with-alternates later to maint).
+
+ * The "%GT" placeholder for the "--format" option of "git log" and
+ friends caused BUG() to trigger on a commit signed with an unknown
+ key, which has been corrected.
+ (merge 7891e46585 jk/gpg-trust-level-fix later to maint).
+
+ * The completion script used to use bare "read" without the "-r"
+ option to read the contents of various state files, which risked
+ getting confused with backslashes in them. This has been
+ corrected.
+ (merge 197152098a ek/completion-use-read-r-to-read-literally later to maint).
+
+ * 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).
@@ -228,3 +340,9 @@ Fixes since v2.40
(merge cc48ddd937 jk/chainlint-fixes later to maint).
(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/blame-options.txt b/Documentation/blame-options.txt
index 95599bd6e5..552dcc60f2 100644
--- a/Documentation/blame-options.txt
+++ b/Documentation/blame-options.txt
@@ -64,11 +64,9 @@ include::line-range-format.txt[]
manual page.
--contents <file>::
- Pretend the file being annotated has a commit with the
- contents from the named file and a parent of <rev>,
- defaulting to HEAD when no <rev> is specified. You may
- specify '-' to make the command read from the standard
- input for the file contents.
+ Annotate using the contents from the named file, starting from <rev>
+ if it is specified, and HEAD otherwise. You may specify '-' to make
+ the command read from the standard input for the file contents.
--date <format>::
Specifies the format used to output dates. If --date is not
diff --git a/Documentation/config/feature.txt b/Documentation/config/feature.txt
index e52bc6b858..17b4d39f89 100644
--- a/Documentation/config/feature.txt
+++ b/Documentation/config/feature.txt
@@ -14,9 +14,6 @@ feature.experimental::
+
* `fetch.negotiationAlgorithm=skipping` may improve fetch negotiation times by
skipping more commits at a time, reducing the number of round trips.
-+
-* `gc.cruftPacks=true` reduces disk space used by unreachable objects during
-garbage collection, preventing loose object explosions.
feature.manyFiles::
Enable config options that optimize for repos with many files in the
diff --git a/Documentation/config/gc.txt b/Documentation/config/gc.txt
index 38fea076a2..7f95c866e1 100644
--- a/Documentation/config/gc.txt
+++ b/Documentation/config/gc.txt
@@ -43,11 +43,11 @@ gc.autoDetach::
if the system supports it. Default is true.
gc.bigPackThreshold::
- If non-zero, all packs larger than this limit are kept when
- `git gc` is run. This is very similar to `--keep-largest-pack`
- except that all packs that meet the threshold are kept, not
- just the largest pack. Defaults to zero. Common unit suffixes of
- 'k', 'm', or 'g' are supported.
+ If non-zero, all non-cruft packs larger than this limit are kept
+ when `git gc` is run. This is very similar to
+ `--keep-largest-pack` except that all non-cruft packs that meet
+ the threshold are kept, not just the largest pack. Defaults to
+ zero. Common unit suffixes of 'k', 'm', or 'g' are supported.
+
Note that if the number of kept packs is more than gc.autoPackLimit,
this configuration variable is ignored, all packs except the base pack
@@ -84,7 +84,7 @@ gc.packRefs::
gc.cruftPacks::
Store unreachable objects in a cruft pack (see
linkgit:git-repack[1]) instead of as loose objects. The default
- is `false`.
+ is `true`.
gc.pruneExpire::
When 'git gc' is run, it will call 'prune --expire 2.weeks.ago'
diff --git a/Documentation/config/pack.txt b/Documentation/config/pack.txt
index 53093d9996..d4c7c9d4e4 100644
--- a/Documentation/config/pack.txt
+++ b/Documentation/config/pack.txt
@@ -171,9 +171,15 @@ pack.writeBitmapLookupTable::
beneficial in repositories that have relatively large bitmap
indexes. Defaults to false.
+pack.readReverseIndex::
+ When true, git will read any .rev file(s) that may be available
+ (see: linkgit:gitformat-pack[5]). When false, the reverse index
+ will be generated from scratch and stored in memory. Defaults to
+ true.
+
pack.writeReverseIndex::
When true, git will write a corresponding .rev file (see:
linkgit:gitformat-pack[5])
for each new packfile that it writes in all places except for
linkgit:git-fast-import[1] and in the bulk checkin mechanism.
- Defaults to false.
+ Defaults to true.
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-branch.txt b/Documentation/git-branch.txt
index d382ac69f7..d207da9101 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -156,6 +156,10 @@ in another worktree linked to the same repository.
--ignore-case::
Sorting and filtering branches are case insensitive.
+--omit-empty::
+ Do not print a newline after formatted refs where the format expands
+ to the empty string.
+
--column[=<options>]::
--no-column::
Display branch listing in columns. See configuration variable
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 6bb32ab460..4af0904f47 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -483,14 +483,11 @@ $ git checkout -b foo # or "git switch -c foo" <1>
$ git branch foo <2>
$ git tag foo <3>
------------
-
<1> creates a new branch `foo`, which refers to commit `f`, and then
updates `HEAD` to refer to branch `foo`. In other words, we'll no longer
be in detached `HEAD` state after this command.
-
<2> similarly creates a new branch `foo`, which refers to commit `f`,
but leaves `HEAD` detached.
-
<3> creates a new tag `foo`, which refers to commit `f`,
leaving `HEAD` detached.
@@ -519,84 +516,89 @@ to checkout these paths out of the index.
EXAMPLES
--------
-. The following sequence checks out the `master` branch, reverts
- the `Makefile` to two revisions back, deletes `hello.c` by
- mistake, and gets it back from the index.
-+
+=== 1. Paths
+
+The following sequence checks out the `master` branch, reverts
+the `Makefile` to two revisions back, deletes `hello.c` by
+mistake, and gets it back from the index.
+
------------
$ git checkout master <1>
$ git checkout master~2 Makefile <2>
$ rm -f hello.c
$ git checkout hello.c <3>
------------
-+
<1> switch branch
<2> take a file out of another commit
<3> restore `hello.c` from the index
-+
+
If you want to check out _all_ C source files out of the index,
you can say
-+
+
------------
$ git checkout -- '*.c'
------------
-+
+
Note the quotes around `*.c`. The file `hello.c` will also be
checked out, even though it is no longer in the working tree,
because the file globbing is used to match entries in the index
(not in the working tree by the shell).
-+
+
If you have an unfortunate branch that is named `hello.c`, this
step would be confused as an instruction to switch to that branch.
You should instead write:
-+
+
------------
$ git checkout -- hello.c
------------
-. After working in the wrong branch, switching to the correct
- branch would be done using:
-+
+=== 2. Merge
+
+After working in the wrong branch, switching to the correct
+branch would be done using:
+
------------
$ git checkout mytopic
------------
-+
+
However, your "wrong" branch and correct `mytopic` branch may
differ in files that you have modified locally, in which case
the above checkout would fail like this:
-+
+
------------
$ git checkout mytopic
error: You have local changes to 'frotz'; not switching branches.
------------
-+
+
You can give the `-m` flag to the command, which would try a
three-way merge:
-+
+
------------
$ git checkout -m mytopic
Auto-merging frotz
------------
-+
+
After this three-way merge, the local modifications are _not_
registered in your index file, so `git diff` would show you what
changes you made since the tip of the new branch.
-. When a merge conflict happens during switching branches with
- the `-m` option, you would see something like this:
-+
+=== 3. Merge conflict
+
+When a merge conflict happens during switching branches with
+the `-m` option, you would see something like this:
+
------------
$ git checkout -m mytopic
Auto-merging frotz
ERROR: Merge conflict in frotz
fatal: merge program failed
------------
-+
+
At this point, `git diff` shows the changes cleanly merged as in
the previous example, as well as the changes in the conflicted
files. Edit and resolve the conflict and mark it resolved with
`git add` as usual:
-+
+
------------
$ edit frotz
$ git add frotz
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index d6434d262d..c37c4a37f7 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -58,6 +58,11 @@ never use the local optimizations). Specifying `--no-local` will
override the default when `/path/to/repo` is given, using the regular
Git transport instead.
+
+If the repository's `$GIT_DIR/objects` has symbolic links or is a
+symbolic link, the clone will fail. This is a security measure to
+prevent the unintentional copying of files by dereferencing the symbolic
+links.
++
*NOTE*: this operation can race with concurrent modification to the
source repository, similar to running `cp -r src dst` while modifying
`src`.
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-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index 0713e49b49..1e215d4e73 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -98,6 +98,10 @@ OPTIONS
--ignore-case::
Sorting and filtering refs are case insensitive.
+--omit-empty::
+ Do not print a newline after formatted refs where the format expands
+ to the empty string.
+
FIELD NAMES
-----------
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index 508f3ae2c0..b1c13fb39a 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -173,8 +173,7 @@ series, where the head is chosen from the cover letter, the
threading makes every mail a reply to the previous one.
+
The default is `--no-thread`, unless the `format.thread` configuration
-is set. If `--thread` is specified without a style, it defaults to the
-style specified by `format.thread` if any, or else `shallow`.
+is set. `--thread` without an argument is equivalent to `--thread=shallow`.
+
Beware that the default for 'git send-email' is to thread emails
itself. If you want `git format-patch` to take care of threading, you
diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt
index a65c9aa62d..90806fd26a 100644
--- a/Documentation/git-gc.txt
+++ b/Documentation/git-gc.txt
@@ -54,9 +54,10 @@ other housekeeping tasks (e.g. rerere, working trees, reflog...) will
be performed as well.
---cruft::
+--[no-]cruft::
When expiring unreachable objects, pack them separately into a
- cruft pack instead of storing them as loose objects.
+ cruft pack instead of storing them as loose objects. `--cruft`
+ is on by default.
--prune=<date>::
Prune loose objects older than date (default is 2 weeks ago,
@@ -77,9 +78,10 @@ be performed as well.
instance running on this repository.
--keep-largest-pack::
- All packs except the largest pack and those marked with a
- `.keep` files are consolidated into a single pack. When this
- option is used, `gc.bigPackThreshold` is ignored.
+ All packs except the largest non-cruft pack, any packs marked
+ with a `.keep` file, and any cruft pack(s) are consolidated into
+ a single pack. When this option is used, `gc.bigPackThreshold`
+ is ignored.
AGGRESSIVE
----------
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-tag.txt b/Documentation/git-tag.txt
index fdc72b5875..7f61c1edb3 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -131,6 +131,10 @@ options for details.
--ignore-case::
Sorting and filtering tags are case insensitive.
+--omit-empty::
+ Do not print a newline after formatted refs where the format expands
+ to the empty string.
+
--column[=<options>]::
--no-column::
Display tag listing in columns. See configuration variable
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/gitformat-pack.txt b/Documentation/gitformat-pack.txt
index e06af02f21..0c1be2dbe8 100644
--- a/Documentation/gitformat-pack.txt
+++ b/Documentation/gitformat-pack.txt
@@ -611,8 +611,8 @@ result of repeatedly resetting the objects' mtimes to the present time.
If you are GC-ing repositories in a mixed version environment, consider omitting
the `--cruft` option when using linkgit:git-repack[1] and linkgit:git-gc[1], and
-leaving the `gc.cruftPacks` configuration unset until all writers understand
-cruft packs.
+setting the `gc.cruftPacks` configuration to "false" until all writers
+understand cruft packs.
=== Alternatives
diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index 62908602e7..86f804720a 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -595,10 +595,51 @@ 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.
+
+`GIT_SENDEMAIL_FILE_COUNTER`::
+ A 1-based counter incremented by one for every file holding an e-mail
+ to be sent (excluding any FIFOs). This counter does not follow the
+ patch series counter scheme. It will always start at 1 and will end at
+ GIT_SENDEMAIL_FILE_TOTAL.
+
+`GIT_SENDEMAIL_FILE_TOTAL`::
+ The total number of files that will be sent (excluding any FIFOs). This
+ counter does not follow the patch series counter scheme. It will always
+ be equal to the number of files being sent, whether there is a cover
+ letter or not.
+
+These variables may for instance be used to validate patch series.
+
+The sample `sendemail-validate` hook that comes with Git checks that all sent
+patches (excluding the cover letter) can be applied on top of the upstream
+repository default branch without conflicts. Some placeholders are left for
+additional validation steps to be performed after all patches of a given series
+have been applied.
fsmonitor-watchman
~~~~~~~~~~~~~~~~~~
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/Makefile b/Makefile
index 60ab1a8b4f..e440728c24 100644
--- a/Makefile
+++ b/Makefile
@@ -1032,6 +1032,7 @@ LIB_OBJS += fsmonitor.o
LIB_OBJS += fsmonitor-ipc.o
LIB_OBJS += fsmonitor-settings.o
LIB_OBJS += gettext.o
+LIB_OBJS += git-zlib.o
LIB_OBJS += gpg-interface.o
LIB_OBJS += graph.o
LIB_OBJS += grep.o
@@ -1192,7 +1193,6 @@ LIB_OBJS += write-or-die.o
LIB_OBJS += ws.o
LIB_OBJS += wt-status.o
LIB_OBJS += xdiff-interface.o
-LIB_OBJS += zlib.o
BUILTIN_OBJS += builtin/add.o
BUILTIN_OBJS += builtin/am.o
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/add-patch.c b/add-patch.c
index 1e1ee2df59..8d770d203f 100644
--- a/add-patch.c
+++ b/add-patch.c
@@ -1,8 +1,11 @@
#include "cache.h"
#include "add-interactive.h"
+#include "advice.h"
#include "alloc.h"
+#include "editor.h"
#include "environment.h"
#include "gettext.h"
+#include "object-name.h"
#include "strbuf.h"
#include "run-command.h"
#include "strvec.h"
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 9b7288bc92..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"
@@ -22,12 +23,16 @@
#include "xdiff-interface.h"
#include "ll-merge.h"
#include "lockfile.h"
+#include "object-name.h"
+#include "object-file.h"
#include "parse-options.h"
#include "quote.h"
#include "rerere.h"
#include "apply.h"
#include "entry.h"
#include "setup.h"
+#include "symlinks.h"
+#include "ws.h"
#include "wrapper.h"
struct gitdiff_data {
@@ -4586,7 +4591,7 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch)
FILE *rej;
char namebuf[PATH_MAX];
struct fragment *frag;
- int cnt = 0;
+ int fd, cnt = 0;
struct strbuf sb = STRBUF_INIT;
for (cnt = 0, frag = patch->fragments; frag; frag = frag->next) {
@@ -4626,7 +4631,17 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch)
memcpy(namebuf, patch->new_name, cnt);
memcpy(namebuf + cnt, ".rej", 5);
- rej = fopen(namebuf, "w");
+ fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666);
+ if (fd < 0) {
+ if (errno != EEXIST)
+ return error_errno(_("cannot open %s"), namebuf);
+ if (unlink(namebuf))
+ return error_errno(_("cannot unlink '%s'"), namebuf);
+ fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666);
+ if (fd < 0)
+ return error_errno(_("cannot open %s"), namebuf);
+ }
+ rej = fdopen(fd, "w");
if (!rej)
return error_errno(_("cannot open %s"), namebuf);
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-tar.c b/archive-tar.c
index 497dad0b3a..4cd81d8161 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -5,6 +5,7 @@
#include "alloc.h"
#include "config.h"
#include "gettext.h"
+#include "git-zlib.h"
#include "hex.h"
#include "tar.h"
#include "archive.h"
diff --git a/archive-zip.c b/archive-zip.c
index e6f5c10a14..d0d065a312 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -1,10 +1,11 @@
/*
* Copyright (c) 2006 Rene Scharfe
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "archive.h"
#include "gettext.h"
+#include "git-zlib.h"
#include "hex.h"
#include "streaming.h"
#include "utf8.h"
diff --git a/archive.c b/archive.c
index f1b8e9ce48..641baad627 100644
--- a/archive.c
+++ b/archive.c
@@ -2,13 +2,16 @@
#include "abspath.h"
#include "alloc.h"
#include "config.h"
+#include "convert.h"
#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"
@@ -173,6 +176,29 @@ static int write_archive_entry(const struct object_id *oid, const char *base,
args->convert = check_attr_export_subst(check);
}
+ if (args->prefix) {
+ static struct strbuf new_path = STRBUF_INIT;
+ static struct strbuf buf = STRBUF_INIT;
+ const char *rel;
+
+ rel = relative_path(path_without_prefix, args->prefix, &buf);
+
+ /*
+ * We don't add an entry for the current working
+ * directory when we are at the root; skip it also when
+ * we're in a subdirectory or submodule. Skip entries
+ * higher up as well.
+ */
+ if (!strcmp(rel, "./") || starts_with(rel, "../"))
+ return S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0;
+
+ /* rel can refer to path, so don't edit it in place */
+ strbuf_reset(&new_path);
+ strbuf_add(&new_path, args->base, args->baselen);
+ strbuf_addstr(&new_path, rel);
+ strbuf_swap(&path, &new_path);
+ }
+
if (args->verbose)
fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
@@ -408,6 +434,27 @@ static int reject_entry(const struct object_id *oid UNUSED,
return ret;
}
+static int reject_outside(const struct object_id *oid UNUSED,
+ struct strbuf *base, const char *filename,
+ unsigned mode, void *context)
+{
+ struct archiver_args *args = context;
+ struct strbuf buf = STRBUF_INIT;
+ struct strbuf path = STRBUF_INIT;
+ int ret = 0;
+
+ if (S_ISDIR(mode))
+ return READ_TREE_RECURSIVE;
+
+ strbuf_addbuf(&path, base);
+ strbuf_addstr(&path, filename);
+ if (starts_with(relative_path(path.buf, args->prefix, &buf), "../"))
+ ret = -1;
+ strbuf_release(&buf);
+ strbuf_release(&path);
+ return ret;
+}
+
static int path_exists(struct archiver_args *args, const char *path)
{
const char *paths[] = { path, NULL };
@@ -415,8 +462,13 @@ static int path_exists(struct archiver_args *args, const char *path)
int ret;
ctx.args = args;
- parse_pathspec(&ctx.pathspec, 0, 0, "", paths);
+ parse_pathspec(&ctx.pathspec, 0, PATHSPEC_PREFER_CWD,
+ args->prefix, paths);
ctx.pathspec.recursive = 1;
+ if (args->prefix && read_tree(args->repo, args->tree, &ctx.pathspec,
+ reject_outside, args))
+ die(_("pathspec '%s' matches files outside the "
+ "current directory"), path);
ret = read_tree(args->repo, args->tree,
&ctx.pathspec,
reject_entry, &ctx);
@@ -432,9 +484,8 @@ static void parse_pathspec_arg(const char **pathspec,
* Also if pathspec patterns are dependent, we're in big
* trouble as we test each one separately
*/
- parse_pathspec(&ar_args->pathspec, 0,
- PATHSPEC_PREFER_FULL,
- "", pathspec);
+ parse_pathspec(&ar_args->pathspec, 0, PATHSPEC_PREFER_CWD,
+ ar_args->prefix, pathspec);
ar_args->pathspec.recursive = 1;
if (pathspec) {
while (*pathspec) {
@@ -446,8 +497,7 @@ static void parse_pathspec_arg(const char **pathspec,
}
static void parse_treeish_arg(const char **argv,
- struct archiver_args *ar_args, const char *prefix,
- int remote)
+ struct archiver_args *ar_args, int remote)
{
const char *name = argv[0];
const struct object_id *commit_oid;
@@ -487,20 +537,6 @@ static void parse_treeish_arg(const char **argv,
if (!tree)
die(_("not a tree object: %s"), oid_to_hex(&oid));
- if (prefix) {
- struct object_id tree_oid;
- unsigned short mode;
- int err;
-
- err = get_tree_entry(ar_args->repo,
- &tree->object.oid,
- prefix, &tree_oid,
- &mode);
- if (err || !S_ISDIR(mode))
- die(_("current working directory is untracked"));
-
- tree = parse_tree_indirect(&tree_oid);
- }
ar_args->refname = ref;
ar_args->tree = tree;
ar_args->commit_oid = commit_oid;
@@ -718,7 +754,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
setup_git_directory();
}
- parse_treeish_arg(argv, &args, prefix, remote);
+ parse_treeish_arg(argv, &args, remote);
parse_pathspec_arg(argv + 1, &args);
rc = ar->write_archive(ar, &args);
diff --git a/archive.h b/archive.h
index 7178e2a9a2..3a4bdfbd07 100644
--- a/archive.h
+++ b/archive.h
@@ -1,8 +1,9 @@
#ifndef ARCHIVE_H
#define ARCHIVE_H
-#include "cache.h"
+#include "object-name.h"
#include "pathspec.h"
+#include "string-list.h"
struct repository;
struct pretty_print_context;
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/banned.h b/banned.h
index 6ccf46bc19..44e76bd90a 100644
--- a/banned.h
+++ b/banned.h
@@ -18,6 +18,10 @@
#define strncpy(x,y,n) BANNED(strncpy)
#undef strncat
#define strncat(x,y,n) BANNED(strncat)
+#undef strtok
+#define strtok(x,y) BANNED(strtok)
+#undef strtok_r
+#define strtok_r(x,y,z) BANNED(strtok_r)
#undef sprintf
#undef vsprintf
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/bisect.c b/bisect.c
index 0a5f2ed354..8d5f8e5885 100644
--- a/bisect.c
+++ b/bisect.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "commit.h"
#include "diff.h"
@@ -17,6 +17,7 @@
#include "strvec.h"
#include "commit-slab.h"
#include "commit-reach.h"
+#include "object-name.h"
#include "object-store.h"
#include "dir.h"
diff --git a/blame.c b/blame.c
index 2c427bcdbf..b830654062 100644
--- a/blame.c
+++ b/blame.c
@@ -3,12 +3,14 @@
#include "object-store.h"
#include "cache-tree.h"
#include "mergesort.h"
+#include "convert.h"
#include "diff.h"
#include "diffcore.h"
#include "gettext.h"
#include "hex.h"
#include "setup.h"
#include "tag.h"
+#include "trace2.h"
#include "blame.h"
#include "alloc.h"
#include "commit-slab.h"
@@ -206,8 +208,12 @@ static struct commit *fake_working_tree_commit(struct repository *r,
origin = make_origin(commit, path);
- ident = fmt_ident("Not Committed Yet", "not.committed.yet",
- WANT_BLANK_IDENT, NULL, 0);
+ if (contents_from)
+ ident = fmt_ident("External file (--contents)", "external.file",
+ WANT_BLANK_IDENT, NULL, 0);
+ else
+ ident = fmt_ident("Not Committed Yet", "not.committed.yet",
+ WANT_BLANK_IDENT, NULL, 0);
strbuf_addstr(&msg, "tree 0000000000000000000000000000000000000000\n");
for (parent = commit->parents; parent; parent = parent->next)
strbuf_addf(&msg, "parent %s\n",
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 99a0e7889e..ba3914adf5 100644
--- a/branch.c
+++ b/branch.c
@@ -1,13 +1,15 @@
#include "git-compat-util.h"
-#include "cache.h"
+#include "advice.h"
#include "config.h"
#include "branch.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "refs.h"
#include "refspec.h"
#include "remote.h"
+#include "repository.h"
#include "sequencer.h"
#include "commit.h"
#include "worktree.h"
@@ -838,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/add.c b/builtin/add.c
index f12054d9be..76cc026a68 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -5,9 +5,11 @@
*/
#define USE_THE_INDEX_VARIABLE
#include "cache.h"
+#include "advice.h"
#include "config.h"
#include "builtin.h"
#include "lockfile.h"
+#include "editor.h"
#include "dir.h"
#include "gettext.h"
#include "pathspec.h"
diff --git a/builtin/am.c b/builtin/am.c
index cd1e20f24e..5c83f2e003 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -6,8 +6,10 @@
#define USE_THE_INDEX_VARIABLE
#include "cache.h"
#include "abspath.h"
+#include "advice.h"
#include "config.h"
#include "builtin.h"
+#include "editor.h"
#include "environment.h"
#include "exec-cmd.h"
#include "gettext.h"
@@ -26,6 +28,7 @@
#include "diffcore.h"
#include "unpack-trees.h"
#include "branch.h"
+#include "object-name.h"
#include "sequencer.h"
#include "revision.h"
#include "merge-recursive.h"
@@ -37,6 +40,7 @@
#include "apply.h"
#include "string-list.h"
#include "packfile.h"
+#include "pager.h"
#include "repository.h"
#include "pretty.h"
#include "wrapper.h"
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 26f07357a0..4812450c39 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -1,14 +1,17 @@
#include "builtin.h"
#include "cache.h"
+#include "copy.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "parse-options.h"
#include "bisect.h"
#include "refs.h"
#include "dir.h"
#include "strvec.h"
#include "run-command.h"
+#include "oid-array.h"
#include "prompt.h"
#include "quote.h"
#include "revision.h"
diff --git a/builtin/blame.c b/builtin/blame.c
index a8d2114adc..2df6039a6e 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -28,7 +28,9 @@
#include "line-log.h"
#include "dir.h"
#include "progress.h"
+#include "object-name.h"
#include "object-store.h"
+#include "pager.h"
#include "blame.h"
#include "refs.h"
#include "setup.h"
diff --git a/builtin/branch.c b/builtin/branch.c
index 68964eef2d..e6c2655af6 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -8,11 +8,13 @@
#include "cache.h"
#include "config.h"
#include "color.h"
+#include "editor.h"
#include "environment.h"
#include "refs.h"
#include "commit.h"
#include "builtin.h"
#include "gettext.h"
+#include "object-name.h"
#include "remote.h"
#include "parse-options.h"
#include "branch.h"
@@ -44,6 +46,7 @@ static const char *head;
static struct object_id head_oid;
static int recurse_submodules = 0;
static int submodule_propagate_branches = 0;
+static int omit_empty = 0;
static int branch_use_color = -1;
static char branch_colors[][COLOR_MAXLEN] = {
@@ -483,7 +486,8 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
string_list_append(output, out.buf);
} else {
fwrite(out.buf, 1, out.len, stdout);
- putchar('\n');
+ if (out.len || !omit_empty)
+ putchar('\n');
}
}
@@ -508,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++) {
@@ -527,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)) {
/*
@@ -550,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);
@@ -566,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)) {
@@ -580,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))
@@ -596,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);
@@ -612,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")
@@ -692,6 +741,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
OPT_BIT('D', NULL, &delete, N_("delete branch (even if not merged)"), 2),
OPT_BIT('m', "move", &rename, N_("move/rename a branch and its reflog"), 1),
OPT_BIT('M', NULL, &rename, N_("move/rename a branch, even if target exists"), 2),
+ OPT_BOOL(0, "omit-empty", &omit_empty,
+ N_("do not output a newline after empty formatted refs")),
OPT_BIT('c', "copy", &copy, N_("copy a branch and its reflog"), 1),
OPT_BIT('C', NULL, &copy, N_("copy a branch, even if target exists"), 2),
OPT_BOOL('l', "list", &list, N_("list branch names")),
@@ -828,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);
@@ -873,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/bugreport.c b/builtin/bugreport.c
index 52955e1d38..daf6c23657 100644
--- a/builtin/bugreport.c
+++ b/builtin/bugreport.c
@@ -1,5 +1,6 @@
#include "builtin.h"
#include "abspath.h"
+#include "editor.h"
#include "gettext.h"
#include "parse-options.h"
#include "strbuf.h"
@@ -8,6 +9,7 @@
#include "hook.h"
#include "hook-list.h"
#include "diagnose.h"
+#include "object-file.h"
#include "setup.h"
#include "wrapper.h"
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/cat-file.c b/builtin/cat-file.c
index 04d4bb6c77..0bafc14e6c 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -7,6 +7,7 @@
#include "cache.h"
#include "alloc.h"
#include "config.h"
+#include "convert.h"
#include "builtin.h"
#include "diff.h"
#include "environment.h"
@@ -19,6 +20,8 @@
#include "tree-walk.h"
#include "oid-array.h"
#include "packfile.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "replace-object.h"
#include "promisor-remote.h"
diff --git a/builtin/check-attr.c b/builtin/check-attr.c
index 1dbe9d6ca8..b2b678847f 100644
--- a/builtin/check-attr.c
+++ b/builtin/check-attr.c
@@ -5,7 +5,9 @@
#include "attr.h"
#include "environment.h"
#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 38a8cd6a96..715eeb5048 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -15,7 +15,9 @@
#include "hook.h"
#include "ll-merge.h"
#include "lockfile.h"
+#include "mem-pool.h"
#include "merge-recursive.h"
+#include "object-name.h"
#include "object-store.h"
#include "parse-options.h"
#include "refs.h"
@@ -26,6 +28,8 @@
#include "setup.h"
#include "submodule.h"
#include "submodule-config.h"
+#include "symlinks.h"
+#include "trace2.h"
#include "tree.h"
#include "tree-walk.h"
#include "unpack-trees.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 6dc89f1058..15f9912b4c 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -11,7 +11,9 @@
#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "abspath.h"
+#include "advice.h"
#include "config.h"
+#include "copy.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
@@ -20,6 +22,7 @@
#include "fetch-pack.h"
#include "refs.h"
#include "refspec.h"
+#include "object-file.h"
#include "object-store.h"
#include "tree.h"
#include "tree-walk.h"
@@ -36,10 +39,12 @@
#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"
#include "bundle-uri.h"
+#include "wrapper.h"
/*
* Overall FIXMEs:
@@ -331,8 +336,18 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
iter = dir_iterator_begin(src->buf, DIR_ITERATOR_PEDANTIC);
- if (!iter)
+ if (!iter) {
+ if (errno == ENOTDIR) {
+ int saved_errno = errno;
+ struct stat st;
+
+ if (!lstat(src->buf, &st) && S_ISLNK(st.st_mode))
+ die(_("'%s' is a symlink, refusing to clone with --local"),
+ src->buf);
+ errno = saved_errno;
+ }
die_errno(_("failed to start iterator over '%s'"), src->buf);
+ }
strbuf_addch(src, '/');
src_len = src->len;
diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index 9011426976..a3d00fa232 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -12,6 +12,7 @@
#include "progress.h"
#include "replace-object.h"
#include "tag.h"
+#include "trace2.h"
#define BUILTIN_COMMIT_GRAPH_VERIFY_USAGE \
N_("git commit-graph verify [--object-dir <dir>] [--shallow] [--[no-]progress]")
diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c
index 15be167f87..d1d251c3de 100644
--- a/builtin/commit-tree.c
+++ b/builtin/commit-tree.c
@@ -7,6 +7,7 @@
#include "config.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "object-store.h"
#include "repository.h"
#include "commit.h"
diff --git a/builtin/commit.c b/builtin/commit.c
index 9d8e1ea91a..e67c4be221 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -7,11 +7,13 @@
#define USE_THE_INDEX_VARIABLE
#include "cache.h"
+#include "advice.h"
#include "config.h"
#include "lockfile.h"
#include "cache-tree.h"
#include "color.h"
#include "dir.h"
+#include "editor.h"
#include "environment.h"
#include "builtin.h"
#include "diff.h"
@@ -26,6 +28,7 @@
#include "log-tree.h"
#include "strbuf.h"
#include "utf8.h"
+#include "object-name.h"
#include "parse-options.h"
#include "string-list.h"
#include "rerere.h"
diff --git a/builtin/config.c b/builtin/config.c
index fe79fb60c4..ff2fe8ef12 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -3,11 +3,13 @@
#include "alloc.h"
#include "config.h"
#include "color.h"
+#include "editor.h"
#include "environment.h"
#include "gettext.h"
#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 62c09a271d..756c5f02ae 100644
--- a/builtin/credential-cache--daemon.c
+++ b/builtin/credential-cache--daemon.c
@@ -2,6 +2,7 @@
#include "abspath.h"
#include "alloc.h"
#include "gettext.h"
+#include "object-file.h"
#include "parse-options.h"
#ifndef NO_UNIX_SOCKETS
@@ -133,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/describe.c b/builtin/describe.c
index 0125d4ddba..55b4baaa22 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -11,6 +11,7 @@
#include "refs.h"
#include "builtin.h"
#include "exec-cmd.h"
+#include "object-name.h"
#include "parse-options.h"
#include "revision.h"
#include "diff.h"
@@ -658,6 +659,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
int fd, result;
setup_work_tree();
+ prepare_repo_settings(the_repository);
+ the_repository->settings.command_requires_full_index = 0;
repo_read_index(the_repository);
refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED,
NULL, NULL, NULL);
diff --git a/builtin/diagnose.c b/builtin/diagnose.c
index 0f8b64994c..4f22eb2b55 100644
--- a/builtin/diagnose.c
+++ b/builtin/diagnose.c
@@ -1,6 +1,7 @@
#include "builtin.h"
#include "abspath.h"
#include "gettext.h"
+#include "object-file.h"
#include "parse-options.h"
#include "diagnose.h"
diff --git a/builtin/diff-files.c b/builtin/diff-files.c
index dc991f753b..360464e6ef 100644
--- a/builtin/diff-files.c
+++ b/builtin/diff-files.c
@@ -27,6 +27,10 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix)
usage(diff_files_usage);
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
+
+ prepare_repo_settings(the_repository);
+ the_repository->settings.command_requires_full_index = 0;
+
repo_init_revisions(the_repository, &rev, prefix);
rev.abbrev = 0;
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 5ba524fa63..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"
@@ -25,6 +26,7 @@
#include "strvec.h"
#include "strbuf.h"
#include "lockfile.h"
+#include "object-file.h"
#include "object-store.h"
#include "dir.h"
#include "entry.h"
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 8224bf4bc1..9a95f6a1a8 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -10,6 +10,7 @@
#include "hex.h"
#include "refs.h"
#include "refspec.h"
+#include "object-file.h"
#include "object-store.h"
#include "commit.h"
#include "object.h"
diff --git a/builtin/fast-import.c b/builtin/fast-import.c
index 1fb95275d7..bbd9b2b3e7 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
@@ -19,6 +19,8 @@
#include "dir.h"
#include "run-command.h"
#include "packfile.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "mem-pool.h"
#include "commit-reach.h"
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index 5f341b794d..3ba0fe5a39 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -2,6 +2,7 @@
#include "alloc.h"
#include "gettext.h"
#include "hex.h"
+#include "object-file.h"
#include "pkt-line.h"
#include "fetch-pack.h"
#include "remote.h"
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 85bd280103..4d7c289752 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -2,6 +2,7 @@
* "git fetch"
*/
#include "cache.h"
+#include "advice.h"
#include "config.h"
#include "gettext.h"
#include "environment.h"
@@ -9,8 +10,10 @@
#include "repository.h"
#include "refs.h"
#include "refspec.h"
+#include "object-name.h"
#include "object-store.h"
#include "oidset.h"
+#include "oid-array.h"
#include "commit.h"
#include "builtin.h"
#include "string-list.h"
@@ -25,12 +28,16 @@
#include "strvec.h"
#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"
#include "promisor-remote.h"
#include "commit-graph.h"
#include "shallow.h"
+#include "trace.h"
+#include "trace2.h"
#include "worktree.h"
#include "bundle-uri.h"
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 0bdc49a6e1..695fc8f4a5 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -22,7 +22,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
int i;
struct ref_sorting *sorting;
struct string_list sorting_options = STRING_LIST_INIT_DUP;
- int maxcount = 0, icase = 0;
+ int maxcount = 0, icase = 0, omit_empty = 0;
struct ref_array array;
struct ref_filter filter;
struct ref_format format = REF_FORMAT_INIT;
@@ -40,6 +40,8 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
N_("quote placeholders suitably for python"), QUOTE_PYTHON),
OPT_BIT(0 , "tcl", &format.quote_style,
N_("quote placeholders suitably for Tcl"), QUOTE_TCL),
+ OPT_BOOL(0, "omit-empty", &omit_empty,
+ N_("do not output a newline after empty formatted refs")),
OPT_GROUP(""),
OPT_INTEGER( 0 , "count", &maxcount, N_("show only <n> matched refs")),
@@ -112,7 +114,8 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
if (format_ref_array_item(array.items[i], &format, &output, &err))
die("%s", err.buf);
fwrite(output.buf, 1, output.len, stdout);
- putchar('\n');
+ if (output.len || !omit_empty)
+ putchar('\n');
}
strbuf_release(&err);
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 095b39d398..dcc165bf0c 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -19,11 +19,15 @@
#include "streaming.h"
#include "decorate.h"
#include "packfile.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "replace-object.h"
#include "resolve-undo.h"
#include "run-command.h"
#include "worktree.h"
+#include "pack-revindex.h"
+#include "pack-bitmap.h"
#define REACHABLE 0x0001
#define SEEN 0x0002
@@ -53,6 +57,8 @@ static int name_objects;
#define ERROR_REFS 010
#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)
{
@@ -856,6 +862,38 @@ static int mark_packed_for_connectivity(const struct object_id *oid,
return 0;
}
+static int check_pack_rev_indexes(struct repository *r, int show_progress)
+{
+ struct progress *progress = NULL;
+ uint32_t pack_count = 0;
+ int res = 0;
+
+ if (show_progress) {
+ 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(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(r, p) &&
+ verify_pack_revindex(p)) {
+ error(_("invalid rev-index for pack '%s'"), p->pack_name);
+ res = ERROR_PACK_REV_INDEX;
+ }
+ display_progress(progress, ++pack_count);
+ }
+ stop_progress(&progress);
+
+ return res;
+}
+
static char const * const fsck_usage[] = {
N_("git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n"
" [--[no-]full] [--strict] [--verbose] [--lost-found]\n"
@@ -1019,6 +1057,10 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
free_worktrees(worktrees);
}
+ errors_found |= check_pack_rev_indexes(the_repository, show_progress);
+ if (verify_bitmap_files(the_repository))
+ errors_found |= ERROR_BITMAP;
+
check_connectivity();
if (the_repository->settings.core_commit_graph) {
diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c
index 42af6a2cc7..f6dd9a784c 100644
--- a/builtin/fsmonitor--daemon.c
+++ b/builtin/fsmonitor--daemon.c
@@ -14,6 +14,7 @@
#include "simple-ipc.h"
#include "khash.h"
#include "pkt-line.h"
+#include "trace2.h"
static const char * const builtin_fsmonitor__daemon_usage[] = {
N_("git fsmonitor--daemon start [<options>]"),
diff --git a/builtin/gc.c b/builtin/gc.c
index edd98d35a5..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"
@@ -25,6 +26,7 @@
#include "commit.h"
#include "commit-graph.h"
#include "packfile.h"
+#include "object-file.h"
#include "object-store.h"
#include "pack.h"
#include "pack-objects.h"
@@ -37,6 +39,7 @@
#include "gettext.h"
#include "hook.h"
#include "setup.h"
+#include "trace2.h"
#include "wrapper.h"
#define FAILED_RUN "failed to run %s"
@@ -48,7 +51,7 @@ static const char * const builtin_gc_usage[] = {
static int pack_refs = 1;
static int prune_reflogs = 1;
-static int cruft_packs = -1;
+static int cruft_packs = 1;
static int aggressive_depth = 50;
static int aggressive_window = 250;
static int gc_auto_threshold = 6700;
@@ -219,7 +222,7 @@ static struct packed_git *find_base_packs(struct string_list *packs,
struct packed_git *p, *base = NULL;
for (p = get_all_packs(the_repository); p; p = p->next) {
- if (!p->pack_local)
+ if (!p->pack_local || p->is_cruft)
continue;
if (limit) {
if (p->pack_size >= limit)
@@ -608,10 +611,6 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
if (prune_expire && parse_expiry_date(prune_expire, &dummy))
die(_("failed to parse prune expiry value %s"), prune_expire);
- prepare_repo_settings(the_repository);
- if (cruft_packs < 0)
- cruft_packs = the_repository->settings.gc_cruft_packs;
-
if (aggressive) {
strvec_push(&repack, "-f");
if (aggressive_depth > 0)
@@ -1687,11 +1686,11 @@ static int get_schedule_cmd(const char **cmd, int *is_available)
if (is_available)
*is_available = 0;
- string_list_split_in_place(&list, testing, ',', -1);
+ string_list_split_in_place(&list, testing, ",", -1);
for_each_string_list_item(item, &list) {
struct string_list pair = STRING_LIST_INIT_NODUP;
- if (string_list_split_in_place(&pair, item->string, ':', 2) != 2)
+ if (string_list_split_in_place(&pair, item->string, ":", 2) != 2)
continue;
if (!strcmp(*cmd, pair.items[0].string)) {
diff --git a/builtin/get-tar-commit-id.c b/builtin/get-tar-commit-id.c
index d5b871b21d..564cfcac4f 100644
--- a/builtin/get-tar-commit-id.c
+++ b/builtin/get-tar-commit-id.c
@@ -35,7 +35,7 @@ int cmd_get_tar_commit_id(int argc, const char **argv UNUSED, const char *prefix
die_errno("git get-tar-commit-id: read error");
if (n != HEADERSIZE)
die_errno("git get-tar-commit-id: EOF before reading tar header");
- if (header->typeflag[0] != 'g')
+ if (header->typeflag[0] != TYPEFLAG_GLOBAL_HEADER)
return 1;
len = strtol(content, &end, 10);
diff --git a/builtin/grep.c b/builtin/grep.c
index a1b68d90bd..b86c754def 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -26,8 +26,11 @@
#include "setup.h"
#include "submodule.h"
#include "submodule-config.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "packfile.h"
+#include "pager.h"
#include "write-or-die.h"
static const char *grep_prefix;
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index a15fe4fd3f..a380121166 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -9,6 +9,7 @@
#include "config.h"
#include "gettext.h"
#include "hex.h"
+#include "object-file.h"
#include "object-store.h"
#include "blob.h"
#include "quote.h"
diff --git a/builtin/help.c b/builtin/help.c
index 87333a02ec..d3cf4af3f6 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -6,7 +6,9 @@
#include "builtin.h"
#include "exec-cmd.h"
#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/index-pack.c b/builtin/index-pack.c
index b17e79cd40..bb67e16655 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -17,7 +17,10 @@
#include "streaming.h"
#include "thread-utils.h"
#include "packfile.h"
+#include "pack-revindex.h"
+#include "object-file.h"
#include "object-store.h"
+#include "oid-array.h"
#include "replace-object.h"
#include "promisor-remote.h"
#include "setup.h"
@@ -1753,12 +1756,13 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
fsck_options.walk = mark_link;
reset_pack_idx_option(&opts);
+ opts.flags |= WRITE_REV;
git_config(git_index_pack_config, &opts);
if (prefix && chdir(prefix))
die(_("Cannot come back to cwd"));
- if (git_env_bool(GIT_TEST_WRITE_REV_INDEX, 0))
- rev_index = 1;
+ if (git_env_bool(GIT_TEST_NO_WRITE_REV_INDEX, 0))
+ rev_index = 0;
else
rev_index = !!(opts.flags & (WRITE_REV_VERIFY | WRITE_REV));
diff --git a/builtin/init-db.c b/builtin/init-db.c
index ba6e0b20fa..aef4036105 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -6,12 +6,15 @@
#include "cache.h"
#include "abspath.h"
#include "config.h"
+#include "copy.h"
#include "environment.h"
#include "gettext.h"
#include "refs.h"
#include "builtin.h"
#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 7d19578963..676de107d6 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -12,7 +12,10 @@
#include "gettext.h"
#include "hex.h"
#include "refs.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
+#include "pager.h"
#include "color.h"
#include "commit.h"
#include "diff.h"
@@ -20,6 +23,7 @@
#include "revision.h"
#include "log-tree.h"
#include "builtin.h"
+#include "oid-array.h"
#include "tag.h"
#include "reflog-walk.h"
#include "patch-ids.h"
@@ -40,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-files.c b/builtin/ls-files.c
index ed35fa8d8e..625f48f0d6 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -8,10 +8,12 @@
#include "cache.h"
#include "repository.h"
#include "config.h"
+#include "convert.h"
#include "quote.h"
#include "dir.h"
#include "builtin.h"
#include "gettext.h"
+#include "object-name.h"
#include "strbuf.h"
#include "tree.h"
#include "cache-tree.h"
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/ls-tree.c b/builtin/ls-tree.c
index f32e6be219..077977a461 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -7,6 +7,7 @@
#include "config.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "object-store.h"
#include "blob.h"
#include "tree.h"
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index 3f22273b40..854019a32d 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -7,6 +7,7 @@
#include "refs.h"
#include "diff.h"
#include "revision.h"
+#include "object-name.h"
#include "parse-options.h"
#include "repository.h"
#include "commit-reach.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 91ed55f3ab..b9e980384a 100644
--- a/builtin/merge-recursive.c
+++ b/builtin/merge-recursive.c
@@ -1,9 +1,13 @@
#include "cache.h"
#include "builtin.h"
+#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 803e380856..b8f8a8b5d9 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -8,6 +8,7 @@
#include "commit.h"
#include "commit-reach.h"
#include "merge-ort.h"
+#include "object-name.h"
#include "object-store.h"
#include "parse-options.h"
#include "repository.h"
@@ -15,6 +16,8 @@
#include "exec-cmd.h"
#include "merge-blobs.h"
#include "quote.h"
+#include "tree.h"
+#include "config.h"
static int line_termination = '\n';
@@ -626,6 +629,8 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
if (argc != expected_remaining_argc)
usage_with_options(merge_tree_usage, mt_options);
+ git_config(git_default_config, NULL);
+
/* Do the relevant type of merge */
if (o.mode == MODE_REAL)
return real_merge(&o, merge_base, argv[0], argv[1], prefix);
diff --git a/builtin/merge.c b/builtin/merge.c
index a99be9610e..8da3e46abb 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -9,11 +9,14 @@
#define USE_THE_INDEX_VARIABLE
#include "cache.h"
#include "abspath.h"
+#include "advice.h"
#include "alloc.h"
#include "config.h"
+#include "editor.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "parse-options.h"
#include "builtin.h"
#include "lockfile.h"
diff --git a/builtin/mktag.c b/builtin/mktag.c
index b3f6d7ea38..44fa56eff3 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -4,6 +4,7 @@
#include "parse-options.h"
#include "tag.h"
#include "replace-object.h"
+#include "object-file.h"
#include "object-store.h"
#include "fsck.h"
#include "config.h"
diff --git a/builtin/mv.c b/builtin/mv.c
index b7c5ffbd8c..665bd27448 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -6,16 +6,19 @@
#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "abspath.h"
+#include "advice.h"
#include "alloc.h"
#include "config.h"
#include "environment.h"
#include "gettext.h"
+#include "object-file.h"
#include "pathspec.h"
#include "lockfile.h"
#include "dir.h"
#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 831d360a78..4d15a23fc4 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -8,6 +8,8 @@
#include "commit.h"
#include "tag.h"
#include "refs.h"
+#include "object-name.h"
+#include "pager.h"
#include "parse-options.h"
#include "prio-queue.h"
#include "hash-lookup.h"
@@ -571,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/notes.c b/builtin/notes.c
index 4ff44f1e3d..d5788352b6 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -10,9 +10,11 @@
#include "cache.h"
#include "config.h"
#include "builtin.h"
+#include "editor.h"
#include "gettext.h"
#include "hex.h"
#include "notes.h"
+#include "object-name.h"
#include "object-store.h"
#include "repository.h"
#include "blob.h"
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 77d88f85b0..a5b466839b 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -33,6 +33,7 @@
#include "strvec.h"
#include "list.h"
#include "packfile.h"
+#include "object-file.h"
#include "object-store.h"
#include "replace-object.h"
#include "dir.h"
@@ -3359,16 +3360,16 @@ static void read_packs_list_from_stdin(void)
}
string_list_sort(&include_packs);
+ string_list_remove_duplicates(&include_packs, 0);
string_list_sort(&exclude_packs);
+ string_list_remove_duplicates(&exclude_packs, 0);
for (p = get_all_packs(the_repository); p; p = p->next) {
const char *pack_name = pack_basename(p);
- item = string_list_lookup(&include_packs, pack_name);
- if (!item)
- item = string_list_lookup(&exclude_packs, pack_name);
-
- if (item)
+ if ((item = string_list_lookup(&include_packs, pack_name)))
+ item->util = p;
+ if ((item = string_list_lookup(&exclude_packs, pack_name)))
item->util = p;
}
@@ -4293,9 +4294,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
}
reset_pack_idx_option(&pack_idx_opts);
+ pack_idx_opts.flags |= WRITE_REV;
git_config(git_pack_config, NULL);
- if (git_env_bool(GIT_TEST_WRITE_REV_INDEX, 0))
- pack_idx_opts.flags |= WRITE_REV;
+ if (git_env_bool(GIT_TEST_NO_WRITE_REV_INDEX, 0))
+ pack_idx_opts.flags &= ~WRITE_REV;
progress = isatty(2);
argc = parse_options(argc, argv, prefix, pack_objects_options,
diff --git a/builtin/prune.c b/builtin/prune.c
index 5c0952f5c6..5dc9b20720 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -11,6 +11,8 @@
#include "progress.h"
#include "prune-packed.h"
#include "replace-object.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "shallow.h"
diff --git a/builtin/pull.c b/builtin/pull.c
index 5405d09f22..0c7bac97b7 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -7,10 +7,12 @@
*/
#define USE_THE_INDEX_VARIABLE
#include "cache.h"
+#include "advice.h"
#include "config.h"
#include "builtin.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "parse-options.h"
#include "exec-cmd.h"
#include "run-command.h"
@@ -1045,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 fa550b8f80..dbdf609daf 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -2,6 +2,7 @@
* "git push"
*/
#include "cache.h"
+#include "advice.h"
#include "branch.h"
#include "config.h"
#include "environment.h"
@@ -13,9 +14,12 @@
#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"
+#include "trace2.h"
#include "color.h"
static const char * const push_usage[] = {
@@ -591,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),
@@ -638,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/range-diff.c b/builtin/range-diff.c
index b72af527f0..04339a92ea 100644
--- a/builtin/range-diff.c
+++ b/builtin/range-diff.c
@@ -1,6 +1,7 @@
#include "cache.h"
#include "builtin.h"
#include "gettext.h"
+#include "object-name.h"
#include "parse-options.h"
#include "range-diff.h"
#include "config.h"
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index 600d4f748f..440f19b1b8 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -11,6 +11,7 @@
#include "hex.h"
#include "lockfile.h"
#include "object.h"
+#include "object-name.h"
#include "tree.h"
#include "tree-walk.h"
#include "cache-tree.h"
@@ -18,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/rebase.c b/builtin/rebase.c
index 1ceac603c7..ace1d5e8d1 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -21,6 +21,8 @@
#include "cache-tree.h"
#include "unpack-trees.h"
#include "lockfile.h"
+#include "object-file.h"
+#include "object-name.h"
#include "parse-options.h"
#include "commit.h"
#include "diff.h"
@@ -32,6 +34,7 @@
#include "sequencer.h"
#include "rebase-interactive.h"
#include "reset.h"
+#include "trace2.h"
#include "hook.h"
#include "wrapper.h"
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 9109552533..1a31a58367 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -29,9 +29,13 @@
#include "tmp-objdir.h"
#include "oidset.h"
#include "packfile.h"
+#include "object-name.h"
#include "object-store.h"
#include "protocol.h"
#include "commit-reach.h"
+#include "server-info.h"
+#include "trace.h"
+#include "trace2.h"
#include "worktree.h"
#include "shallow.h"
#include "parse-options.h"
@@ -2093,7 +2097,7 @@ static struct command *read_head_info(struct packet_reader *reader,
const char *feature_list = reader->line + linelen + 1;
const char *hash = NULL;
const char *client_sid;
- int len = 0;
+ size_t len = 0;
if (parse_feature_request(feature_list, "report-status"))
report_status = 1;
if (parse_feature_request(feature_list, "report-status-v2"))
diff --git a/builtin/repack.c b/builtin/repack.c
index df4d8e0f0b..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"
@@ -325,7 +326,8 @@ static int geometry_cmp(const void *va, const void *vb)
}
static void init_pack_geometry(struct pack_geometry **geometry_p,
- struct string_list *existing_kept_packs)
+ struct string_list *existing_kept_packs,
+ const struct pack_objects_args *args)
{
struct packed_git *p;
struct pack_geometry *geometry;
@@ -335,6 +337,14 @@ static void init_pack_geometry(struct pack_geometry **geometry_p,
geometry = *geometry_p;
for (p = get_all_packs(the_repository); p; p = p->next) {
+ if (args->local && !p->pack_local)
+ /*
+ * When asked to only repack local packfiles we skip
+ * over any packfiles that are borrowed from alternate
+ * object directories.
+ */
+ continue;
+
if (!pack_kept_objects) {
/*
* Any pack that has its pack_keep bit set will appear
@@ -448,8 +458,10 @@ static void split_pack_geometry(struct pack_geometry *geometry, int factor)
geometry->split = split;
}
-static struct packed_git *get_largest_active_pack(struct pack_geometry *geometry)
+static struct packed_git *get_preferred_pack(struct pack_geometry *geometry)
{
+ uint32_t i;
+
if (!geometry) {
/*
* No geometry means either an all-into-one repack (in which
@@ -464,7 +476,21 @@ static struct packed_git *get_largest_active_pack(struct pack_geometry *geometry
}
if (geometry->split == geometry->pack_nr)
return NULL;
- return geometry->pack[geometry->pack_nr - 1];
+
+ /*
+ * The preferred pack is the largest pack above the split line. In
+ * other words, it is the largest pack that does not get rolled up in
+ * the geometric repack.
+ */
+ for (i = geometry->pack_nr; i > geometry->split; i--)
+ /*
+ * A pack that is not local would never be included in a
+ * multi-pack index. We thus skip over any non-local packs.
+ */
+ if (geometry->pack[i - 1]->pack_local)
+ return geometry->pack[i - 1];
+
+ return NULL;
}
static void clear_pack_geometry(struct pack_geometry *geometry)
@@ -558,6 +584,17 @@ static void midx_included_packs(struct string_list *include,
for (i = geometry->split; i < geometry->pack_nr; i++) {
struct packed_git *p = geometry->pack[i];
+ /*
+ * The multi-pack index never refers to packfiles part
+ * of an alternate object database, so we skip these.
+ * While git-multi-pack-index(1) would silently ignore
+ * them anyway, this allows us to skip executing the
+ * command completely when we have only non-local
+ * packfiles.
+ */
+ if (!p->pack_local)
+ continue;
+
strbuf_addstr(&buf, pack_basename(p));
strbuf_strip_suffix(&buf, ".pack");
strbuf_addstr(&buf, ".idx");
@@ -591,7 +628,7 @@ static int write_midx_included_packs(struct string_list *include,
{
struct child_process cmd = CHILD_PROCESS_INIT;
struct string_list_item *item;
- struct packed_git *largest = get_largest_active_pack(geometry);
+ struct packed_git *preferred = get_preferred_pack(geometry);
FILE *in;
int ret;
@@ -612,9 +649,9 @@ static int write_midx_included_packs(struct string_list *include,
if (write_bitmaps)
strvec_push(&cmd.args, "--bitmap");
- if (largest)
+ if (preferred)
strvec_pushf(&cmd.args, "--preferred-pack=%s",
- pack_basename(largest));
+ pack_basename(preferred));
if (refs_snapshot)
strvec_pushf(&cmd.args, "--refs-snapshot=%s", refs_snapshot);
@@ -774,7 +811,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
N_("same as -a, pack unreachable cruft objects separately"),
PACK_CRUFT),
OPT_STRING(0, "cruft-expiration", &cruft_expiration, N_("approxidate"),
- N_("with -C, expire objects older than this")),
+ N_("with --cruft, expire objects older than this")),
OPT_BOOL('d', NULL, &delete_redundant,
N_("remove redundant packs, and run git-prune-packed")),
OPT_BOOL('f', NULL, &po_args.no_reuse_delta,
@@ -853,6 +890,18 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
if (write_bitmaps && !(pack_everything & ALL_INTO_ONE) && !write_midx)
die(_(incremental_bitmap_conflict_error));
+ if (write_bitmaps && po_args.local && has_alt_odb(the_repository)) {
+ /*
+ * When asked to do a local repack, but we have
+ * packfiles that are inherited from an alternate, then
+ * we cannot guarantee that the multi-pack-index would
+ * have full coverage of all objects. We thus disable
+ * writing bitmaps in that case.
+ */
+ warning(_("disabling bitmap writing, as some objects are not being packed"));
+ write_bitmaps = 0;
+ }
+
if (write_midx && write_bitmaps) {
struct strbuf path = STRBUF_INIT;
@@ -875,7 +924,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
if (geometric_factor) {
if (pack_everything)
die(_("options '%s' and '%s' cannot be used together"), "--geometric", "-A/-a");
- init_pack_geometry(&geometry, &existing_kept_packs);
+ init_pack_geometry(&geometry, &existing_kept_packs, &po_args);
split_pack_geometry(geometry, geometric_factor);
}
diff --git a/builtin/replace.c b/builtin/replace.c
index d2adc8ab61..981f189443 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -11,12 +11,15 @@
#include "cache.h"
#include "config.h"
#include "builtin.h"
+#include "editor.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
#include "refs.h"
#include "parse-options.h"
#include "run-command.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "replace-object.h"
#include "repository.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/reset.c b/builtin/reset.c
index 0ed329236c..f99f32d580 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -9,6 +9,7 @@
*/
#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
+#include "advice.h"
#include "config.h"
#include "environment.h"
#include "gettext.h"
@@ -23,12 +24,15 @@
#include "diffcore.h"
#include "tree.h"
#include "branch.h"
+#include "object-name.h"
#include "parse-options.h"
#include "unpack-trees.h"
#include "cache-tree.h"
#include "setup.h"
#include "submodule.h"
#include "submodule-config.h"
+#include "trace.h"
+#include "trace2.h"
#include "dir.h"
#include "add-interactive.h"
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index a3dbbb6338..6dc8be492a 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -10,6 +10,8 @@
#include "list-objects-filter.h"
#include "list-objects-filter-options.h"
#include "object.h"
+#include "object-name.h"
+#include "object-file.h"
#include "object-store.h"
#include "pack.h"
#include "pack-bitmap.h"
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 1af2089f9b..852e49e340 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -15,6 +15,7 @@
#include "refs.h"
#include "quote.h"
#include "builtin.h"
+#include "object-name.h"
#include "parse-options.h"
#include "diff.h"
#include "revision.h"
diff --git a/builtin/rm.c b/builtin/rm.c
index 6be9281742..b4589c824c 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -12,8 +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 463a8d11c3..7ef4a642c1 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -2,13 +2,16 @@
#include "config.h"
#include "environment.h"
#include "gettext.h"
+#include "hash.h"
#include "hex.h"
#include "pretty.h"
#include "refs.h"
#include "builtin.h"
#include "color.h"
#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/show-ref.c b/builtin/show-ref.c
index 138d30a005..a2243b4219 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -4,6 +4,7 @@
#include "gettext.h"
#include "hex.h"
#include "refs.h"
+#include "object-name.h"
#include "object-store.h"
#include "object.h"
#include "tag.h"
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index 5e917ead7b..40d420f06c 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -4,6 +4,8 @@
#include "dir.h"
#include "environment.h"
#include "gettext.h"
+#include "object-file.h"
+#include "object-name.h"
#include "parse-options.h"
#include "pathspec.h"
#include "repository.h"
diff --git a/builtin/stash.c b/builtin/stash.c
index 735d27039e..a7e17ffe38 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -5,6 +5,7 @@
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "parse-options.h"
#include "refs.h"
#include "lockfile.h"
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 569068e6a2..6bf8d666ce 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -24,6 +24,8 @@
#include "revision.h"
#include "diffcore.h"
#include "diff.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "advice.h"
#include "branch.h"
diff --git a/builtin/tag.c b/builtin/tag.c
index 782bb3aa2f..1850a6a6fd 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -7,12 +7,15 @@
*/
#include "cache.h"
+#include "advice.h"
#include "config.h"
#include "builtin.h"
+#include "editor.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
#include "refs.h"
+#include "object-name.h"
#include "object-store.h"
#include "tag.h"
#include "run-command.h"
@@ -41,6 +44,7 @@ static const char * const git_tag_usage[] = {
static unsigned int colopts;
static int force_sign_annotate;
static int config_sign_tag = -1; /* unspecified */
+static int omit_empty = 0;
static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting,
struct ref_format *format)
@@ -79,7 +83,8 @@ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting,
if (format_ref_array_item(array.items[i], format, &output, &err))
die("%s", err.buf);
fwrite(output.buf, 1, output.len, stdout);
- putchar('\n');
+ if (output.len || !omit_empty)
+ putchar('\n');
}
strbuf_release(&err);
@@ -474,6 +479,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
OPT_WITHOUT(&filter.no_commit, N_("print only tags that don't contain the commit")),
OPT_MERGED(&filter, N_("print only tags that are merged")),
OPT_NO_MERGED(&filter, N_("print only tags that are not merged")),
+ OPT_BOOL(0, "omit-empty", &omit_empty,
+ N_("do not output a newline after empty formatted refs")),
OPT_REF_SORT(&sorting_options),
{
OPTION_CALLBACK, 0, "points-at", &filter.points_at, N_("object"),
diff --git a/builtin/unpack-file.c b/builtin/unpack-file.c
index 00179180c7..b35a4b9dfe 100644
--- a/builtin/unpack-file.c
+++ b/builtin/unpack-file.c
@@ -1,6 +1,7 @@
#include "builtin.h"
#include "config.h"
#include "hex.h"
+#include "object-name.h"
#include "object-store.h"
#include "wrapper.h"
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 585e81b106..2c52c3a741 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -4,6 +4,7 @@
#include "config.h"
#include "environment.h"
#include "gettext.h"
+#include "git-zlib.h"
#include "hex.h"
#include "object-store.h"
#include "object.h"
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 03cda5e60d..5fab9ad2ec 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -9,19 +9,23 @@
#include "config.h"
#include "environment.h"
#include "gettext.h"
+#include "hash.h"
#include "hex.h"
#include "lockfile.h"
#include "quote.h"
#include "cache-tree.h"
#include "tree-walk.h"
#include "builtin.h"
+#include "object-file.h"
#include "refs.h"
#include "resolve-undo.h"
#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 3ffd75b3e7..0c59b1c9ef 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -1,10 +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/var.c b/builtin/var.c
index acb988d2d5..2149998980 100644
--- a/builtin/var.c
+++ b/builtin/var.c
@@ -5,7 +5,9 @@
*/
#include "builtin.h"
#include "config.h"
+#include "editor.h"
#include "ident.h"
+#include "pager.h"
#include "refs.h"
static const char var_usage[] = "git var (-l | <variable>)";
diff --git a/builtin/verify-commit.c b/builtin/verify-commit.c
index 4d10aa98b1..5d99b82a64 100644
--- a/builtin/verify-commit.c
+++ b/builtin/verify-commit.c
@@ -9,6 +9,7 @@
#include "config.h"
#include "builtin.h"
#include "gettext.h"
+#include "object-name.h"
#include "object-store.h"
#include "repository.h"
#include "commit.h"
diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c
index 28d0da6845..c6019a0ad8 100644
--- a/builtin/verify-tag.c
+++ b/builtin/verify-tag.c
@@ -11,6 +11,7 @@
#include "gettext.h"
#include "tag.h"
#include "run-command.h"
+#include "object-name.h"
#include "parse-options.h"
#include "gpg-interface.h"
#include "ref-filter.h"
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 39e9e5c9ce..f3180463be 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -2,15 +2,19 @@
#include "abspath.h"
#include "checkout.h"
#include "config.h"
+#include "copy.h"
#include "builtin.h"
#include "dir.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-file.h"
+#include "object-name.h"
#include "parse-options.h"
#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/bulk-checkin.c b/bulk-checkin.c
index 6362b6aabc..d843279715 100644
--- a/bulk-checkin.c
+++ b/bulk-checkin.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2011, Google Inc.
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "bulk-checkin.h"
#include "environment.h"
@@ -15,7 +15,9 @@
#include "string-list.h"
#include "tmp-objdir.h"
#include "packfile.h"
+#include "object-file.h"
#include "object-store.h"
+#include "wrapper.h"
static int odb_transaction_nesting;
diff --git a/bundle-uri.c b/bundle-uri.c
index e2b267cc02..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"
@@ -795,10 +796,10 @@ int fetch_bundle_uri(struct repository *r, const char *uri,
init_bundle_list(&list);
/*
- * Do not fetch a NULL or empty bundle URI. An empty bundle URI
+ * Do not fetch an empty bundle URI. An empty bundle URI
* could signal that a configured bundle URI has been disabled.
*/
- if (!uri || !*uri) {
+ if (!*uri) {
result = 0;
goto cleanup;
}
diff --git a/bundle.c b/bundle.c
index 6471489975..a5505368de 100644
--- a/bundle.c
+++ b/bundle.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "lockfile.h"
#include "bundle.h"
#include "environment.h"
diff --git a/cache-tree.c b/cache-tree.c
index ff14b527da..ebfe649b33 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -7,10 +7,13 @@
#include "tree-walk.h"
#include "cache-tree.h"
#include "bulk-checkin.h"
+#include "object-file.h"
#include "object-store.h"
#include "replace-object.h"
#include "promisor-remote.h"
#include "sparse-index.h"
+#include "trace.h"
+#include "trace2.h"
#ifndef DEBUG_CACHE_TREE
#define DEBUG_CACHE_TREE 0
diff --git a/cache.h b/cache.h
index 82d7b112b4..bdedb87e83 100644
--- a/cache.h
+++ b/cache.h
@@ -4,108 +4,9 @@
#include "git-compat-util.h"
#include "strbuf.h"
#include "hashmap.h"
-#include "list.h"
-#include "advice.h"
-#include "gettext.h"
-#include "convert.h"
-#include "trace.h"
-#include "trace2.h"
-#include "string-list.h"
-#include "pack-revindex.h"
-#include "hash.h"
-#include "path.h"
#include "pathspec.h"
#include "object.h"
-#include "oid-array.h"
-#include "repository.h"
#include "statinfo.h"
-#include "mem-pool.h"
-
-typedef struct git_zstream {
- z_stream z;
- unsigned long avail_in;
- unsigned long avail_out;
- unsigned long total_in;
- unsigned long total_out;
- unsigned char *next_in;
- unsigned char *next_out;
-} git_zstream;
-
-void git_inflate_init(git_zstream *);
-void git_inflate_init_gzip_only(git_zstream *);
-void git_inflate_end(git_zstream *);
-int git_inflate(git_zstream *, int flush);
-
-void git_deflate_init(git_zstream *, int level);
-void git_deflate_init_gzip(git_zstream *, int level);
-void git_deflate_init_raw(git_zstream *, int level);
-void git_deflate_end(git_zstream *);
-int git_deflate_abort(git_zstream *);
-int git_deflate_end_gently(git_zstream *);
-int git_deflate(git_zstream *, int flush);
-unsigned long git_deflate_bound(git_zstream *, unsigned long);
-
-#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
-
-/* unknown mode (impossible combination S_IFIFO|S_IFCHR) */
-#define S_IFINVALID 0030000
-
-/*
- * A "directory link" is a link to another git directory.
- *
- * The value 0160000 is not normally a valid mode, and
- * also just happens to be S_IFDIR + S_IFLNK
- */
-#define S_IFGITLINK 0160000
-#define S_ISGITLINK(m) (((m) & S_IFMT) == S_IFGITLINK)
-
-/*
- * 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
-
-
-/*
- * Intensive research over the course of many years has shown that
- * port 9418 is totally unused by anything else. Or
- *
- * Your search - "port 9418" - did not match any documents.
- *
- * as www.google.com puts it.
- *
- * This port has been properly assigned for git use by IANA:
- * git (Assigned-9418) [I06-050728-0001].
- *
- * git 9418/tcp git pack transfer service
- * git 9418/udp git pack transfer service
- *
- * with Linus Torvalds <torvalds@osdl.org> as the point of
- * contact. September 2005.
- *
- * See http://www.iana.org/assignments/port-numbers
- */
-#define DEFAULT_GIT_PORT 9418
/*
* Basic data structures for the directory cache
@@ -186,11 +87,8 @@ struct cache_entry {
#error "CE_EXTENDED_FLAGS out of range"
#endif
-#define S_ISSPARSEDIR(m) ((m) == S_IFDIR)
-
/* Forward structure decls */
struct pathspec;
-struct child_process;
struct tree;
/*
@@ -228,17 +126,6 @@ static inline unsigned create_ce_flags(unsigned stage)
#define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE)
#define ce_intent_to_add(ce) ((ce)->ce_flags & CE_INTENT_TO_ADD)
-#define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644)
-static inline unsigned int create_ce_mode(unsigned int mode)
-{
- if (S_ISLNK(mode))
- return S_IFLNK;
- if (S_ISSPARSEDIR(mode))
- return S_IFDIR;
- if (S_ISDIR(mode) || S_ISGITLINK(mode))
- return S_IFGITLINK;
- return S_IFREG | ce_permissions(mode);
-}
static inline unsigned int ce_mode_from_stat(const struct cache_entry *ce,
unsigned int mode)
{
@@ -265,16 +152,6 @@ static inline int ce_to_dtype(const struct cache_entry *ce)
else
return DT_UNKNOWN;
}
-static inline unsigned int canon_mode(unsigned int mode)
-{
- if (S_ISREG(mode))
- return S_IFREG | ce_permissions(mode);
- if (S_ISLNK(mode))
- return S_IFLNK;
- if (S_ISDIR(mode))
- return S_IFDIR;
- return S_IFGITLINK;
-}
static inline int ce_path_match(struct index_state *istate,
const struct cache_entry *ce,
@@ -445,13 +322,6 @@ void prefetch_cache_entries(const struct index_state *istate,
extern struct index_state the_index;
#endif
-static inline enum object_type object_type(unsigned int mode)
-{
- return S_ISDIR(mode) ? OBJ_TREE :
- S_ISGITLINK(mode) ? OBJ_COMMIT :
- OBJ_BLOB;
-}
-
#define INIT_DB_QUIET 0x0001
#define INIT_DB_EXIST_OK 0x0002
@@ -626,13 +496,6 @@ int has_racy_timestamp(struct index_state *istate);
int ie_match_stat(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
int ie_modified(struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
-#define HASH_WRITE_OBJECT 1
-#define HASH_FORMAT_CHECK 2
-#define HASH_RENORMALIZE 4
-#define HASH_SILENT 8
-int index_fd(struct index_state *istate, struct object_id *oid, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
-int index_path(struct index_state *istate, struct object_id *oid, const char *path, struct stat *st, unsigned flags);
-
/*
* Record to sd the data from st that we use to check whether a file
* might have changed.
@@ -684,8 +547,6 @@ void set_alternate_index_output(const char *);
extern int verify_index_checksum;
extern int verify_ce_order;
-extern int quote_path_fully;
-
#define MTIME_CHANGED 0x0001
#define CTIME_CHANGED 0x0002
#define OWNER_CHANGED 0x0004
@@ -694,307 +555,7 @@ extern int quote_path_fully;
#define DATA_CHANGED 0x0020
#define TYPE_CHANGED 0x0040
-/*
- * Return an abbreviated sha1 unique within this repository's object database.
- * The result will be at least `len` characters long, and will be NUL
- * terminated.
- *
- * The non-`_r` version returns a static buffer which remains valid until 4
- * more calls to repo_find_unique_abbrev are made.
- *
- * The `_r` variant writes to a buffer supplied by the caller, which must be at
- * least `GIT_MAX_HEXSZ + 1` bytes. The return value is the number of bytes
- * written (excluding the NUL terminator).
- *
- * Note that while this version avoids the static buffer, it is not fully
- * reentrant, as it calls into other non-reentrant git code.
- */
-const char *repo_find_unique_abbrev(struct repository *r, const struct object_id *oid, int len);
-int repo_find_unique_abbrev_r(struct repository *r, char *hex, const struct object_id *oid, int len);
-
-/*
- * Create the directory containing the named path, using care to be
- * somewhat safe against races. Return one of the scld_error values to
- * indicate success/failure. On error, set errno to describe the
- * problem.
- *
- * SCLD_VANISHED indicates that one of the ancestor directories of the
- * path existed at one point during the function call and then
- * suddenly vanished, probably because another process pruned the
- * directory while we were working. To be robust against this kind of
- * race, callers might want to try invoking the function again when it
- * returns SCLD_VANISHED.
- *
- * safe_create_leading_directories() temporarily changes path while it
- * is working but restores it before returning.
- * safe_create_leading_directories_const() doesn't modify path, even
- * temporarily. Both these variants adjust the permissions of the
- * created directories to honor core.sharedRepository, so they are best
- * suited for files inside the git dir. For working tree files, use
- * safe_create_leading_directories_no_share() instead, as it ignores
- * the core.sharedRepository setting.
- */
-enum scld_error {
- SCLD_OK = 0,
- SCLD_FAILED = -1,
- SCLD_PERMS = -2,
- SCLD_EXISTS = -3,
- SCLD_VANISHED = -4
-};
-enum scld_error safe_create_leading_directories(char *path);
-enum scld_error safe_create_leading_directories_const(const char *path);
-enum scld_error safe_create_leading_directories_no_share(char *path);
-
-int mkdir_in_gitdir(const char *path);
-
-int git_open_cloexec(const char *name, int flags);
-#define git_open(name) git_open_cloexec(name, O_RDONLY)
-
-/**
- * unpack_loose_header() initializes the data stream needed to unpack
- * a loose object header.
- *
- * Returns:
- *
- * - ULHR_OK on success
- * - ULHR_BAD on error
- * - ULHR_TOO_LONG if the header was too long
- *
- * It will only parse up to MAX_HEADER_LEN bytes unless an optional
- * "hdrbuf" argument is non-NULL. This is intended for use with
- * OBJECT_INFO_ALLOW_UNKNOWN_TYPE to extract the bad type for (error)
- * reporting. The full header will be extracted to "hdrbuf" for use
- * with parse_loose_header(), ULHR_TOO_LONG will still be returned
- * from this function to indicate that the header was too long.
- */
-enum unpack_loose_header_result {
- ULHR_OK,
- ULHR_BAD,
- ULHR_TOO_LONG,
-};
-enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
- unsigned char *map,
- unsigned long mapsize,
- void *buffer,
- unsigned long bufsiz,
- struct strbuf *hdrbuf);
-
-/**
- * parse_loose_header() parses the starting "<type> <len>\0" of an
- * object. If it doesn't follow that format -1 is returned. To check
- * the validity of the <type> populate the "typep" in the "struct
- * object_info". It will be OBJ_BAD if the object type is unknown. The
- * parsed <len> can be retrieved via "oi->sizep", and from there
- * passed to unpack_loose_rest().
- */
-struct object_info;
-int parse_loose_header(const char *hdr, struct object_info *oi);
-
-/**
- * With in-core object data in "buf", rehash it to make sure the
- * object name actually matches "oid" to detect object corruption.
- *
- * A negative value indicates an error, usually that the OID is not
- * what we expected, but it might also indicate another error.
- */
-int check_object_signature(struct repository *r, const struct object_id *oid,
- void *map, unsigned long size,
- enum object_type type);
-
-/**
- * A streaming version of check_object_signature().
- * Try reading the object named with "oid" using
- * the streaming interface and rehash it to do the same.
- */
-int stream_object_signature(struct repository *r, const struct object_id *oid);
-
-int finalize_object_file(const char *tmpfile, const char *filename);
-
-/* Helper to check and "touch" a file */
-int check_and_freshen_file(const char *fn, int freshen);
-
-/* Convert to/from hex/sha1 representation */
-#define MINIMUM_ABBREV minimum_abbrev
-#define DEFAULT_ABBREV default_abbrev
-
-/* used when the code does not know or care what the default abbrev is */
-#define FALLBACK_DEFAULT_ABBREV 7
-
-struct object_context {
- unsigned short mode;
- /*
- * symlink_path is only used by get_tree_entry_follow_symlinks,
- * and only for symlinks that point outside the repository.
- */
- struct strbuf symlink_path;
- /*
- * If GET_OID_RECORD_PATH is set, this will record path (if any)
- * found when resolving the name. The caller is responsible for
- * releasing the memory.
- */
- char *path;
-};
-
-int repo_get_oid(struct repository *r, const char *str, struct object_id *oid);
-__attribute__((format (printf, 2, 3)))
-int get_oidf(struct object_id *oid, const char *fmt, ...);
-int repo_get_oid_commit(struct repository *r, const char *str, struct object_id *oid);
-int repo_get_oid_committish(struct repository *r, const char *str, struct object_id *oid);
-int repo_get_oid_tree(struct repository *r, const char *str, struct object_id *oid);
-int repo_get_oid_treeish(struct repository *r, const char *str, struct object_id *oid);
-int repo_get_oid_blob(struct repository *r, const char *str, struct object_id *oid);
-int repo_get_oid_mb(struct repository *r, const char *str, struct object_id *oid);
-void maybe_die_on_misspelt_object_name(struct repository *repo,
- const char *name,
- const char *prefix);
-enum get_oid_result get_oid_with_context(struct repository *repo, const char *str,
- unsigned flags, struct object_id *oid,
- struct object_context *oc);
-
-typedef int each_abbrev_fn(const struct object_id *oid, void *);
-int repo_for_each_abbrev(struct repository *r, const char *prefix, each_abbrev_fn, void *);
-
-int set_disambiguate_hint_config(const char *var, const char *value);
-
-/*
- * This reads short-hand syntax that not only evaluates to a commit
- * object name, but also can act as if the end user spelled the name
- * of the branch from the command line.
- *
- * - "@{-N}" finds the name of the Nth previous branch we were on, and
- * places the name of the branch in the given buf and returns the
- * number of characters parsed if successful.
- *
- * - "<branch>@{upstream}" finds the name of the other ref that
- * <branch> is configured to merge with (missing <branch> defaults
- * to the current branch), and places the name of the branch in the
- * given buf and returns the number of characters parsed if
- * successful.
- *
- * If the input is not of the accepted format, it returns a negative
- * number to signal an error.
- *
- * If the input was ok but there are not N branch switches in the
- * reflog, it returns 0.
- */
-#define INTERPRET_BRANCH_LOCAL (1<<0)
-#define INTERPRET_BRANCH_REMOTE (1<<1)
-#define INTERPRET_BRANCH_HEAD (1<<2)
-struct interpret_branch_name_options {
- /*
- * If "allowed" is non-zero, it is a treated as a bitfield of allowable
- * expansions: local branches ("refs/heads/"), remote branches
- * ("refs/remotes/"), or "HEAD". If no "allowed" bits are set, any expansion is
- * allowed, even ones to refs outside of those namespaces.
- */
- unsigned allowed;
-
- /*
- * If ^{upstream} or ^{push} (or equivalent) is requested, and the
- * branch in question does not have such a reference, return -1 instead
- * of die()-ing.
- */
- unsigned nonfatal_dangling_mark : 1;
-};
-int repo_interpret_branch_name(struct repository *r,
- const char *str, int len,
- struct strbuf *buf,
- const struct interpret_branch_name_options *options);
-
-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);
-
-void *read_object_with_reference(struct repository *r,
- const struct object_id *oid,
- enum object_type required_type,
- unsigned long *size,
- struct object_id *oid_ret);
-
-struct object *repo_peel_to_type(struct repository *r,
- const char *name, int namelen,
- struct object *o, enum object_type);
-
-const char *git_editor(void);
-const char *git_sequence_editor(void);
-const char *git_pager(int stdout_is_tty);
-int is_terminal_dumb(void);
-
-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;
-};
-
-/*
- * Set this to 0 to prevent oid_object_info_extended() from fetching missing
- * blobs. This has a difference only if extensions.partialClone is set.
- *
- * Its default value is 1.
- */
-extern int fetch_if_missing;
-
-/* Dumb servers support */
-int update_server_info(int);
-
-extern const char *git_mailmap_file;
-extern const char *git_mailmap_blob;
-
-#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);
-
-/* pager.c */
-void setup_pager(void);
-int pager_in_use(void);
-extern int pager_use_color;
-int term_columns(void);
-void term_clear_line(void);
-int decimal_width(uintmax_t);
-int check_pager_config(const char *cmd);
-void prepare_pager_args(struct child_process *, const char *pager);
-
-/* 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 */
/*
@@ -1006,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);
@@ -1081,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/chdir-notify.c b/chdir-notify.c
index 929ec01b3a..0d7bc04607 100644
--- a/chdir-notify.c
+++ b/chdir-notify.c
@@ -1,8 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "chdir-notify.h"
#include "list.h"
+#include "path.h"
#include "strbuf.h"
+#include "trace.h"
struct chdir_notify_entry {
const char *name;
diff --git a/checkout.c b/checkout.c
index 1247b88224..4256e71a7c 100644
--- a/checkout.c
+++ b/checkout.c
@@ -1,8 +1,11 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "object-name.h"
#include "remote.h"
#include "refspec.h"
+#include "repository.h"
#include "checkout.h"
#include "config.h"
+#include "strbuf.h"
struct tracking_name_data {
/* const */ char *src_ref;
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/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh
index b098e10f52..a18b13a41d 100755
--- a/ci/run-build-and-tests.sh
+++ b/ci/run-build-and-tests.sh
@@ -27,7 +27,7 @@ linux-TEST-vars)
export GIT_TEST_MULTI_PACK_INDEX=1
export GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=1
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
- export GIT_TEST_WRITE_REV_INDEX=1
+ export GIT_TEST_NO_WRITE_REV_INDEX=1
export GIT_TEST_CHECKOUT_WORKERS=2
;;
linux-clang)
diff --git a/color.c b/color.c
index 672dcbb73a..83abb11eda 100644
--- a/color.c
+++ b/color.c
@@ -1,8 +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/column.c b/column.c
index fbf88639aa..ff2f0abf39 100644
--- a/column.c
+++ b/column.c
@@ -1,7 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "column.h"
#include "string-list.h"
+#include "pager.h"
#include "parse-options.h"
#include "run-command.h"
#include "utf8.h"
diff --git a/combine-diff.c b/combine-diff.c
index 44ef6a1a81..1e3cd7fb17 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -1,19 +1,23 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "object-store.h"
#include "commit.h"
+#include "convert.h"
#include "blob.h"
#include "diff.h"
#include "diffcore.h"
#include "environment.h"
#include "hex.h"
+#include "object-name.h"
#include "quote.h"
#include "xdiff-interface.h"
#include "xdiff/xmacros.h"
#include "log-tree.h"
#include "refs.h"
+#include "tree.h"
#include "userdiff.h"
#include "oid-array.h"
#include "revision.h"
+#include "wrapper.h"
static int compare_paths(const struct combine_diff_path *one,
const struct diff_filespec *two)
diff --git a/commit-graph.c b/commit-graph.c
index b1e737c01b..843bdb458d 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "gettext.h"
#include "hex.h"
@@ -11,7 +11,9 @@
#include "revision.h"
#include "hash-lookup.h"
#include "commit-graph.h"
+#include "object-file.h"
#include "object-store.h"
+#include "oid-array.h"
#include "alloc.h"
#include "hashmap.h"
#include "replace-object.h"
@@ -21,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 6d844da9a6..0fb9316931 100644
--- a/commit.c
+++ b/commit.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "tag.h"
#include "commit.h"
#include "commit-graph.h"
@@ -6,6 +6,7 @@
#include "gettext.h"
#include "hex.h"
#include "repository.h"
+#include "object-name.h"
#include "object-store.h"
#include "pkt-line.h"
#include "utf8.h"
@@ -25,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 **);
@@ -95,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;
@@ -106,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 b83cb5cf06..033778b3c5 100644
--- a/common-main.c
+++ b/common-main.c
@@ -1,8 +1,11 @@
-#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"
/*
* Many parts of Git have subprograms communicate via pipe, expect the
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/fsmonitor/fsm-listen-win32.c b/compat/fsmonitor/fsm-listen-win32.c
index 7b07b74ba5..677b1bbdec 100644
--- a/compat/fsmonitor/fsm-listen-win32.c
+++ b/compat/fsmonitor/fsm-listen-win32.c
@@ -4,6 +4,7 @@
#include "fsm-listen.h"
#include "fsmonitor--daemon.h"
#include "gettext.h"
+#include "trace2.h"
/*
* The documentation of ReadDirectoryChangesW() states that the maximum
diff --git a/compat/mingw.c b/compat/mingw.c
index 94c5a1daa4..d06cdc6254 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -12,6 +12,8 @@
#include "win32/lazyload.h"
#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/pread.c b/compat/pread.c
index 978cac4ec9..484e6d4c71 100644
--- a/compat/pread.c
+++ b/compat/pread.c
@@ -1,4 +1,5 @@
#include "../git-compat-util.h"
+#include "../wrapper.h"
ssize_t git_pread(int fd, void *buf, size_t count, off_t offset)
{
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/simple-ipc/ipc-unix-socket.c b/compat/simple-ipc/ipc-unix-socket.c
index 152db60a31..b2f4f22ce4 100644
--- a/compat/simple-ipc/ipc-unix-socket.c
+++ b/compat/simple-ipc/ipc-unix-socket.c
@@ -1,9 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "gettext.h"
#include "simple-ipc.h"
#include "strbuf.h"
#include "pkt-line.h"
#include "thread-utils.h"
+#include "trace2.h"
#include "unix-socket.h"
#include "unix-stream-server.h"
diff --git a/compat/simple-ipc/ipc-win32.c b/compat/simple-ipc/ipc-win32.c
index 997f614434..6adce3c650 100644
--- a/compat/simple-ipc/ipc-win32.c
+++ b/compat/simple-ipc/ipc-win32.c
@@ -5,6 +5,8 @@
#include "strbuf.h"
#include "pkt-line.h"
#include "thread-utils.h"
+#include "trace.h"
+#include "trace2.h"
#include "accctrl.h"
#include "aclapi.h"
diff --git a/compat/win32/trace2_win32_process_info.c b/compat/win32/trace2_win32_process_info.c
index a53fd92434..a4e33768f4 100644
--- a/compat/win32/trace2_win32_process_info.c
+++ b/compat/win32/trace2_win32_process_info.c
@@ -1,5 +1,7 @@
#include "../../cache.h"
#include "../../json-writer.h"
+#include "../../repository.h"
+#include "../../trace2.h"
#include "lazyload.h"
#include <Psapi.h>
#include <tlHelp32.h>
diff --git a/config.c b/config.c
index 493f47df8a..b79baf83e3 100644
--- a/config.c
+++ b/config.c
@@ -5,30 +5,37 @@
* Copyright (C) Johannes Schindelin, 2005
*
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
+#include "advice.h"
#include "alloc.h"
#include "date.h"
#include "branch.h"
#include "config.h"
+#include "convert.h"
#include "environment.h"
#include "gettext.h"
#include "ident.h"
#include "repository.h"
#include "lockfile.h"
+#include "mailmap.h"
#include "exec-cmd.h"
#include "strbuf.h"
#include "quote.h"
#include "hashmap.h"
#include "string-list.h"
+#include "object-name.h"
#include "object-store.h"
+#include "pager.h"
#include "utf8.h"
#include "dir.h"
#include "color.h"
#include "replace-object.h"
#include "refs.h"
#include "setup.h"
+#include "trace2.h"
#include "worktree.h"
+#include "ws.h"
#include "wrapper.h"
#include "write-or-die.h"
@@ -3652,9 +3659,10 @@ void git_config_set_multivar(const char *key, const char *value,
flags);
}
-static int section_name_match (const char *buf, const char *name)
+static size_t section_name_match (const char *buf, const char *name)
{
- int i = 0, j = 0, dot = 0;
+ size_t i = 0, j = 0;
+ int dot = 0;
if (buf[i] != '[')
return 0;
for (i = 1; buf[i] && buf[i] != ']'; i++) {
@@ -3707,6 +3715,8 @@ static int section_name_is_ok(const char *name)
return 1;
}
+#define GIT_CONFIG_MAX_LINE_LEN (512 * 1024)
+
/* if new_name == NULL, the section is removed instead */
static int git_config_copy_or_rename_section_in_file(const char *config_filename,
const char *old_name,
@@ -3716,11 +3726,12 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
char *filename_buf = NULL;
struct lock_file lock = LOCK_INIT;
int out_fd;
- char buf[1024];
+ struct strbuf buf = STRBUF_INIT;
FILE *config_file = NULL;
struct stat st;
struct strbuf copystr = STRBUF_INIT;
struct config_store_data store;
+ uint32_t line_nr = 0;
memset(&store, 0, sizeof(store));
@@ -3757,16 +3768,25 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
goto out;
}
- while (fgets(buf, sizeof(buf), config_file)) {
- unsigned i;
- int length;
+ while (!strbuf_getwholeline(&buf, config_file, '\n')) {
+ size_t i, length;
int is_section = 0;
- char *output = buf;
- for (i = 0; buf[i] && isspace(buf[i]); i++)
+ char *output = buf.buf;
+
+ line_nr++;
+
+ if (buf.len >= GIT_CONFIG_MAX_LINE_LEN) {
+ ret = error(_("refusing to work with overly long line "
+ "in '%s' on line %"PRIuMAX),
+ config_filename, (uintmax_t)line_nr);
+ goto out;
+ }
+
+ for (i = 0; buf.buf[i] && isspace(buf.buf[i]); i++)
; /* do nothing */
- if (buf[i] == '[') {
+ if (buf.buf[i] == '[') {
/* it's a section */
- int offset;
+ size_t offset;
is_section = 1;
/*
@@ -3783,7 +3803,7 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
strbuf_reset(&copystr);
}
- offset = section_name_match(&buf[i], old_name);
+ offset = section_name_match(&buf.buf[i], old_name);
if (offset > 0) {
ret++;
if (!new_name) {
@@ -3858,6 +3878,7 @@ out:
out_no_rollback:
free(filename_buf);
config_store_data_clear(&store);
+ strbuf_release(&buf);
return ret;
}
diff --git a/connect.c b/connect.c
index c0c8a38178..3a0186280c 100644
--- a/connect.c
+++ b/connect.c
@@ -1,5 +1,4 @@
#include "git-compat-util.h"
-#include "cache.h"
#include "config.h"
#include "environment.h"
#include "gettext.h"
@@ -14,6 +13,7 @@
#include "string-list.h"
#include "oid-array.h"
#include "transport.h"
+#include "trace2.h"
#include "strbuf.h"
#include "version.h"
#include "protocol.h"
@@ -22,7 +22,7 @@
static char *server_capabilities_v1;
static struct strvec server_capabilities_v2 = STRVEC_INIT;
-static const char *next_server_feature_value(const char *feature, int *len, int *offset);
+static const char *next_server_feature_value(const char *feature, size_t *len, size_t *offset);
static int check_ref(const char *name, unsigned int flags)
{
@@ -205,10 +205,10 @@ reject:
static void annotate_refs_with_symref_info(struct ref *ref)
{
struct string_list symref = STRING_LIST_INIT_DUP;
- int offset = 0;
+ size_t offset = 0;
while (1) {
- int len;
+ size_t len;
const char *val;
val = next_server_feature_value("symref", &len, &offset);
@@ -231,7 +231,7 @@ static void annotate_refs_with_symref_info(struct ref *ref)
static void process_capabilities(struct packet_reader *reader, int *linelen)
{
const char *feat_val;
- int feat_len;
+ size_t feat_len;
const char *line = reader->line;
int nul_location = strlen(line);
if (nul_location == *linelen)
@@ -263,7 +263,8 @@ static int process_dummy_ref(const struct packet_reader *reader)
return 0;
name++;
- return oideq(null_oid(), &oid) && !strcmp(name, "capabilities^{}");
+ return oideq(reader->hash_algo->null_oid, &oid) &&
+ !strcmp(name, "capabilities^{}");
}
static void check_no_capabilities(const char *line, int len)
@@ -595,9 +596,10 @@ struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
return list;
}
-const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp, int *offset)
+const char *parse_feature_value(const char *feature_list, const char *feature, size_t *lenp, size_t *offset)
{
- int len;
+ const char *orig_start = feature_list;
+ size_t len;
if (!feature_list)
return NULL;
@@ -616,19 +618,19 @@ const char *parse_feature_value(const char *feature_list, const char *feature, i
if (lenp)
*lenp = 0;
if (offset)
- *offset = found + len - feature_list;
+ *offset = found + len - orig_start;
return value;
}
/* feature with a value (e.g., "agent=git/1.2.3") */
else if (*value == '=') {
- int end;
+ size_t end;
value++;
end = strcspn(value, " \t\n");
if (lenp)
*lenp = end;
if (offset)
- *offset = value + end - feature_list;
+ *offset = value + end - orig_start;
return value;
}
/*
@@ -643,8 +645,8 @@ const char *parse_feature_value(const char *feature_list, const char *feature, i
int server_supports_hash(const char *desired, int *feature_supported)
{
- int offset = 0;
- int len;
+ size_t offset = 0;
+ size_t len;
const char *hash;
hash = next_server_feature_value("object-format", &len, &offset);
@@ -668,12 +670,12 @@ int parse_feature_request(const char *feature_list, const char *feature)
return !!parse_feature_value(feature_list, feature, NULL, NULL);
}
-static const char *next_server_feature_value(const char *feature, int *len, int *offset)
+static const char *next_server_feature_value(const char *feature, size_t *len, size_t *offset)
{
return parse_feature_value(server_capabilities_v1, feature, len, offset);
}
-const char *server_feature_value(const char *feature, int *len)
+const char *server_feature_value(const char *feature, size_t *len)
{
return parse_feature_value(server_capabilities_v1, feature, len, NULL);
}
diff --git a/connect.h b/connect.h
index f41a0b4c1f..1645126c17 100644
--- a/connect.h
+++ b/connect.h
@@ -12,14 +12,14 @@ int finish_connect(struct child_process *conn);
int git_connection_is_socket(struct child_process *conn);
int server_supports(const char *feature);
int parse_feature_request(const char *features, const char *feature);
-const char *server_feature_value(const char *feature, int *len_ret);
+const char *server_feature_value(const char *feature, size_t *len_ret);
int url_is_local_not_ssh(const char *url);
struct packet_reader;
enum protocol_version discover_version(struct packet_reader *reader);
int server_supports_hash(const char *desired, int *feature_supported);
-const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp, int *offset);
+const char *parse_feature_value(const char *feature_list, const char *feature, size_t *lenp, size_t *offset);
int server_supports_v2(const char *c);
void ensure_server_supports_v2(const char *c);
int server_feature_v2(const char *c, const char **v);
diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 76ee4ab1e5..2c030050ae 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -298,7 +298,7 @@ __git_ps1_colorize_gitstring ()
# variable, in that order.
__git_eread ()
{
- test -r "$1" && IFS=$'\r\n' read "$2" <"$1"
+ test -r "$1" && IFS=$'\r\n' read -r "$2" <"$1"
}
# see if a cherry-pick or revert is in progress, if the user has committed a
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/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
index 10c9c87839..7db4c45676 100755
--- a/contrib/subtree/git-subtree.sh
+++ b/contrib/subtree/git-subtree.sh
@@ -34,8 +34,8 @@ git subtree pull --prefix=<prefix> <repository> <ref>
git subtree push --prefix=<prefix> <repository> <refspec>
--
h,help show the help
-q quiet
-d show debug messages
+q,quiet quiet
+d,debug show debug messages
P,prefix= the name of the subdir to split out
options for 'split' (also: 'push')
annotate= add a prefix to commit message of new commits
diff --git a/convert.c b/convert.c
index da06e2f51c..7cf7bd0c88 100644
--- a/convert.c
+++ b/convert.c
@@ -1,5 +1,8 @@
#include "cache.h"
+#include "advice.h"
#include "config.h"
+#include "convert.h"
+#include "copy.h"
#include "gettext.h"
#include "hex.h"
#include "object-store.h"
@@ -9,6 +12,7 @@
#include "sigchain.h"
#include "pkt-line.h"
#include "sub-process.h"
+#include "trace.h"
#include "utf8.h"
#include "ll-merge.h"
#include "wrapper.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 db8a31a6ea..7139cc201d 100644
--- a/daemon.c
+++ b/daemon.c
@@ -1,9 +1,11 @@
-#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"
#include "setup.h"
#include "strbuf.h"
diff --git a/date.c b/date.c
index 1fb2cd1b53..619ada5b20 100644
--- a/date.c
+++ b/date.c
@@ -4,9 +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.
@@ -1366,20 +1368,6 @@ static timestamp_t approxidate_str(const char *date,
return (timestamp_t)update_tm(&tm, &now, 0);
}
-timestamp_t approxidate_relative(const char *date)
-{
- struct timeval tv;
- timestamp_t timestamp;
- int offset;
- int errors = 0;
-
- if (!parse_date_basic(date, &timestamp, &offset))
- return timestamp;
-
- get_time(&tv);
- return approxidate_str(date, (const struct timeval *) &tv, &errors);
-}
-
timestamp_t approxidate_careful(const char *date, int *error_ret)
{
struct timeval tv;
diff --git a/date.h b/date.h
index 5d4eaba0a9..6136212a19 100644
--- a/date.h
+++ b/date.h
@@ -68,7 +68,6 @@ int parse_expiry_date(const char *date, timestamp_t *timestamp);
void datestamp(struct strbuf *out);
#define approxidate(s) approxidate_careful((s), NULL)
timestamp_t approxidate_careful(const char *, int *);
-timestamp_t approxidate_relative(const char *date);
int date_overflows(timestamp_t date);
time_t tm_to_time_t(const struct tm *tm);
#endif
diff --git a/delta-islands.c b/delta-islands.c
index 40f2ccfb55..c824a5f6a4 100644
--- a/delta-islands.c
+++ b/delta-islands.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "attr.h"
#include "object.h"
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 4169dd8cb1..60e979dc1b 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -8,11 +8,14 @@
#include "diffcore.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "revision.h"
#include "cache-tree.h"
#include "unpack-trees.h"
#include "refs.h"
#include "submodule.h"
+#include "symlinks.h"
+#include "trace.h"
#include "dir.h"
#include "fsmonitor.h"
#include "commit-reach.h"
diff --git a/diff-no-index.c b/diff-no-index.c
index 934a24bee5..4296940f90 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -4,7 +4,7 @@
* Copyright (c) 2008 by Junio C Hamano
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "color.h"
#include "commit.h"
diff --git a/diff.c b/diff.c
index 78b0fdd8ca..3c88c37908 100644
--- a/diff.c
+++ b/diff.c
@@ -4,7 +4,9 @@
#include "cache.h"
#include "abspath.h"
#include "alloc.h"
+#include "base85.h"
#include "config.h"
+#include "convert.h"
#include "environment.h"
#include "gettext.h"
#include "tempfile.h"
@@ -28,13 +30,18 @@
#include "string-list.h"
#include "strvec.h"
#include "graph.h"
+#include "oid-array.h"
#include "packfile.h"
+#include "pager.h"
#include "parse-options.h"
#include "help.h"
#include "promisor-remote.h"
#include "dir.h"
+#include "object-file.h"
+#include "object-name.h"
#include "setup.h"
#include "strmap.h"
+#include "ws.h"
#include "wrapper.h"
#ifdef NO_FAST_WORKING_DIRECTORY
@@ -134,7 +141,7 @@ static int parse_dirstat_params(struct diff_options *options, const char *params
int i;
if (*params_copy)
- string_list_split_in_place(&params, params_copy, ',', -1);
+ string_list_split_in_place(&params, params_copy, ",", -1);
for (i = 0; i < params.nr; i++) {
const char *p = params.items[i].string;
if (!strcmp(p, "changes")) {
@@ -3000,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;
@@ -3089,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)
@@ -3133,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 18fd14c46b..a7469df3ac 100644
--- a/dir.c
+++ b/dir.c
@@ -9,9 +9,11 @@
#include "abspath.h"
#include "alloc.h"
#include "config.h"
+#include "convert.h"
#include "dir.h"
#include "environment.h"
#include "gettext.h"
+#include "object-file.h"
#include "object-store.h"
#include "attr.h"
#include "refs.h"
@@ -23,6 +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 d632d79066..38c5dbbb79 100644
--- a/editor.c
+++ b/editor.c
@@ -1,12 +1,17 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
+#include "advice.h"
#include "config.h"
+#include "editor.h"
#include "environment.h"
#include "gettext.h"
+#include "pager.h"
+#include "path.h"
#include "strbuf.h"
#include "strvec.h"
#include "run-command.h"
#include "sigchain.h"
+#include "wrapper.h"
#ifndef DEFAULT_EDITOR
#define DEFAULT_EDITOR "vi"
@@ -129,3 +134,31 @@ int launch_sequence_editor(const char *path, struct strbuf *buffer,
{
return launch_specified_editor(git_sequence_editor(), path, buffer, env);
}
+
+int strbuf_edit_interactively(struct strbuf *buffer, const char *path,
+ const char *const *env)
+{
+ char *path2 = NULL;
+ int fd, res = 0;
+
+ if (!is_absolute_path(path))
+ path = path2 = xstrdup(git_path("%s", path));
+
+ fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0)
+ res = error_errno(_("could not open '%s' for writing"), path);
+ else if (write_in_full(fd, buffer->buf, buffer->len) < 0) {
+ res = error_errno(_("could not write to '%s'"), path);
+ close(fd);
+ } else if (close(fd) < 0)
+ res = error_errno(_("could not close '%s'"), path);
+ else {
+ strbuf_reset(buffer);
+ if (launch_editor(path, buffer, env) < 0)
+ res = error_errno(_("could not edit '%s'"), path);
+ unlink(path);
+ }
+
+ free(path2);
+ return res;
+}
diff --git a/editor.h b/editor.h
new file mode 100644
index 0000000000..8016bb5e00
--- /dev/null
+++ b/editor.h
@@ -0,0 +1,34 @@
+#ifndef EDITOR_H
+#define EDITOR_H
+
+struct strbuf;
+
+const char *git_editor(void);
+const char *git_sequence_editor(void);
+int is_terminal_dumb(void);
+
+/**
+ * Launch the user preferred editor to edit a file and fill the buffer
+ * with the file's contents upon the user completing their editing. The
+ * third argument can be used to set the environment which the editor is
+ * run in. If the buffer is NULL the editor is launched as usual but the
+ * file's contents are not read into the buffer upon completion.
+ */
+int launch_editor(const char *path, struct strbuf *buffer,
+ const char *const *env);
+
+int launch_sequence_editor(const char *path, struct strbuf *buffer,
+ const char *const *env);
+
+/*
+ * In contrast to `launch_editor()`, this function writes out the contents
+ * of the specified file first, then clears the `buffer`, then launches
+ * the editor and reads back in the file contents into the `buffer`.
+ * Finally, it deletes the temporary file.
+ *
+ * If `path` is relative, it refers to a file in the `.git` directory.
+ */
+int strbuf_edit_interactively(struct strbuf *buffer, const char *path,
+ const char *const *env);
+
+#endif
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 63c697e7e9..28d18eaca8 100644
--- a/environment.c
+++ b/environment.c
@@ -7,9 +7,10 @@
* 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"
#include "environment.h"
#include "gettext.h"
#include "repository.h"
@@ -18,12 +19,14 @@
#include "fmt-merge-msg.h"
#include "commit.h"
#include "strvec.h"
+#include "object-file.h"
#include "object-store.h"
#include "replace-object.h"
#include "tmp-objdir.h"
#include "chdir-notify.h"
#include "setup.h"
#include "shallow.h"
+#include "trace.h"
#include "wrapper.h"
#include "write-or-die.h"
@@ -56,7 +59,6 @@ size_t packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE;
size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT;
size_t delta_base_cache_limit = 96 * 1024 * 1024;
unsigned long big_file_threshold = 512 * 1024 * 1024;
-int pager_use_color = 1;
const char *editor_program;
const char *askpass_program;
const char *excludes_file;
@@ -65,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 fae0d4b244..1e34e48c0e 100644
--- a/exec-cmd.c
+++ b/exec-cmd.c
@@ -3,8 +3,11 @@
#include "environment.h"
#include "exec-cmd.h"
#include "gettext.h"
+#include "path.h"
#include "quote.h"
#include "strvec.h"
+#include "trace.h"
+#include "trace2.h"
#if defined(RUNTIME_PREFIX)
diff --git a/fetch-pack.c b/fetch-pack.c
index 368f2ed25a..0f71054fba 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -1,7 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "repository.h"
#include "config.h"
+#include "date.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
@@ -17,6 +18,7 @@
#include "remote.h"
#include "run-command.h"
#include "connect.h"
+#include "trace2.h"
#include "transport.h"
#include "version.h"
#include "oid-array.h"
@@ -1099,7 +1101,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
struct ref *ref = copy_ref_list(orig_ref);
struct object_id oid;
const char *agent_feature;
- int agent_len;
+ size_t agent_len;
struct fetch_negotiator negotiator_alloc;
struct fetch_negotiator *negotiator;
@@ -1117,7 +1119,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
agent_supported = 1;
if (agent_len)
print_verbose(args, _("Server version is %.*s"),
- agent_len, agent_feature);
+ (int)agent_len, agent_feature);
}
if (!server_supports("session-id"))
diff --git a/fmt-merge-msg.c b/fmt-merge-msg.c
index 1886c92ddb..5af0d4715b 100644
--- a/fmt-merge-msg.c
+++ b/fmt-merge-msg.c
@@ -1,8 +1,9 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "config.h"
#include "environment.h"
#include "refs.h"
+#include "object-name.h"
#include "object-store.h"
#include "diff.h"
#include "diff-merges.h"
diff --git a/fsck.c b/fsck.c
index 8ef1b02234..3261ef9ec2 100644
--- a/fsck.c
+++ b/fsck.c
@@ -1,5 +1,6 @@
-#include "cache.h"
+#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/fsmonitor.c b/fsmonitor.c
index c956a347a2..28c083d4d8 100644
--- a/fsmonitor.c
+++ b/fsmonitor.c
@@ -7,6 +7,7 @@
#include "fsmonitor-ipc.h"
#include "run-command.h"
#include "strbuf.h"
+#include "trace2.h"
#define INDEX_EXTENSION_VERSION1 (1)
#define INDEX_EXTENSION_VERSION2 (2)
diff --git a/fsmonitor.h b/fsmonitor.h
index 778707b131..c67e0ebc09 100644
--- a/fsmonitor.h
+++ b/fsmonitor.h
@@ -4,6 +4,7 @@
#include "cache.h"
#include "dir.h"
#include "fsmonitor-settings.h"
+#include "trace.h"
extern struct trace_key trace_fsmonitor;
diff --git a/gettext.c b/gettext.c
index 5f34870830..f27e94407b 100644
--- a/gettext.c
+++ b/gettext.c
@@ -102,6 +102,8 @@ static void init_gettext_charset(const char *domain)
setlocale(LC_CTYPE, "C");
}
+int git_gettext_enabled = 0;
+
void git_setup_gettext(void)
{
const char *podir = getenv(GIT_TEXT_DOMAIN_DIR_ENVIRONMENT);
@@ -121,6 +123,8 @@ void git_setup_gettext(void)
init_gettext_charset("git");
textdomain("git");
+ git_gettext_enabled = 1;
+
free(p);
}
diff --git a/gettext.h b/gettext.h
index d209911ebb..484cafa562 100644
--- a/gettext.h
+++ b/gettext.h
@@ -29,9 +29,11 @@
#define FORMAT_PRESERVING(n) __attribute__((format_arg(n)))
#ifndef NO_GETTEXT
+extern int git_gettext_enabled;
void git_setup_gettext(void);
int gettext_width(const char *s);
#else
+#define git_gettext_enabled (0)
static inline void git_setup_gettext(void)
{
}
@@ -45,12 +47,16 @@ static inline FORMAT_PRESERVING(1) const char *_(const char *msgid)
{
if (!*msgid)
return "";
+ if (!git_gettext_enabled)
+ return msgid;
return gettext(msgid);
}
static inline FORMAT_PRESERVING(1) FORMAT_PRESERVING(2)
const char *Q_(const char *msgid, const char *plu, unsigned long n)
{
+ if (!git_gettext_enabled)
+ return n == 1 ? msgid : plu;
return ngettext(msgid, plu, n);
}
diff --git a/git-compat-util.h b/git-compat-util.h
index 4a200a9fb4..5b2b99c17c 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -878,12 +878,6 @@ int git_lstat(const char *, struct stat *);
#define pread git_pread
ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
#endif
-/*
- * Forward decl that will remind us if its twin in cache.h changes.
- * This function is used in compat/pread.c. But we can't include
- * cache.h there.
- */
-ssize_t read_in_full(int fd, void *buf, size_t count);
#ifdef NO_SETENV
#define setenv gitsetenv
diff --git a/git-send-email.perl b/git-send-email.perl
index fd8cd0d46f..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,16 +797,46 @@ 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.
+ my @real_files = ();
foreach my $f (@files) {
unless (-p $f) {
- validate_patch($f, $target_xfer_encoding);
+ push(@real_files, $f);
}
}
+
+ # Run the loop once again to avoid gaps in the counter due to FIFO
+ # arguments provided by the user.
+ my $num = 1;
+ my $num_files = scalar @real_files;
+ $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;
+ }
+ delete $ENV{GIT_SENDEMAIL_FILE_COUNTER};
+ delete $ENV{GIT_SENDEMAIL_FILE_TOTAL};
}
+@files = handle_backup_files(@files);
+
if (@files) {
unless ($quiet) {
print $_,"\n" for (@files);
@@ -1050,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) {
@@ -1221,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;
@@ -1502,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
@@ -1553,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;
@@ -1742,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);
@@ -1765,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) {
@@ -1900,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) {
@@ -1961,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) {
@@ -2006,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);
@@ -2023,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;
}
@@ -2095,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/zlib.c b/git-zlib.c
index d594cba3fc..d43bbeb6da 100644
--- a/zlib.c
+++ b/git-zlib.c
@@ -2,7 +2,8 @@
* zlib wrappers to make sure we don't silently miss errors
* at init time.
*/
-#include "cache.h"
+#include "git-compat-util.h"
+#include "git-zlib.h"
static const char *zerr_to_string(int status)
{
diff --git a/git-zlib.h b/git-zlib.h
new file mode 100644
index 0000000000..d8a670aff9
--- /dev/null
+++ b/git-zlib.h
@@ -0,0 +1,28 @@
+#ifndef GIT_ZLIB_H
+#define GIT_ZLIB_H
+
+typedef struct git_zstream {
+ z_stream z;
+ unsigned long avail_in;
+ unsigned long avail_out;
+ unsigned long total_in;
+ unsigned long total_out;
+ unsigned char *next_in;
+ unsigned char *next_out;
+} git_zstream;
+
+void git_inflate_init(git_zstream *);
+void git_inflate_init_gzip_only(git_zstream *);
+void git_inflate_end(git_zstream *);
+int git_inflate(git_zstream *, int flush);
+
+void git_deflate_init(git_zstream *, int level);
+void git_deflate_init_gzip(git_zstream *, int level);
+void git_deflate_init_raw(git_zstream *, int level);
+void git_deflate_end(git_zstream *);
+int git_deflate_abort(git_zstream *);
+int git_deflate_end_gently(git_zstream *);
+int git_deflate(git_zstream *, int flush);
+unsigned long git_deflate_bound(git_zstream *, unsigned long);
+
+#endif /* GIT_ZLIB_H */
diff --git a/git.c b/git.c
index de681f4f7c..45899be826 100644
--- a/git.c
+++ b/git.c
@@ -4,11 +4,14 @@
#include "exec-cmd.h"
#include "gettext.h"
#include "help.h"
+#include "pager.h"
#include "run-command.h"
#include "alias.h"
#include "replace-object.h"
#include "setup.h"
#include "shallow.h"
+#include "trace.h"
+#include "trace2.h"
#define RUN_SETUP (1<<0)
#define RUN_SETUP_GENTLY (1<<1)
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 aceeb08336..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"
@@ -650,7 +652,7 @@ int check_signature(struct signature_check *sigc,
gpg_interface_lazy_init();
sigc->result = 'N';
- sigc->trust_level = -1;
+ sigc->trust_level = TRUST_UNDEFINED;
fmt = get_format_by_sig(signature);
if (!fmt)
diff --git a/grep.c b/grep.c
index b86462a12a..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"
@@ -11,6 +12,7 @@
#include "commit.h"
#include "quote.h"
#include "help.h"
+#include "wrapper.h"
static int grep_source_load(struct grep_source *gs);
static int grep_source_is_binary(struct grep_source *gs,
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-backend.c b/http-backend.c
index 89aad1b42c..ac146d85c5 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -1,7 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "config.h"
#include "environment.h"
+#include "git-zlib.h"
#include "hex.h"
#include "repository.h"
#include "refs.h"
diff --git a/http-fetch.c b/http-fetch.c
index c874d3402d..fffda59267 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "exec-cmd.h"
#include "gettext.h"
diff --git a/http-push.c b/http-push.c
index 88b70f2c44..29cf9db34e 100644
--- a/http-push.c
+++ b/http-push.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "environment.h"
#include "hex.h"
#include "repository.h"
@@ -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/http-walker.c b/http-walker.c
index e5dadae377..bba306b2d5 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "repository.h"
#include "commit.h"
#include "hex.h"
diff --git a/http.c b/http.c
index d5d82c5230..bb58bb3e6a 100644
--- a/http.c
+++ b/http.c
@@ -12,10 +12,12 @@
#include "version.h"
#include "pkt-line.h"
#include "gettext.h"
+#include "trace.h"
#include "transport.h"
#include "packfile.h"
#include "protocol.h"
#include "string-list.h"
+#include "object-file.h"
#include "object-store.h"
static struct trace_key trace_curl = TRACE_KEY_INIT(CURL);
diff --git a/http.h b/http.h
index 77c042706c..3a409bccd4 100644
--- a/http.h
+++ b/http.h
@@ -1,7 +1,9 @@
#ifndef HTTP_H
#define HTTP_H
-#include "cache.h"
+struct packed_git;
+
+#include "git-zlib.h"
#include <curl/curl.h>
#include <curl/easy.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/list-objects-filter.c b/list-objects-filter.c
index 298ca08711..5d270ce598 100644
--- a/list-objects-filter.c
+++ b/list-objects-filter.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "dir.h"
#include "gettext.h"
@@ -15,6 +15,7 @@
#include "list-objects-filter-options.h"
#include "oidmap.h"
#include "oidset.h"
+#include "object-name.h"
#include "object-store.h"
/* Remember to update object flag allocation in object.h */
diff --git a/list-objects.c b/list-objects.c
index df18d10306..eecca721ac 100644
--- a/list-objects.c
+++ b/list-objects.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "tag.h"
#include "commit.h"
#include "gettext.h"
diff --git a/ll-merge.c b/ll-merge.c
index 8be38d3bd4..1993530688 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -4,13 +4,15 @@
* Copyright (c) 2007 Junio C Hamano
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
+#include "convert.h"
#include "attr.h"
#include "xdiff-interface.h"
#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 dbb088473e..f4b22a60cc 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -1,9 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "commit-reach.h"
#include "config.h"
#include "diff.h"
#include "environment.h"
#include "hex.h"
+#include "object-name.h"
#include "object-store.h"
#include "repository.h"
#include "tmp-objdir.h"
@@ -23,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/mailmap.c b/mailmap.c
index 74fd9db448..5dc5223c43 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -1,7 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "environment.h"
#include "string-list.h"
#include "mailmap.h"
+#include "object-name.h"
#include "object-store.h"
#include "setup.h"
diff --git a/mailmap.h b/mailmap.h
index 7e99fccb46..0f8fd2c586 100644
--- a/mailmap.h
+++ b/mailmap.h
@@ -3,6 +3,9 @@
struct string_list;
+extern const char *git_mailmap_file;
+extern const char *git_mailmap_blob;
+
int read_mailmap(struct string_list *map);
void clear_mailmap(struct string_list *map);
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 5bf64354d1..a50b095c47 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -31,12 +31,17 @@
#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"
+#include "oid-array.h"
#include "promisor-remote.h"
#include "revision.h"
#include "strmap.h"
#include "submodule-config.h"
#include "submodule.h"
+#include "trace2.h"
#include "tree.h"
#include "unpack-trees.h"
#include "xdiff-interface.h"
@@ -4718,14 +4723,14 @@ void merge_switch_to_result(struct merge_options *opt,
void merge_finalize(struct merge_options *opt,
struct merge_result *result)
{
- struct merge_options_internal *opti = result->priv;
-
if (opt->renormalize)
git_attr_set_direction(GIT_ATTR_CHECKIN);
assert(opt->priv == NULL);
- clear_or_reinit_internal_opts(opti, 0);
- FREE_AND_NULL(opti);
+ if (result->priv) {
+ clear_or_reinit_internal_opts(result->priv, 0);
+ FREE_AND_NULL(result->priv);
+ }
}
/*** Function Grouping: helper functions for merge_incore_*() ***/
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 ed5534eb57..8e87b6386d 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -22,12 +22,16 @@
#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"
#include "repository.h"
#include "revision.h"
#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 9af3e5de88..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"
@@ -8,6 +8,7 @@
#include "hex.h"
#include "lockfile.h"
#include "packfile.h"
+#include "object-file.h"
#include "object-store.h"
#include "hash-lookup.h"
#include "midx.h"
@@ -1330,17 +1331,17 @@ static int write_midx_internal(const char *object_dir,
}
if (preferred_pack_name) {
- int found = 0;
+ ctx.preferred_pack_idx = -1;
+
for (i = 0; i < ctx.nr; i++) {
if (!cmp_idx_or_pack_name(preferred_pack_name,
ctx.info[i].pack_name)) {
ctx.preferred_pack_idx = i;
- found = 1;
break;
}
}
- if (!found)
+ if (ctx.preferred_pack_idx == -1)
warning(_("unknown preferred pack: '%s'"),
preferred_pack_name);
} else if (ctx.nr &&
diff --git a/name-hash.c b/name-hash.c
index 2c2861efd1..fb13716e43 100644
--- a/name-hash.c
+++ b/name-hash.c
@@ -9,6 +9,7 @@
#include "environment.h"
#include "gettext.h"
#include "thread-utils.h"
+#include "trace.h"
#include "trace2.h"
#include "sparse-index.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-merge.c b/notes-merge.c
index c40107c3aa..233e49e319 100644
--- a/notes-merge.c
+++ b/notes-merge.c
@@ -1,7 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "advice.h"
#include "commit.h"
#include "gettext.h"
#include "refs.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "repository.h"
#include "diff.h"
@@ -13,6 +16,7 @@
#include "notes.h"
#include "notes-merge.h"
#include "strbuf.h"
+#include "trace.h"
#include "notes-utils.h"
#include "commit-reach.h"
#include "wrapper.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/notes.c b/notes.c
index 45fb7f22d1..f51a2d3630 100644
--- a/notes.c
+++ b/notes.c
@@ -1,8 +1,9 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "environment.h"
#include "hex.h"
#include "notes.h"
+#include "object-name.h"
#include "object-store.h"
#include "blob.h"
#include "tree.h"
@@ -963,7 +964,7 @@ void string_list_add_refs_from_colon_sep(struct string_list *list,
char *globs_copy = xstrdup(globs);
int i;
- string_list_split_in_place(&split, globs_copy, ':', -1);
+ string_list_split_in_place(&split, globs_copy, ":", -1);
string_list_remove_empty_items(&split, 0);
for (i = 0; i < split.nr; i++)
@@ -1019,13 +1020,13 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
t->root = (struct int_node *) xcalloc(1, sizeof(struct int_node));
t->first_non_note = NULL;
t->prev_non_note = NULL;
- t->ref = xstrdup_or_null(notes_ref);
+ t->ref = xstrdup(notes_ref);
t->update_ref = (flags & NOTES_INIT_WRITABLE) ? t->ref : NULL;
t->combine_notes = combine_notes;
t->initialized = 1;
t->dirty = 0;
- if (flags & NOTES_INIT_EMPTY || !notes_ref ||
+ if (flags & NOTES_INIT_EMPTY ||
repo_get_oid_treeish(the_repository, notes_ref, &object_oid))
return;
if (flags & NOTES_INIT_WRITABLE && read_ref(notes_ref, &object_oid))
diff --git a/object-file.c b/object-file.c
index 76b22ca75c..7c1af5c8db 100644
--- a/object-file.c
+++ b/object-file.c
@@ -6,10 +6,11 @@
* 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"
+#include "convert.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
@@ -35,7 +36,9 @@
#include "mergesort.h"
#include "quote.h"
#include "packfile.h"
+#include "object-file.h"
#include "object-store.h"
+#include "oidtree.h"
#include "promisor-remote.h"
#include "setup.h"
#include "submodule.h"
@@ -951,6 +954,12 @@ void prepare_alt_odb(struct repository *r)
r->objects->loaded_alternates = 1;
}
+int has_alt_odb(struct repository *r)
+{
+ prepare_alt_odb(r);
+ return !!r->objects->odb->next;
+}
+
/* Returns 1 if we have successfully freshened the file, 0 otherwise. */
static int freshen_file(const char *fn)
{
diff --git a/object-file.h b/object-file.h
new file mode 100644
index 0000000000..d6414610f8
--- /dev/null
+++ b/object-file.h
@@ -0,0 +1,131 @@
+#ifndef OBJECT_FILE_H
+#define OBJECT_FILE_H
+
+#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.
+ *
+ * Its default value is 1.
+ */
+extern int fetch_if_missing;
+
+#define HASH_WRITE_OBJECT 1
+#define HASH_FORMAT_CHECK 2
+#define HASH_RENORMALIZE 4
+#define HASH_SILENT 8
+int index_fd(struct index_state *istate, struct object_id *oid, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
+int index_path(struct index_state *istate, struct object_id *oid, const char *path, struct stat *st, unsigned flags);
+
+/*
+ * Create the directory containing the named path, using care to be
+ * somewhat safe against races. Return one of the scld_error values to
+ * indicate success/failure. On error, set errno to describe the
+ * problem.
+ *
+ * SCLD_VANISHED indicates that one of the ancestor directories of the
+ * path existed at one point during the function call and then
+ * suddenly vanished, probably because another process pruned the
+ * directory while we were working. To be robust against this kind of
+ * race, callers might want to try invoking the function again when it
+ * returns SCLD_VANISHED.
+ *
+ * safe_create_leading_directories() temporarily changes path while it
+ * is working but restores it before returning.
+ * safe_create_leading_directories_const() doesn't modify path, even
+ * temporarily. Both these variants adjust the permissions of the
+ * created directories to honor core.sharedRepository, so they are best
+ * suited for files inside the git dir. For working tree files, use
+ * safe_create_leading_directories_no_share() instead, as it ignores
+ * the core.sharedRepository setting.
+ */
+enum scld_error {
+ SCLD_OK = 0,
+ SCLD_FAILED = -1,
+ SCLD_PERMS = -2,
+ SCLD_EXISTS = -3,
+ SCLD_VANISHED = -4
+};
+enum scld_error safe_create_leading_directories(char *path);
+enum scld_error safe_create_leading_directories_const(const char *path);
+enum scld_error safe_create_leading_directories_no_share(char *path);
+
+int mkdir_in_gitdir(const char *path);
+
+int git_open_cloexec(const char *name, int flags);
+#define git_open(name) git_open_cloexec(name, O_RDONLY)
+
+/**
+ * unpack_loose_header() initializes the data stream needed to unpack
+ * a loose object header.
+ *
+ * Returns:
+ *
+ * - ULHR_OK on success
+ * - ULHR_BAD on error
+ * - ULHR_TOO_LONG if the header was too long
+ *
+ * It will only parse up to MAX_HEADER_LEN bytes unless an optional
+ * "hdrbuf" argument is non-NULL. This is intended for use with
+ * OBJECT_INFO_ALLOW_UNKNOWN_TYPE to extract the bad type for (error)
+ * reporting. The full header will be extracted to "hdrbuf" for use
+ * with parse_loose_header(), ULHR_TOO_LONG will still be returned
+ * from this function to indicate that the header was too long.
+ */
+enum unpack_loose_header_result {
+ ULHR_OK,
+ ULHR_BAD,
+ ULHR_TOO_LONG,
+};
+enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
+ unsigned char *map,
+ unsigned long mapsize,
+ void *buffer,
+ unsigned long bufsiz,
+ struct strbuf *hdrbuf);
+
+/**
+ * parse_loose_header() parses the starting "<type> <len>\0" of an
+ * object. If it doesn't follow that format -1 is returned. To check
+ * the validity of the <type> populate the "typep" in the "struct
+ * object_info". It will be OBJ_BAD if the object type is unknown. The
+ * parsed <len> can be retrieved via "oi->sizep", and from there
+ * passed to unpack_loose_rest().
+ */
+struct object_info;
+int parse_loose_header(const char *hdr, struct object_info *oi);
+
+/**
+ * With in-core object data in "buf", rehash it to make sure the
+ * object name actually matches "oid" to detect object corruption.
+ *
+ * A negative value indicates an error, usually that the OID is not
+ * what we expected, but it might also indicate another error.
+ */
+int check_object_signature(struct repository *r, const struct object_id *oid,
+ void *map, unsigned long size,
+ enum object_type type);
+
+/**
+ * A streaming version of check_object_signature().
+ * Try reading the object named with "oid" using
+ * the streaming interface and rehash it to do the same.
+ */
+int stream_object_signature(struct repository *r, const struct object_id *oid);
+
+int finalize_object_file(const char *tmpfile, const char *filename);
+
+/* Helper to check and "touch" a file */
+int check_and_freshen_file(const char *fn, int freshen);
+
+void *read_object_with_reference(struct repository *r,
+ const struct object_id *oid,
+ enum object_type required_type,
+ unsigned long *size,
+ struct object_id *oid_ret);
+
+#endif /* OBJECT_FILE_H */
diff --git a/object-name.c b/object-name.c
index f1edc0035b..6fc3fa595b 100644
--- a/object-name.c
+++ b/object-name.c
@@ -1,4 +1,6 @@
#include "cache.h"
+#include "object-name.h"
+#include "advice.h"
#include "config.h"
#include "environment.h"
#include "gettext.h"
@@ -12,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-name.h b/object-name.h
new file mode 100644
index 0000000000..1d63698f42
--- /dev/null
+++ b/object-name.h
@@ -0,0 +1,121 @@
+#ifndef OBJECT_NAME_H
+#define OBJECT_NAME_H
+
+#include "object.h"
+#include "strbuf.h"
+
+struct object_id;
+struct repository;
+
+struct object_context {
+ unsigned short mode;
+ /*
+ * symlink_path is only used by get_tree_entry_follow_symlinks,
+ * and only for symlinks that point outside the repository.
+ */
+ struct strbuf symlink_path;
+ /*
+ * If GET_OID_RECORD_PATH is set, this will record path (if any)
+ * found when resolving the name. The caller is responsible for
+ * releasing the memory.
+ */
+ char *path;
+};
+
+/*
+ * Return an abbreviated sha1 unique within this repository's object database.
+ * The result will be at least `len` characters long, and will be NUL
+ * terminated.
+ *
+ * The non-`_r` version returns a static buffer which remains valid until 4
+ * more calls to repo_find_unique_abbrev are made.
+ *
+ * The `_r` variant writes to a buffer supplied by the caller, which must be at
+ * least `GIT_MAX_HEXSZ + 1` bytes. The return value is the number of bytes
+ * written (excluding the NUL terminator).
+ *
+ * Note that while this version avoids the static buffer, it is not fully
+ * reentrant, as it calls into other non-reentrant git code.
+ */
+const char *repo_find_unique_abbrev(struct repository *r, const struct object_id *oid, int len);
+int repo_find_unique_abbrev_r(struct repository *r, char *hex, const struct object_id *oid, int len);
+
+int repo_get_oid(struct repository *r, const char *str, struct object_id *oid);
+__attribute__((format (printf, 2, 3)))
+int get_oidf(struct object_id *oid, const char *fmt, ...);
+int repo_get_oid_commit(struct repository *r, const char *str, struct object_id *oid);
+int repo_get_oid_committish(struct repository *r, const char *str, struct object_id *oid);
+int repo_get_oid_tree(struct repository *r, const char *str, struct object_id *oid);
+int repo_get_oid_treeish(struct repository *r, const char *str, struct object_id *oid);
+int repo_get_oid_blob(struct repository *r, const char *str, struct object_id *oid);
+int repo_get_oid_mb(struct repository *r, const char *str, struct object_id *oid);
+void maybe_die_on_misspelt_object_name(struct repository *repo,
+ const char *name,
+ const char *prefix);
+enum get_oid_result get_oid_with_context(struct repository *repo, const char *str,
+ unsigned flags, struct object_id *oid,
+ struct object_context *oc);
+
+
+typedef int each_abbrev_fn(const struct object_id *oid, void *);
+int repo_for_each_abbrev(struct repository *r, const char *prefix, each_abbrev_fn, void *);
+
+int set_disambiguate_hint_config(const char *var, const char *value);
+
+/*
+ * This reads short-hand syntax that not only evaluates to a commit
+ * object name, but also can act as if the end user spelled the name
+ * of the branch from the command line.
+ *
+ * - "@{-N}" finds the name of the Nth previous branch we were on, and
+ * places the name of the branch in the given buf and returns the
+ * number of characters parsed if successful.
+ *
+ * - "<branch>@{upstream}" finds the name of the other ref that
+ * <branch> is configured to merge with (missing <branch> defaults
+ * to the current branch), and places the name of the branch in the
+ * given buf and returns the number of characters parsed if
+ * successful.
+ *
+ * If the input is not of the accepted format, it returns a negative
+ * number to signal an error.
+ *
+ * If the input was ok but there are not N branch switches in the
+ * reflog, it returns 0.
+ */
+#define INTERPRET_BRANCH_LOCAL (1<<0)
+#define INTERPRET_BRANCH_REMOTE (1<<1)
+#define INTERPRET_BRANCH_HEAD (1<<2)
+struct interpret_branch_name_options {
+ /*
+ * If "allowed" is non-zero, it is a treated as a bitfield of allowable
+ * expansions: local branches ("refs/heads/"), remote branches
+ * ("refs/remotes/"), or "HEAD". If no "allowed" bits are set, any expansion is
+ * allowed, even ones to refs outside of those namespaces.
+ */
+ unsigned allowed;
+
+ /*
+ * If ^{upstream} or ^{push} (or equivalent) is requested, and the
+ * branch in question does not have such a reference, return -1 instead
+ * of die()-ing.
+ */
+ unsigned nonfatal_dangling_mark : 1;
+};
+int repo_interpret_branch_name(struct repository *r,
+ const char *str, int len,
+ struct strbuf *buf,
+ const struct interpret_branch_name_options *options);
+
+struct object *repo_peel_to_type(struct repository *r,
+ const char *name, int namelen,
+ struct object *o, enum object_type);
+
+/* Convert to/from hex/sha1 representation */
+#define MINIMUM_ABBREV minimum_abbrev
+#define DEFAULT_ABBREV default_abbrev
+
+/* used when the code does not know or care what the default abbrev is */
+#define FALLBACK_DEFAULT_ABBREV 7
+
+#endif /* OBJECT_NAME_H */
diff --git a/object-store.h b/object-store.h
index f9d225783a..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;
@@ -56,6 +56,7 @@ KHASH_INIT(odb_path_map, const char * /* key: odb_path */,
struct object_directory *, 1, fspathhash, fspatheq)
void prepare_alt_odb(struct repository *r);
+int has_alt_odb(struct repository *r);
char *compute_alternate_path(const char *path, struct strbuf *err);
struct object_directory *find_odb(struct repository *r, const char *obj_dir);
typedef int alt_odb_fn(struct object_directory *, void *);
diff --git a/object.c b/object.c
index 45c9721b8c..6d4ef1524d 100644
--- a/object.c
+++ b/object.c
@@ -3,6 +3,7 @@
#include "hex.h"
#include "object.h"
#include "replace-object.h"
+#include "object-file.h"
#include "object-store.h"
#include "blob.h"
#include "tree.h"
diff --git a/object.h b/object.h
index fc45b158da..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;
@@ -101,6 +102,50 @@ enum object_type {
OBJ_MAX
};
+/* unknown mode (impossible combination S_IFIFO|S_IFCHR) */
+#define S_IFINVALID 0030000
+
+/*
+ * A "directory link" is a link to another git directory.
+ *
+ * The value 0160000 is not normally a valid mode, and
+ * also just happens to be S_IFDIR + S_IFLNK
+ */
+#define S_IFGITLINK 0160000
+#define S_ISGITLINK(m) (((m) & S_IFMT) == S_IFGITLINK)
+
+#define S_ISSPARSEDIR(m) ((m) == S_IFDIR)
+
+static inline enum object_type object_type(unsigned int mode)
+{
+ return S_ISDIR(mode) ? OBJ_TREE :
+ S_ISGITLINK(mode) ? OBJ_COMMIT :
+ OBJ_BLOB;
+}
+
+#define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644)
+static inline unsigned int create_ce_mode(unsigned int mode)
+{
+ if (S_ISLNK(mode))
+ return S_IFLNK;
+ if (S_ISSPARSEDIR(mode))
+ return S_IFDIR;
+ if (S_ISDIR(mode) || S_ISGITLINK(mode))
+ return S_IFGITLINK;
+ return S_IFREG | ce_permissions(mode);
+}
+
+static inline unsigned int canon_mode(unsigned int mode)
+{
+ if (S_ISREG(mode))
+ return S_IFREG | ce_permissions(mode);
+ if (S_ISLNK(mode))
+ return S_IFLNK;
+ if (S_ISDIR(mode))
+ return S_IFDIR;
+ return S_IFGITLINK;
+}
+
/*
* The object type is stored in 3 bits.
*/
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 7f5f489beb..cdffe2ce47 100644
--- a/pack-bitmap-write.c
+++ b/pack-bitmap-write.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "environment.h"
#include "gettext.h"
@@ -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 b2e7d06d60..999f962602 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "commit.h"
#include "gettext.h"
@@ -15,6 +15,8 @@
#include "pack-objects.h"
#include "packfile.h"
#include "repository.h"
+#include "trace2.h"
+#include "object-file.h"
#include "object-store.h"
#include "list-objects-filter-options.h"
#include "midx.h"
@@ -379,7 +381,7 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git,
goto cleanup;
}
- if (load_midx_revindex(bitmap_git->midx) < 0) {
+ if (load_midx_revindex(bitmap_git->midx)) {
warning(_("multi-pack bitmap is missing required reverse index"));
goto cleanup;
}
@@ -463,7 +465,7 @@ static int open_pack_bitmap_1(struct bitmap_index *bitmap_git, struct packed_git
return 0;
}
-static int load_reverse_index(struct bitmap_index *bitmap_git)
+static int load_reverse_index(struct repository *r, struct bitmap_index *bitmap_git)
{
if (bitmap_is_midx(bitmap_git)) {
uint32_t i;
@@ -477,23 +479,23 @@ static int load_reverse_index(struct bitmap_index *bitmap_git)
* since we will need to make use of them in pack-objects.
*/
for (i = 0; i < bitmap_git->midx->num_packs; i++) {
- ret = load_pack_revindex(bitmap_git->midx->packs[i]);
+ ret = load_pack_revindex(r, bitmap_git->midx->packs[i]);
if (ret)
return ret;
}
return 0;
}
- return load_pack_revindex(bitmap_git->pack);
+ return load_pack_revindex(r, bitmap_git->pack);
}
-static int load_bitmap(struct bitmap_index *bitmap_git)
+static int load_bitmap(struct repository *r, struct bitmap_index *bitmap_git)
{
assert(bitmap_git->map);
bitmap_git->bitmaps = kh_init_oid_map();
bitmap_git->ext_index.positions = kh_init_oid_pos();
- if (load_reverse_index(bitmap_git))
+ if (load_reverse_index(r, bitmap_git))
goto failed;
if (!(bitmap_git->commits = read_bitmap_1(bitmap_git)) ||
@@ -580,7 +582,7 @@ struct bitmap_index *prepare_bitmap_git(struct repository *r)
{
struct bitmap_index *bitmap_git = xcalloc(1, sizeof(*bitmap_git));
- if (!open_bitmap(r, bitmap_git) && !load_bitmap(bitmap_git))
+ if (!open_bitmap(r, bitmap_git) && !load_bitmap(r, bitmap_git))
return bitmap_git;
free_bitmap_index(bitmap_git);
@@ -589,9 +591,10 @@ struct bitmap_index *prepare_bitmap_git(struct repository *r)
struct bitmap_index *prepare_midx_bitmap_git(struct multi_pack_index *midx)
{
+ struct repository *r = the_repository;
struct bitmap_index *bitmap_git = xcalloc(1, sizeof(*bitmap_git));
- if (!open_midx_bitmap_1(bitmap_git, midx) && !load_bitmap(bitmap_git))
+ if (!open_midx_bitmap_1(bitmap_git, midx) && !load_bitmap(r, bitmap_git))
return bitmap_git;
free_bitmap_index(bitmap_git);
@@ -1592,7 +1595,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
* from disk. this is the point of no return; after this the rev_list
* becomes invalidated and we must perform the revwalk through bitmaps
*/
- if (load_bitmap(bitmap_git) < 0)
+ if (load_bitmap(revs->repo, bitmap_git) < 0)
goto cleanup;
object_array_clear(&revs->pending);
@@ -1742,6 +1745,7 @@ int reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
uint32_t *entries,
struct bitmap **reuse_out)
{
+ struct repository *r = the_repository;
struct packed_git *pack;
struct bitmap *result = bitmap_git->result;
struct bitmap *reuse;
@@ -1752,7 +1756,7 @@ int reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
assert(result);
- load_reverse_index(bitmap_git);
+ load_reverse_index(r, bitmap_git);
if (bitmap_is_midx(bitmap_git))
pack = bitmap_git->midx->packs[midx_preferred_pack(bitmap_git)];
@@ -2132,12 +2136,13 @@ int rebuild_bitmap(const uint32_t *reposition,
uint32_t *create_bitmap_mapping(struct bitmap_index *bitmap_git,
struct packing_data *mapping)
{
+ struct repository *r = the_repository;
uint32_t i, num_objects;
uint32_t *reposition;
if (!bitmap_is_midx(bitmap_git))
- load_reverse_index(bitmap_git);
- else if (load_midx_revindex(bitmap_git->midx) < 0)
+ load_reverse_index(r, bitmap_git);
+ else if (load_midx_revindex(bitmap_git->midx))
BUG("rebuild_existing_bitmaps: missing required rev-cache "
"extension");
@@ -2341,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/pack-check.c b/pack-check.c
index 6974e40a95..049f2f0bfc 100644
--- a/pack-check.c
+++ b/pack-check.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "environment.h"
#include "hex.h"
#include "repository.h"
@@ -6,6 +6,7 @@
#include "pack-revindex.h"
#include "progress.h"
#include "packfile.h"
+#include "object-file.h"
#include "object-store.h"
struct idx_entry {
diff --git a/pack-mtimes.c b/pack-mtimes.c
index afed632190..020a37f8fe 100644
--- a/pack-mtimes.c
+++ b/pack-mtimes.c
@@ -1,6 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "gettext.h"
#include "pack-mtimes.h"
+#include "object-file.h"
#include "object-store.h"
#include "packfile.h"
diff --git a/pack-revindex.c b/pack-revindex.c
index 03c7e81f9d..1f51b712e8 100644
--- a/pack-revindex.c
+++ b/pack-revindex.c
@@ -1,10 +1,13 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "gettext.h"
#include "pack-revindex.h"
+#include "object-file.h"
#include "object-store.h"
#include "packfile.h"
+#include "trace2.h"
#include "config.h"
#include "midx.h"
+#include "csum-file.h"
struct revindex_entry {
off_t offset;
@@ -205,10 +208,14 @@ static int load_revindex_from_disk(char *revindex_name,
size_t revindex_size;
struct revindex_header *hdr;
+ if (git_env_bool(GIT_TEST_REV_INDEX_DIE_ON_DISK, 0))
+ die("dying as requested by '%s'", GIT_TEST_REV_INDEX_DIE_ON_DISK);
+
fd = git_open(revindex_name);
if (fd < 0) {
- ret = -1;
+ /* "No file" means return 1. */
+ ret = 1;
goto cleanup;
}
if (fstat(fd, &st)) {
@@ -260,7 +267,7 @@ cleanup:
return ret;
}
-static int load_pack_revindex_from_disk(struct packed_git *p)
+int load_pack_revindex_from_disk(struct packed_git *p)
{
char *revindex_name;
int ret;
@@ -283,18 +290,58 @@ cleanup:
return ret;
}
-int load_pack_revindex(struct packed_git *p)
+int load_pack_revindex(struct repository *r, struct packed_git *p)
{
if (p->revindex || p->revindex_data)
return 0;
- if (!load_pack_revindex_from_disk(p))
+ prepare_repo_settings(r);
+
+ if (r->settings.pack_read_reverse_index &&
+ !load_pack_revindex_from_disk(p))
return 0;
else if (!create_pack_revindex_in_memory(p))
return 0;
return -1;
}
+/*
+ * verify_pack_revindex verifies that the on-disk rev-index for the given
+ * pack-file is the same that would be created if written from scratch.
+ *
+ * A negative number is returned on error.
+ */
+int verify_pack_revindex(struct packed_git *p)
+{
+ int res = 0;
+
+ /* Do not bother checking if not initialized. */
+ if (!p->revindex_map || !p->revindex_data)
+ return res;
+
+ if (!hashfile_checksum_valid((const unsigned char *)p->revindex_map, p->revindex_size)) {
+ error(_("invalid checksum"));
+ res = -1;
+ }
+
+ /* This may fail due to a broken .idx. */
+ if (create_pack_revindex_in_memory(p))
+ return res;
+
+ for (size_t i = 0; i < p->num_objects; i++) {
+ uint32_t nr = p->revindex[i].nr;
+ uint32_t rev_val = get_be32(p->revindex_data + i);
+
+ if (nr != rev_val) {
+ error(_("invalid rev-index position at %"PRIu64": %"PRIu32" != %"PRIu32""),
+ (uint64_t)i, nr, rev_val);
+ res = -1;
+ }
+ }
+
+ return res;
+}
+
int load_midx_revindex(struct multi_pack_index *m)
{
struct strbuf revindex_name = STRBUF_INIT;
@@ -356,7 +403,7 @@ int offset_to_pack_pos(struct packed_git *p, off_t ofs, uint32_t *pos)
{
unsigned lo, hi;
- if (load_pack_revindex(p) < 0)
+ if (load_pack_revindex(the_repository, p) < 0)
return -1;
lo = 0;
diff --git a/pack-revindex.h b/pack-revindex.h
index 4974e75eb4..6dd47efea1 100644
--- a/pack-revindex.h
+++ b/pack-revindex.h
@@ -34,11 +34,13 @@
#define RIDX_SIGNATURE 0x52494458 /* "RIDX" */
#define RIDX_VERSION 1
-#define GIT_TEST_WRITE_REV_INDEX "GIT_TEST_WRITE_REV_INDEX"
+#define GIT_TEST_NO_WRITE_REV_INDEX "GIT_TEST_NO_WRITE_REV_INDEX"
#define GIT_TEST_REV_INDEX_DIE_IN_MEMORY "GIT_TEST_REV_INDEX_DIE_IN_MEMORY"
+#define GIT_TEST_REV_INDEX_DIE_ON_DISK "GIT_TEST_REV_INDEX_DIE_ON_DISK"
struct packed_git;
struct multi_pack_index;
+struct repository;
/*
* load_pack_revindex populates the revindex's internal data-structures for the
@@ -47,7 +49,23 @@ struct multi_pack_index;
* If a '.rev' file is present it is mmap'd, and pointers are assigned into it
* (instead of using the in-memory variant).
*/
-int load_pack_revindex(struct packed_git *p);
+int load_pack_revindex(struct repository *r, struct packed_git *p);
+
+/*
+ * Specifically load a pack revindex from disk.
+ *
+ * Returns 0 on success, 1 on "no .rev file", and -1 when there is an
+ * error parsing the .rev file.
+ */
+int load_pack_revindex_from_disk(struct packed_git *p);
+
+/*
+ * verify_pack_revindex verifies that the on-disk rev-index for the given
+ * pack-file is the same that would be created if written from scratch.
+ *
+ * A negative number is returned on error.
+ */
+int verify_pack_revindex(struct packed_git *p);
/*
* load_midx_revindex loads the '.rev' file corresponding to the given
diff --git a/pack-write.c b/pack-write.c
index f171405495..3b3ce89de6 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
@@ -9,6 +9,8 @@
#include "pack-mtimes.h"
#include "oidmap.h"
#include "pack-objects.h"
+#include "pack-revindex.h"
+#include "wrapper.h"
void reset_pack_idx_option(struct pack_idx_option *opts)
{
@@ -312,13 +314,13 @@ static void write_mtimes_trailer(struct hashfile *f, const unsigned char *hash)
hashwrite(f, hash, the_hash_algo->rawsz);
}
-static const char *write_mtimes_file(struct packing_data *to_pack,
- struct pack_idx_entry **objects,
- uint32_t nr_objects,
- const unsigned char *hash)
+static char *write_mtimes_file(struct packing_data *to_pack,
+ struct pack_idx_entry **objects,
+ uint32_t nr_objects,
+ const unsigned char *hash)
{
struct strbuf tmp_file = STRBUF_INIT;
- const char *mtimes_name;
+ char *mtimes_name;
struct hashfile *f;
int fd;
@@ -544,7 +546,7 @@ void stage_tmp_packfiles(struct strbuf *name_buffer,
char **idx_tmp_name)
{
const char *rev_tmp_name = NULL;
- const char *mtimes_tmp_name = NULL;
+ char *mtimes_tmp_name = NULL;
if (adjust_shared_perm(pack_tmp_name))
die_errno("unable to make temporary pack file readable");
@@ -568,6 +570,9 @@ void stage_tmp_packfiles(struct strbuf *name_buffer,
rename_tmp_packfile(name_buffer, rev_tmp_name, "rev");
if (mtimes_tmp_name)
rename_tmp_packfile(name_buffer, mtimes_tmp_name, "mtimes");
+
+ free((char *)rev_tmp_name);
+ free(mtimes_tmp_name);
}
void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought)
diff --git a/packfile.c b/packfile.c
index b120405ccc..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"
@@ -15,11 +15,14 @@
#include "commit.h"
#include "object.h"
#include "tag.h"
+#include "trace.h"
#include "tree-walk.h"
#include "tree.h"
+#include "object-file.h"
#include "object-store.h"
#include "midx.h"
#include "commit-graph.h"
+#include "pack-revindex.h"
#include "promisor-remote.h"
#include "wrapper.h"
@@ -2151,7 +2154,7 @@ int for_each_object_in_pack(struct packed_git *p,
int r = 0;
if (flags & FOR_EACH_OBJECT_PACK_ORDER) {
- if (load_pack_revindex(p))
+ if (load_pack_revindex(the_repository, p))
return -1;
}
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/pager.c b/pager.c
index b66bbff278..63055d0873 100644
--- a/pager.c
+++ b/pager.c
@@ -1,9 +1,13 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
+#include "editor.h"
+#include "pager.h"
#include "run-command.h"
#include "sigchain.h"
#include "alias.h"
+int pager_use_color = 1;
+
#ifndef DEFAULT_PAGER
#define DEFAULT_PAGER "less"
#endif
diff --git a/pager.h b/pager.h
new file mode 100644
index 0000000000..b77433026d
--- /dev/null
+++ b/pager.h
@@ -0,0 +1,17 @@
+#ifndef PAGER_H
+#define PAGER_H
+
+struct child_process;
+
+const char *git_pager(int stdout_is_tty);
+void setup_pager(void);
+int pager_in_use(void);
+int term_columns(void);
+void term_clear_line(void);
+int decimal_width(uintmax_t);
+int check_pager_config(const char *cmd);
+void prepare_pager_args(struct child_process *, const char *pager);
+
+extern int pager_use_color;
+
+#endif /* PAGER_H */
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 10f2f75e83..a24521dee0 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -1,11 +1,12 @@
#include "git-compat-util.h"
#include "parse-options.h"
#include "branch.h"
-#include "cache.h"
#include "commit.h"
#include "color.h"
+#include "date.h"
#include "environment.h"
#include "gettext.h"
+#include "object-name.h"
#include "string-list.h"
#include "strvec.h"
#include "oid-array.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/path.c b/path.c
index dff215ac69..7c1cd8182a 100644
--- a/path.c
+++ b/path.c
@@ -18,6 +18,7 @@
#include "object-store.h"
#include "lockfile.h"
#include "exec-cmd.h"
+#include "wrapper.h"
static int get_st_mode_bits(const char *path, int *mode)
{
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 36ae0fea4a..62b4208b66 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -1,8 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "copy.h"
#include "pkt-line.h"
#include "gettext.h"
#include "hex.h"
#include "run-command.h"
+#include "trace.h"
#include "wrapper.h"
#include "write-or-die.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 52544d004e..7a26b08c21 100644
--- a/preload-index.c
+++ b/preload-index.c
@@ -11,6 +11,8 @@
#include "progress.h"
#include "thread-utils.h"
#include "repository.h"
+#include "symlinks.h"
+#include "trace2.h"
/*
* Mostly randomly chosen maximum thread counts: we
diff --git a/pretty.c b/pretty.c
index 76fc4f61e4..0bb938021b 100644
--- a/pretty.c
+++ b/pretty.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "config.h"
#include "commit.h"
@@ -7,6 +7,7 @@
#include "hex.h"
#include "utf8.h"
#include "diff.h"
+#include "pager.h"
#include "revision.h"
#include "string-list.h"
#include "mailmap.h"
diff --git a/progress.c b/progress.c
index 44c784d75f..f695798aca 100644
--- a/progress.c
+++ b/progress.c
@@ -9,10 +9,13 @@
*/
#define GIT_TEST_PROGRESS_ONLY
-#include "cache.h"
+#include "git-compat-util.h"
+#include "pager.h"
#include "progress.h"
+#include "repository.h"
#include "strbuf.h"
#include "trace.h"
+#include "trace2.h"
#include "utf8.h"
#include "config.h"
diff --git a/promisor-remote.c b/promisor-remote.c
index a8dbb788e8..1adcd6fb0a 100644
--- a/promisor-remote.c
+++ b/promisor-remote.c
@@ -1,9 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "gettext.h"
#include "hex.h"
#include "object-store.h"
#include "promisor-remote.h"
#include "config.h"
+#include "trace2.h"
#include "transport.h"
#include "strvec.h"
#include "packfile.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/protocol.c b/protocol.c
index bdb32e1eeb..079ba75acf 100644
--- a/protocol.c
+++ b/protocol.c
@@ -1,7 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "environment.h"
#include "protocol.h"
+#include "trace2.h"
static enum protocol_version parse_protocol_version(const char *value)
{
diff --git a/protocol.h b/protocol.h
index cef1a4a01c..de66bf80f8 100644
--- a/protocol.h
+++ b/protocol.h
@@ -1,6 +1,27 @@
#ifndef PROTOCOL_H
#define PROTOCOL_H
+/*
+ * Intensive research over the course of many years has shown that
+ * port 9418 is totally unused by anything else. Or
+ *
+ * Your search - "port 9418" - did not match any documents.
+ *
+ * as www.google.com puts it.
+ *
+ * This port has been properly assigned for git use by IANA:
+ * git (Assigned-9418) [I06-050728-0001].
+ *
+ * git 9418/tcp git pack transfer service
+ * git 9418/udp git pack transfer service
+ *
+ * with Linus Torvalds <torvalds@osdl.org> as the point of
+ * contact. September 2005.
+ *
+ * See http://www.iana.org/assignments/port-numbers
+ */
+#define DEFAULT_GIT_PORT 9418
+
enum protocol_version {
protocol_unknown_version = -1,
protocol_v0 = 0,
diff --git a/quote.c b/quote.c
index 7ccb5a06cd..43c739671e 100644
--- a/quote.c
+++ b/quote.c
@@ -1,5 +1,6 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
+#include "path.h"
#include "quote.h"
#include "strbuf.h"
#include "strvec.h"
diff --git a/quote.h b/quote.h
index 87ff458b06..0300c29104 100644
--- a/quote.h
+++ b/quote.h
@@ -3,6 +3,8 @@
struct strbuf;
+extern int quote_path_fully;
+
/* Help to copy the thing properly quoted for the shell safety.
* any single quote is replaced with '\'', any exclamation point
* is replaced with '\!', and the whole thing is enclosed in a
diff --git a/range-diff.c b/range-diff.c
index d1ed3b8ee5..6a704e6f47 100644
--- a/range-diff.c
+++ b/range-diff.c
@@ -1,7 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "environment.h"
#include "gettext.h"
#include "range-diff.h"
+#include "object-name.h"
#include "string-list.h"
#include "run-command.h"
#include "strvec.h"
@@ -10,6 +11,7 @@
#include "linear-assignment.h"
#include "diffcore.h"
#include "commit.h"
+#include "pager.h"
#include "pretty.h"
#include "userdiff.h"
#include "apply.h"
diff --git a/read-cache.c b/read-cache.c
index 2a49178633..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"
@@ -14,17 +15,23 @@
#include "cache-tree.h"
#include "refs.h"
#include "dir.h"
+#include "object-file.h"
#include "object-store.h"
+#include "oid-array.h"
#include "tree.h"
#include "commit.h"
#include "blob.h"
#include "environment.h"
#include "gettext.h"
+#include "mem-pool.h"
+#include "object-name.h"
#include "resolve-undo.h"
#include "run-command.h"
#include "strbuf.h"
+#include "trace2.h"
#include "varint.h"
#include "split-index.h"
+#include "symlinks.h"
#include "utf8.h"
#include "fsmonitor.h"
#include "thread-utils.h"
@@ -493,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 79ed61b9fa..852a331318 100644
--- a/rebase-interactive.c
+++ b/rebase-interactive.c
@@ -1,13 +1,16 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "commit.h"
+#include "editor.h"
#include "environment.h"
#include "gettext.h"
#include "sequencer.h"
#include "rebase-interactive.h"
+#include "repository.h"
#include "strbuf.h"
#include "commit-slab.h"
#include "config.h"
#include "dir.h"
+#include "object-name.h"
#include "wrapper.h"
static const char edit_todo_list_advice[] =
diff --git a/ref-filter.c b/ref-filter.c
index 72175612f3..4991cd4f7a 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1,12 +1,15 @@
-#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"
#include "wildmatch.h"
+#include "object-name.h"
#include "object-store.h"
+#include "oid-array.h"
#include "repository.h"
#include "commit.h"
#include "remote.h"
@@ -17,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.c b/refs.c
index 0f369dbde7..d2a98e1c21 100644
--- a/refs.c
+++ b/refs.c
@@ -2,7 +2,8 @@
* The backend-independent part of the reference module.
*/
-#include "cache.h"
+#include "git-compat-util.h"
+#include "advice.h"
#include "alloc.h"
#include "config.h"
#include "environment.h"
@@ -15,6 +16,7 @@
#include "refs/refs-internal.h"
#include "run-command.h"
#include "hook.h"
+#include "object-name.h"
#include "object-store.h"
#include "object.h"
#include "tag.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 e6a6971381..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"
@@ -12,6 +14,7 @@
#include "../dir-iterator.h"
#include "../lockfile.h"
#include "../object.h"
+#include "../object-file.h"
#include "../dir.h"
#include "../chdir-notify.h"
#include "../setup.h"
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index 1eba1015dd..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"
@@ -9,6 +10,7 @@
#include "../iterator.h"
#include "../lockfile.h"
#include "../chdir-notify.h"
+#include "../wrapper.h"
#include "../write-or-die.h"
enum mmap_strategy {
@@ -650,7 +652,7 @@ static struct snapshot *create_snapshot(struct packed_ref_store *refs)
snapshot->buf,
snapshot->eof - snapshot->buf);
- string_list_split_in_place(&traits, p, ' ', -1);
+ string_list_split_in_place(&traits, p, " ", -1);
if (unsorted_string_list_has_string(&traits, "fully-peeled"))
snapshot->peeled = PEELED_FULLY;
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 850d9d3744..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 "cache.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/remote-curl.c b/remote-curl.c
index db3bc431fc..acf7b2bb40 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -21,6 +21,7 @@
#include "setup.h"
#include "protocol.h"
#include "quote.h"
+#include "trace2.h"
#include "transport.h"
#include "write-or-die.h"
diff --git a/remote.c b/remote.c
index 3a831cb530..0764fca0db 100644
--- a/remote.c
+++ b/remote.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "alloc.h"
#include "config.h"
@@ -9,6 +9,7 @@
#include "urlmatch.h"
#include "refs.h"
#include "refspec.h"
+#include "object-name.h"
#include "object-store.h"
#include "commit.h"
#include "diff.h"
diff --git a/repo-settings.c b/repo-settings.c
index 0a6c0b381f..d220c5dd9f 100644
--- a/repo-settings.c
+++ b/repo-settings.c
@@ -41,10 +41,8 @@ void prepare_repo_settings(struct repository *r)
repo_cfg_bool(r, "feature.experimental", &experimental, 0);
/* Defaults modified by feature.* */
- if (experimental) {
+ if (experimental)
r->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_SKIPPING;
- r->settings.gc_cruft_packs = 1;
- }
if (manyfiles) {
r->settings.index_version = 4;
r->settings.index_skip_hash = 1;
@@ -63,6 +61,7 @@ void prepare_repo_settings(struct repository *r)
repo_cfg_bool(r, "core.multipackindex", &r->settings.core_multi_pack_index, 1);
repo_cfg_bool(r, "index.sparse", &r->settings.sparse_index, 0);
repo_cfg_bool(r, "index.skiphash", &r->settings.index_skip_hash, r->settings.index_skip_hash);
+ repo_cfg_bool(r, "pack.readreverseindex", &r->settings.pack_read_reverse_index, 1);
/*
* The GIT_TEST_MULTI_PACK_INDEX variable is special in that
diff --git a/repository.c b/repository.c
index f6d9f5db08..c53e480e32 100644
--- a/repository.c
+++ b/repository.c
@@ -14,6 +14,7 @@
#include "setup.h"
#include "submodule-config.h"
#include "sparse-index.h"
+#include "trace2.h"
#include "promisor-remote.h"
/* The main repository */
diff --git a/repository.h b/repository.h
index 15a8afc5fb..1a13ff2867 100644
--- a/repository.h
+++ b/repository.h
@@ -33,10 +33,10 @@ struct repo_settings {
int commit_graph_generation_version;
int commit_graph_read_changed_paths;
int gc_write_commit_graph;
- int gc_cruft_packs;
int fetch_write_commit_graph;
int command_requires_full_index;
int sparse_index;
+ int pack_read_reverse_index;
struct fsmonitor_settings *fsmonitor; /* lazily loaded */
diff --git a/rerere.c b/rerere.c
index 5516e336d0..e968d413d6 100644
--- a/rerere.c
+++ b/rerere.c
@@ -1,7 +1,8 @@
-#include "git-compat-util.h"
+#include "cache.h"
#include "abspath.h"
#include "alloc.h"
#include "config.h"
+#include "copy.h"
#include "gettext.h"
#include "hex.h"
#include "lockfile.h"
@@ -13,6 +14,7 @@
#include "ll-merge.h"
#include "attr.h"
#include "pathspec.h"
+#include "object-file.h"
#include "object-store.h"
#include "hash-lookup.h"
#include "strmap.h"
diff --git a/reset.c b/reset.c
index ab300923e0..48da0adf85 100644
--- a/reset.c
+++ b/reset.c
@@ -3,6 +3,7 @@
#include "gettext.h"
#include "hex.h"
#include "lockfile.h"
+#include "object-name.h"
#include "refs.h"
#include "reset.h"
#include "run-command.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 2b3f0f901e..c5deafc92f 100644
--- a/resolve-undo.h
+++ b/resolve-undo.h
@@ -1,7 +1,12 @@
#ifndef RESOLVE_UNDO_H
#define RESOLVE_UNDO_H
-#include "cache.h"
+struct cache_entry;
+struct index_state;
+struct pathspec;
+struct string_list;
+
+#include "hash-ll.h"
struct resolve_undo_info {
unsigned int mode[3];
diff --git a/revision.c b/revision.c
index 106ca1ce6c..b33cc1d106 100644
--- a/revision.c
+++ b/revision.c
@@ -1,9 +1,11 @@
-#include "git-compat-util.h"
+#include "cache.h"
#include "alloc.h"
#include "config.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
+#include "object-file.h"
#include "object-store.h"
#include "tag.h"
#include "blob.h"
@@ -31,6 +33,7 @@
#include "worktree.h"
#include "setup.h"
#include "strvec.h"
+#include "trace2.h"
#include "commit-reach.h"
#include "commit-graph.h"
#include "prio-queue.h"
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 614d48fa9a..d4247d5fcc 100644
--- a/run-command.c
+++ b/run-command.c
@@ -5,9 +5,12 @@
#include "gettext.h"
#include "sigchain.h"
#include "strvec.h"
+#include "symlinks.h"
#include "thread-utils.h"
#include "strbuf.h"
#include "string-list.h"
+#include "trace.h"
+#include "trace2.h"
#include "quote.h"
#include "config.h"
#include "packfile.h"
diff --git a/scalar.c b/scalar.c
index de07c37d21..1326e1f608 100644
--- a/scalar.c
+++ b/scalar.c
@@ -2,7 +2,7 @@
* The Scalar command-line interface.
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "gettext.h"
#include "parse-options.h"
@@ -16,6 +16,7 @@
#include "packfile.h"
#include "help.h"
#include "setup.h"
+#include "trace2.h"
static void setup_enlistment_directory(int argc, const char **argv,
const char * const *usagestr,
diff --git a/send-pack.c b/send-pack.c
index f81bbb28d7..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"
@@ -14,6 +15,7 @@
#include "quote.h"
#include "transport.h"
#include "version.h"
+#include "wrapper.h"
#include "oid-array.h"
#include "gpg-interface.h"
#include "shallow.h"
@@ -538,7 +540,7 @@ int send_pack(struct send_pack_args *args,
die(_("the receiving end does not support this repository's hash algorithm"));
if (args->push_cert != SEND_PACK_PUSH_CERT_NEVER) {
- int len;
+ size_t len;
push_cert_nonce = server_feature_value("push-cert", &len);
if (push_cert_nonce) {
reject_invalid_nonce(push_cert_nonce, len);
diff --git a/sequencer.c b/sequencer.c
index d2c7698c48..b553b49fbb 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1,14 +1,19 @@
#include "cache.h"
#include "abspath.h"
+#include "advice.h"
#include "alloc.h"
#include "config.h"
+#include "copy.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
#include "lockfile.h"
#include "dir.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "object.h"
+#include "pager.h"
#include "commit.h"
#include "sequencer.h"
#include "tag.h"
@@ -3621,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 355b6e01a5..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"
@@ -9,7 +9,9 @@
#include "commit.h"
#include "tag.h"
#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 6c5b85e96c..458582207e 100644
--- a/setup.c
+++ b/setup.c
@@ -1,7 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "environment.h"
#include "gettext.h"
+#include "object-name.h"
#include "repository.h"
#include "config.h"
#include "dir.h"
@@ -10,6 +11,8 @@
#include "chdir-notify.h"
#include "promisor-remote.h"
#include "quote.h"
+#include "trace2.h"
+#include "wrapper.h"
static int inside_git_dir = -1;
static int inside_work_tree = -1;
@@ -1349,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/shallow.c b/shallow.c
index b4d726bd59..128f56179e 100644
--- a/shallow.c
+++ b/shallow.c
@@ -17,6 +17,7 @@
#include "list-objects.h"
#include "commit-reach.h"
#include "shallow.h"
+#include "trace.h"
#include "wrapper.h"
void set_alternate_shallow_file(struct repository *r, const char *path, int override)
diff --git a/sideband.c b/sideband.c
index 0af582858b..6cbfd391c4 100644
--- a/sideband.c
+++ b/sideband.c
@@ -1,6 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "color.h"
#include "config.h"
+#include "editor.h"
#include "gettext.h"
#include "sideband.h"
#include "help.h"
diff --git a/split-index.c b/split-index.c
index c98807c655..40e54760b3 100644
--- a/split-index.c
+++ b/split-index.c
@@ -1,7 +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 7a435ca2c9..15a29cd08c 100644
--- a/split-index.h
+++ b/split-index.h
@@ -1,7 +1,7 @@
#ifndef SPLIT_INDEX_H
#define SPLIT_INDEX_H
-#include "cache.h"
+#include "hash-ll.h"
struct index_state;
struct strbuf;
diff --git a/strbuf.c b/strbuf.c
index 70a83e7980..08eec8f1d8 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -1,10 +1,12 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "alloc.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "refs.h"
+#include "repository.h"
#include "string-list.h"
#include "utf8.h"
#include "date.h"
@@ -1179,34 +1181,6 @@ int strbuf_normalize_path(struct strbuf *src)
return 0;
}
-int strbuf_edit_interactively(struct strbuf *buffer, const char *path,
- const char *const *env)
-{
- char *path2 = NULL;
- int fd, res = 0;
-
- if (!is_absolute_path(path))
- path = path2 = xstrdup(git_path("%s", path));
-
- fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
- if (fd < 0)
- res = error_errno(_("could not open '%s' for writing"), path);
- else if (write_in_full(fd, buffer->buf, buffer->len) < 0) {
- res = error_errno(_("could not write to '%s'"), path);
- close(fd);
- } else if (close(fd) < 0)
- res = error_errno(_("could not close '%s'"), path);
- else {
- strbuf_reset(buffer);
- if (launch_editor(path, buffer, env) < 0)
- res = error_errno(_("could not edit '%s'"), path);
- unlink(path);
- }
-
- free(path2);
- return res;
-}
-
void strbuf_strip_file_from_path(struct strbuf *sb)
{
char *path_sep = find_last_dir_sep(sb->buf);
diff --git a/strbuf.h b/strbuf.h
index b980f9edc6..3dfeadb44c 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -640,30 +640,6 @@ void strbuf_repo_add_unique_abbrev(struct strbuf *sb, struct repository *repo,
void strbuf_add_unique_abbrev(struct strbuf *sb, const struct object_id *oid,
int abbrev_len);
-/**
- * Launch the user preferred editor to edit a file and fill the buffer
- * with the file's contents upon the user completing their editing. The
- * third argument can be used to set the environment which the editor is
- * run in. If the buffer is NULL the editor is launched as usual but the
- * file's contents are not read into the buffer upon completion.
- */
-int launch_editor(const char *path, struct strbuf *buffer,
- const char *const *env);
-
-int launch_sequence_editor(const char *path, struct strbuf *buffer,
- const char *const *env);
-
-/*
- * In contrast to `launch_editor()`, this function writes out the contents
- * of the specified file first, then clears the `buffer`, then launches
- * the editor and reads back in the file contents into the `buffer`.
- * Finally, it deletes the temporary file.
- *
- * If `path` is relative, it refers to a file in the `.git` directory.
- */
-int strbuf_edit_interactively(struct strbuf *buffer, const char *path,
- const char *const *env);
-
/*
* Remove the filename from the provided path string. If the path
* contains a trailing separator, then the path is considered a directory
diff --git a/streaming.c b/streaming.c
index 024fd796b7..21e39585e8 100644
--- a/streaming.c
+++ b/streaming.c
@@ -1,10 +1,12 @@
/*
* Copyright (c) 2011, Google Inc.
*/
-#include "cache.h"
+#include "git-compat-util.h"
+#include "convert.h"
#include "environment.h"
#include "streaming.h"
#include "repository.h"
+#include "object-file.h"
#include "object-store.h"
#include "replace-object.h"
#include "packfile.h"
diff --git a/string-list.c b/string-list.c
index db473f273e..0f8ac117fd 100644
--- a/string-list.c
+++ b/string-list.c
@@ -203,6 +203,15 @@ void string_list_clear_func(struct string_list *list, string_list_clear_func_t c
list->nr = list->alloc = 0;
}
+void string_list_setlen(struct string_list *list, size_t nr)
+{
+ if (list->strdup_strings)
+ BUG("cannot setlen a string_list which owns its entries");
+ if (nr > list->nr)
+ BUG("cannot grow a string_list with setlen");
+ list->nr = nr;
+}
+
struct string_list_item *string_list_append_nodup(struct string_list *list,
char *string)
{
@@ -301,7 +310,7 @@ int string_list_split(struct string_list *list, const char *string,
}
int string_list_split_in_place(struct string_list *list, char *string,
- int delim, int maxsplit)
+ const char *delim, int maxsplit)
{
int count = 0;
char *p = string, *end;
@@ -315,7 +324,7 @@ int string_list_split_in_place(struct string_list *list, char *string,
string_list_append(list, p);
return count;
}
- end = strchr(p, delim);
+ end = strpbrk(p, delim);
if (end) {
*end = '\0';
string_list_append(list, p);
diff --git a/string-list.h b/string-list.h
index c7b0d5d000..122b318641 100644
--- a/string-list.h
+++ b/string-list.h
@@ -134,6 +134,16 @@ typedef void (*string_list_clear_func_t)(void *p, const char *str);
/** Call a custom clear function on each util pointer */
void string_list_clear_func(struct string_list *list, string_list_clear_func_t clearfunc);
+/*
+ * Set the length of a string_list to `nr`, provided that (a) `list`
+ * does not own its own storage, and (b) that `nr` is no larger than
+ * `list->nr`.
+ *
+ * Useful when "shrinking" `list` to write over existing entries that
+ * are no longer used without reallocating.
+ */
+void string_list_setlen(struct string_list *list, size_t nr);
+
/**
* Apply `func` to each item. If `func` returns nonzero, the
* iteration aborts and the return value is propagated.
@@ -270,5 +280,5 @@ int string_list_split(struct string_list *list, const char *string,
* list->strdup_strings must *not* be set.
*/
int string_list_split_in_place(struct string_list *list, char *string,
- int delim, int maxsplit);
+ const char *delim, int maxsplit);
#endif /* STRING_LIST_H */
diff --git a/submodule-config.c b/submodule-config.c
index ecf0fcf007..58dfbde9ae 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "alloc.h"
#include "dir.h"
#include "environment.h"
@@ -9,8 +9,10 @@
#include "submodule-config.h"
#include "submodule.h"
#include "strbuf.h"
+#include "object-name.h"
#include "object-store.h"
#include "parse-options.h"
+#include "thread-utils.h"
#include "tree-walk.h"
/*
diff --git a/submodule.c b/submodule.c
index 94644fac0a..2e78f51349 100644
--- a/submodule.c
+++ b/submodule.c
@@ -24,10 +24,13 @@
#include "remote.h"
#include "worktree.h"
#include "parse-options.h"
+#include "object-file.h"
+#include "object-name.h"
#include "object-store.h"
#include "commit-reach.h"
#include "setup.h"
#include "shallow.h"
+#include "trace2.h"
static int config_update_recurse_submodules = RECURSE_SUBMODULES_OFF;
static int initialized_fetch_ref_tips;
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/README b/t/README
index 29576c3748..bdfac4cceb 100644
--- a/t/README
+++ b/t/README
@@ -475,7 +475,7 @@ GIT_TEST_DEFAULT_HASH=<hash-algo> specifies which hash algorithm to
use in the test scripts. Recognized values for <hash-algo> are "sha1"
and "sha256".
-GIT_TEST_WRITE_REV_INDEX=<boolean>, when true enables the
+GIT_TEST_NO_WRITE_REV_INDEX=<boolean>, when true disables the
'pack.writeReverseIndex' setting.
GIT_TEST_SPARSE_INDEX=<boolean>, when true enables index writes to use the
diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh
index b35be20cf3..2ef70235b1 100644
--- a/t/annotate-tests.sh
+++ b/t/annotate-tests.sh
@@ -72,6 +72,13 @@ test_expect_success 'blame 1 author' '
check_count A 2
'
+test_expect_success 'blame working copy' '
+ test_when_finished "git restore file" &&
+ echo "1A quick brown fox jumps over the" >file &&
+ echo "another lazy dog" >>file &&
+ check_count A 1 "Not Committed Yet" 1
+'
+
test_expect_success 'blame with --contents' '
check_count --contents=file A 2
'
@@ -79,7 +86,7 @@ test_expect_success 'blame with --contents' '
test_expect_success 'blame with --contents changed' '
echo "1A quick brown fox jumps over the" >contents &&
echo "another lazy dog" >>contents &&
- check_count --contents=contents A 1 "Not Committed Yet" 1
+ check_count --contents=contents A 1 "External file (--contents)" 1
'
test_expect_success 'blame in a bare repo without starting commit' '
@@ -109,7 +116,7 @@ test_expect_success 'blame 2 authors' '
'
test_expect_success 'blame with --contents and revision' '
- check_count -h testTag --contents=file A 2 "Not Committed Yet" 2
+ check_count -h testTag --contents=file A 2 "External file (--contents)" 2
'
test_expect_success 'setup B1 lines (branch1)' '
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-chmtime.c b/t/helper/test-chmtime.c
index dc28890a18..0e5538833a 100644
--- a/t/helper/test-chmtime.c
+++ b/t/helper/test-chmtime.c
@@ -94,7 +94,7 @@ int cmd__chmtime(int argc, const char **argv)
if (timespec_arg(argv[i], &set_time, &set_eq)) {
++i;
} else {
- if (get == 0) {
+ if (get == 0 && verbose == 0) {
fprintf(stderr, "Not a base-10 integer: %s\n", argv[i] + 1);
goto 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-date.c b/t/helper/test-date.c
index cd6a6df702..0683d46574 100644
--- a/t/helper/test-date.c
+++ b/t/helper/test-date.c
@@ -1,6 +1,6 @@
#include "test-tool.h"
-#include "cache.h"
#include "date.h"
+#include "trace.h"
static const char *usage_msg = "\n"
" test-tool date relative [time_t]...\n"
@@ -81,7 +81,7 @@ static void parse_approxidate(const char **argv)
{
for (; *argv; argv++) {
timestamp_t t;
- t = approxidate_relative(*argv);
+ t = approxidate(*argv);
printf("%s -> %s\n", *argv, show_date(t, 0, DATE_MODE(ISO8601)));
}
}
@@ -90,7 +90,7 @@ static void parse_approx_timestamp(const char **argv)
{
for (; *argv; argv++) {
timestamp_t t;
- t = approxidate_relative(*argv);
+ t = approxidate(*argv);
printf("%s -> %"PRItime"\n", *argv, t);
}
}
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-fast-rebase.c b/t/helper/test-fast-rebase.c
index fd48e0ee2c..d1d63feaa9 100644
--- a/t/helper/test-fast-rebase.c
+++ b/t/helper/test-fast-rebase.c
@@ -20,6 +20,7 @@
#include "hex.h"
#include "lockfile.h"
#include "merge-ort.h"
+#include "object-name.h"
#include "refs.h"
#include "revision.h"
#include "sequencer.h"
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-hashmap.c b/t/helper/test-hashmap.c
index 36ff07bd4b..0eb0b3d49c 100644
--- a/t/helper/test-hashmap.c
+++ b/t/helper/test-hashmap.c
@@ -2,6 +2,7 @@
#include "git-compat-util.h"
#include "hashmap.h"
#include "strbuf.h"
+#include "string-list.h"
struct test_entry
{
@@ -150,6 +151,7 @@ static void perf_hashmap(unsigned int method, unsigned int rounds)
*/
int cmd__hashmap(int argc, const char **argv)
{
+ struct string_list parts = STRING_LIST_INIT_NODUP;
struct strbuf line = STRBUF_INIT;
int icase;
struct hashmap map = HASHMAP_INIT(test_entry_cmp, &icase);
@@ -159,21 +161,26 @@ int cmd__hashmap(int argc, const char **argv)
/* process commands from stdin */
while (strbuf_getline(&line, stdin) != EOF) {
- char *cmd, *p1 = NULL, *p2 = NULL;
+ char *cmd, *p1, *p2;
unsigned int hash = 0;
struct test_entry *entry;
/* break line into command and up to two parameters */
- cmd = strtok(line.buf, DELIM);
+ string_list_setlen(&parts, 0);
+ string_list_split_in_place(&parts, line.buf, DELIM, 2);
+ string_list_remove_empty_items(&parts, 0);
+
/* ignore empty lines */
- if (!cmd || *cmd == '#')
+ if (!parts.nr)
+ continue;
+ if (!*parts.items[0].string || *parts.items[0].string == '#')
continue;
- p1 = strtok(NULL, DELIM);
- if (p1) {
+ cmd = parts.items[0].string;
+ p1 = parts.nr >= 1 ? parts.items[1].string : NULL;
+ p2 = parts.nr >= 2 ? parts.items[2].string : NULL;
+ if (p1)
hash = icase ? strihash(p1) : strhash(p1);
- p2 = strtok(NULL, DELIM);
- }
if (!strcmp("add", cmd) && p1 && p2) {
@@ -260,6 +267,7 @@ int cmd__hashmap(int argc, const char **argv)
}
}
+ string_list_clear(&parts, 0);
strbuf_release(&line);
hashmap_clear_and_free(&map, struct test_entry, ent);
return 0;
diff --git a/t/helper/test-json-writer.c b/t/helper/test-json-writer.c
index 86887f5320..afe393f597 100644
--- a/t/helper/test-json-writer.c
+++ b/t/helper/test-json-writer.c
@@ -1,5 +1,6 @@
#include "test-tool.h"
#include "json-writer.h"
+#include "string-list.h"
static const char *expect_obj1 = "{\"a\":\"abc\",\"b\":42,\"c\":true}";
static const char *expect_obj2 = "{\"a\":-1,\"b\":2147483647,\"c\":0}";
@@ -394,35 +395,41 @@ static int unit_tests(void)
return 0;
}
-static void get_s(int line_nr, char **s_in)
+struct line {
+ struct string_list *parts;
+ size_t consumed_nr;
+ int nr;
+};
+
+static void get_s(struct line *line, char **s_in)
{
- *s_in = strtok(NULL, " ");
- if (!*s_in)
- die("line[%d]: expected: <s>", line_nr);
+ if (line->consumed_nr > line->parts->nr)
+ die("line[%d]: expected: <s>", line->nr);
+ *s_in = line->parts->items[line->consumed_nr++].string;
}
-static void get_i(int line_nr, intmax_t *s_in)
+static void get_i(struct line *line, intmax_t *s_in)
{
char *s;
char *endptr;
- get_s(line_nr, &s);
+ get_s(line, &s);
*s_in = strtol(s, &endptr, 10);
if (*endptr || errno == ERANGE)
- die("line[%d]: invalid integer value", line_nr);
+ die("line[%d]: invalid integer value", line->nr);
}
-static void get_d(int line_nr, double *s_in)
+static void get_d(struct line *line, double *s_in)
{
char *s;
char *endptr;
- get_s(line_nr, &s);
+ get_s(line, &s);
*s_in = strtod(s, &endptr);
if (*endptr || errno == ERANGE)
- die("line[%d]: invalid float value", line_nr);
+ die("line[%d]: invalid float value", line->nr);
}
static int pretty;
@@ -453,6 +460,7 @@ static char *get_trimmed_line(char *buf, int buf_size)
static int scripted(void)
{
+ struct string_list parts = STRING_LIST_INIT_NODUP;
struct json_writer jw = JSON_WRITER_INIT;
char buf[MAX_LINE_LENGTH];
char *line;
@@ -470,66 +478,77 @@ static int scripted(void)
die("expected first line to be 'object' or 'array'");
while ((line = get_trimmed_line(buf, MAX_LINE_LENGTH)) != NULL) {
+ struct line state = { 0 };
char *verb;
char *key;
char *s_value;
intmax_t i_value;
double d_value;
- line_nr++;
+ state.parts = &parts;
+ state.nr = ++line_nr;
+
+ /* break line into command and zero or more tokens */
+ string_list_setlen(&parts, 0);
+ string_list_split_in_place(&parts, line, " ", -1);
+ string_list_remove_empty_items(&parts, 0);
+
+ /* ignore empty lines */
+ if (!parts.nr || !*parts.items[0].string)
+ continue;
- verb = strtok(line, " ");
+ verb = parts.items[state.consumed_nr++].string;
if (!strcmp(verb, "end")) {
jw_end(&jw);
}
else if (!strcmp(verb, "object-string")) {
- get_s(line_nr, &key);
- get_s(line_nr, &s_value);
+ get_s(&state, &key);
+ get_s(&state, &s_value);
jw_object_string(&jw, key, s_value);
}
else if (!strcmp(verb, "object-int")) {
- get_s(line_nr, &key);
- get_i(line_nr, &i_value);
+ get_s(&state, &key);
+ get_i(&state, &i_value);
jw_object_intmax(&jw, key, i_value);
}
else if (!strcmp(verb, "object-double")) {
- get_s(line_nr, &key);
- get_i(line_nr, &i_value);
- get_d(line_nr, &d_value);
+ get_s(&state, &key);
+ get_i(&state, &i_value);
+ get_d(&state, &d_value);
jw_object_double(&jw, key, i_value, d_value);
}
else if (!strcmp(verb, "object-true")) {
- get_s(line_nr, &key);
+ get_s(&state, &key);
jw_object_true(&jw, key);
}
else if (!strcmp(verb, "object-false")) {
- get_s(line_nr, &key);
+ get_s(&state, &key);
jw_object_false(&jw, key);
}
else if (!strcmp(verb, "object-null")) {
- get_s(line_nr, &key);
+ get_s(&state, &key);
jw_object_null(&jw, key);
}
else if (!strcmp(verb, "object-object")) {
- get_s(line_nr, &key);
+ get_s(&state, &key);
jw_object_inline_begin_object(&jw, key);
}
else if (!strcmp(verb, "object-array")) {
- get_s(line_nr, &key);
+ get_s(&state, &key);
jw_object_inline_begin_array(&jw, key);
}
else if (!strcmp(verb, "array-string")) {
- get_s(line_nr, &s_value);
+ get_s(&state, &s_value);
jw_array_string(&jw, s_value);
}
else if (!strcmp(verb, "array-int")) {
- get_i(line_nr, &i_value);
+ get_i(&state, &i_value);
jw_array_intmax(&jw, i_value);
}
else if (!strcmp(verb, "array-double")) {
- get_i(line_nr, &i_value);
- get_d(line_nr, &d_value);
+ get_i(&state, &i_value);
+ get_d(&state, &d_value);
jw_array_double(&jw, i_value, d_value);
}
else if (!strcmp(verb, "array-true"))
@@ -552,6 +571,7 @@ static int scripted(void)
printf("%s\n", jw.json.buf);
jw_release(&jw);
+ string_list_clear(&parts, 0);
return 0;
}
diff --git a/t/helper/test-lazy-init-name-hash.c b/t/helper/test-lazy-init-name-hash.c
index 06ce3a47cc..b83a75d19f 100644
--- a/t/helper/test-lazy-init-name-hash.c
+++ b/t/helper/test-lazy-init-name-hash.c
@@ -3,7 +3,9 @@
#include "cache.h"
#include "environment.h"
#include "parse-options.h"
+#include "repository.h"
#include "setup.h"
+#include "trace.h"
static int single;
static int multi;
diff --git a/t/helper/test-match-trees.c b/t/helper/test-match-trees.c
index 508eb7066a..d0db5ff26f 100644
--- a/t/helper/test-match-trees.c
+++ b/t/helper/test-match-trees.c
@@ -1,6 +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 335e5bb3a9..42ccc87051 100644
--- a/t/helper/test-mergesort.c
+++ b/t/helper/test-mergesort.c
@@ -1,6 +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 a7b7b38df1..bd30244a54 100644
--- a/t/helper/test-oidmap.c
+++ b/t/helper/test-oidmap.c
@@ -1,9 +1,11 @@
#include "test-tool.h"
-#include "cache.h"
#include "hex.h"
+#include "object-name.h"
#include "oidmap.h"
+#include "repository.h"
#include "setup.h"
#include "strbuf.h"
+#include "string-list.h"
/* key is an oid and value is a name (could be a refname for example) */
struct test_entry {
@@ -25,6 +27,7 @@ struct test_entry {
*/
int cmd__oidmap(int argc UNUSED, const char **argv UNUSED)
{
+ struct string_list parts = STRING_LIST_INIT_NODUP;
struct strbuf line = STRBUF_INIT;
struct oidmap map = OIDMAP_INIT;
@@ -35,19 +38,24 @@ int cmd__oidmap(int argc UNUSED, const char **argv UNUSED)
/* process commands from stdin */
while (strbuf_getline(&line, stdin) != EOF) {
- char *cmd, *p1 = NULL, *p2 = NULL;
+ char *cmd, *p1, *p2;
struct test_entry *entry;
struct object_id oid;
/* break line into command and up to two parameters */
- cmd = strtok(line.buf, DELIM);
+ string_list_setlen(&parts, 0);
+ string_list_split_in_place(&parts, line.buf, DELIM, 2);
+ string_list_remove_empty_items(&parts, 0);
+
/* ignore empty lines */
- if (!cmd || *cmd == '#')
+ if (!parts.nr)
+ continue;
+ if (!*parts.items[0].string || *parts.items[0].string == '#')
continue;
- p1 = strtok(NULL, DELIM);
- if (p1)
- p2 = strtok(NULL, DELIM);
+ cmd = parts.items[0].string;
+ p1 = parts.nr >= 1 ? parts.items[1].string : NULL;
+ p2 = parts.nr >= 2 ? parts.items[2].string : NULL;
if (!strcmp("put", cmd) && p1 && p2) {
@@ -108,6 +116,7 @@ int cmd__oidmap(int argc UNUSED, const char **argv UNUSED)
}
}
+ string_list_clear(&parts, 0);
strbuf_release(&line);
oidmap_free(&map, 1);
return 0;
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 4f5ac2fadc..2ef53d5f7a 100644
--- a/t/helper/test-path-utils.c
+++ b/t/helper/test-path-utils.c
@@ -2,8 +2,10 @@
#include "cache.h"
#include "abspath.h"
#include "environment.h"
+#include "path.h"
#include "setup.h"
#include "string-list.h"
+#include "trace.h"
#include "utf8.h"
/*
diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c
index b0deaa106a..5b6f217441 100644
--- a/t/helper/test-reach.c
+++ b/t/helper/test-reach.c
@@ -1,11 +1,11 @@
#include "test-tool.h"
-#include "cache.h"
#include "alloc.h"
#include "commit.h"
#include "commit-reach.h"
#include "config.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "parse-options.h"
#include "ref-filter.h"
#include "setup.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 2123dda85b..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"
/*
@@ -62,7 +62,7 @@ int cmd__string_list(int argc, const char **argv)
struct string_list list = STRING_LIST_INIT_NODUP;
int i;
char *s = xstrdup(argv[2]);
- int delim = *argv[3];
+ const char *delim = argv[3];
int maxsplit = atoi(argv[4]);
i = string_list_split_in_place(&list, s, delim, maxsplit);
@@ -111,7 +111,7 @@ int cmd__string_list(int argc, const char **argv)
*/
if (sb.len && sb.buf[sb.len - 1] == '\n')
strbuf_setlen(&sb, sb.len - 1);
- string_list_split_in_place(&list, sb.buf, '\n', -1);
+ string_list_split_in_place(&list, sb.buf, "\n", -1);
string_list_sort(&list);
diff --git a/t/helper/test-submodule-config.c b/t/helper/test-submodule-config.c
index 40a6ee45af..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 "cache.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/perf/p2000-sparse-operations.sh b/t/perf/p2000-sparse-operations.sh
index f7bdba90c5..901cc493ef 100755
--- a/t/perf/p2000-sparse-operations.sh
+++ b/t/perf/p2000-sparse-operations.sh
@@ -43,6 +43,7 @@ test_expect_success 'setup repo and indexes' '
done &&
git sparse-checkout init --cone &&
+ git tag -a v1.0 -m "Final" &&
git sparse-checkout set $SPARSE_CONE &&
git checkout -b wide $OLD_COMMIT &&
@@ -126,5 +127,9 @@ test_perf_on_all git update-index --add --remove $SPARSE_CONE/a
test_perf_on_all "git rm -f $SPARSE_CONE/a && git checkout HEAD -- $SPARSE_CONE/a"
test_perf_on_all git grep --cached bogus -- "f2/f1/f1/*"
test_perf_on_all git write-tree
+test_perf_on_all git describe --dirty
+test_perf_on_all 'echo >>new && git describe --dirty'
+test_perf_on_all git diff-files
+test_perf_on_all git diff-files -- $SPARSE_CONE/a
test_done
diff --git a/t/perf/p5312-pack-bitmaps-revs.sh b/t/perf/p5312-pack-bitmaps-revs.sh
index 0684b690af..ceec60656b 100755
--- a/t/perf/p5312-pack-bitmaps-revs.sh
+++ b/t/perf/p5312-pack-bitmaps-revs.sh
@@ -12,8 +12,7 @@ test_lookup_pack_bitmap () {
test_perf_large_repo
test_expect_success 'setup bitmap config' '
- git config pack.writebitmaps true &&
- git config pack.writeReverseIndex true
+ git config pack.writebitmaps true
'
# we need to create the tag up front such that it is covered by the repack and
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/t0063-string-list.sh b/t/t0063-string-list.sh
index 46d4839194..1fee6d9010 100755
--- a/t/t0063-string-list.sh
+++ b/t/t0063-string-list.sh
@@ -18,6 +18,14 @@ test_split () {
"
}
+test_split_in_place() {
+ cat >expected &&
+ test_expect_success "split (in place) $1 at $2, max $3" "
+ test-tool string-list split_in_place '$1' '$2' '$3' >actual &&
+ test_cmp expected actual
+ "
+}
+
test_split "foo:bar:baz" ":" "-1" <<EOF
3
[0]: "foo"
@@ -61,6 +69,49 @@ test_split ":" ":" "-1" <<EOF
[1]: ""
EOF
+test_split_in_place "foo:;:bar:;:baz:;:" ":;" "-1" <<EOF
+10
+[0]: "foo"
+[1]: ""
+[2]: ""
+[3]: "bar"
+[4]: ""
+[5]: ""
+[6]: "baz"
+[7]: ""
+[8]: ""
+[9]: ""
+EOF
+
+test_split_in_place "foo:;:bar:;:baz" ":;" "0" <<EOF
+1
+[0]: "foo:;:bar:;:baz"
+EOF
+
+test_split_in_place "foo:;:bar:;:baz" ":;" "1" <<EOF
+2
+[0]: "foo"
+[1]: ";:bar:;:baz"
+EOF
+
+test_split_in_place "foo:;:bar:;:baz" ":;" "2" <<EOF
+3
+[0]: "foo"
+[1]: ""
+[2]: ":bar:;:baz"
+EOF
+
+test_split_in_place "foo:;:bar:;:" ":;" "-1" <<EOF
+7
+[0]: "foo"
+[1]: ""
+[2]: ""
+[3]: "bar"
+[4]: ""
+[5]: ""
+[6]: ""
+EOF
+
test_expect_success "test filter_string_list" '
test "x-" = "x$(test-tool string-list filter - y)" &&
test "x-" = "x$(test-tool string-list filter no y)" &&
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/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index 9bbc0d646b..e58bfbfcb4 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -1377,7 +1377,7 @@ test_expect_success 'index.sparse disabled inline uses full index' '
! test_region index ensure_full_index trace2.txt
'
-ensure_not_expanded () {
+run_sparse_index_trace2 () {
rm -f trace2.txt &&
if test -z "$WITHOUT_UNTRACKED_TXT"
then
@@ -1397,7 +1397,16 @@ ensure_not_expanded () {
git -C sparse-index "$@" \
>sparse-index-out \
2>sparse-index-error || return 1
- fi &&
+ fi
+}
+
+ensure_expanded () {
+ run_sparse_index_trace2 "$@" &&
+ test_region index ensure_full_index trace2.txt
+}
+
+ensure_not_expanded () {
+ run_sparse_index_trace2 "$@" &&
test_region ! index ensure_full_index trace2.txt
}
@@ -1514,6 +1523,31 @@ test_expect_success 'sparse-index is not expanded: stash' '
ensure_not_expanded stash pop
'
+test_expect_success 'describe tested on all' '
+ init_repos &&
+
+ # Add tag to be read by describe
+
+ run_on_all git tag -a v1.0 -m "Version 1" &&
+ test_all_match git describe --dirty &&
+ run_on_all rm g &&
+ test_all_match git describe --dirty
+'
+
+
+test_expect_success 'sparse-index is not expanded: describe' '
+ init_repos &&
+
+ # Add tag to be read by describe
+
+ git -C sparse-index tag -a v1.0 -m "Version 1" &&
+
+ ensure_not_expanded describe --dirty &&
+ echo "test" >>sparse-index/g &&
+ ensure_not_expanded describe --dirty &&
+ ensure_not_expanded describe
+'
+
test_expect_success 'sparse index is not expanded: diff' '
init_repos &&
@@ -2083,4 +2117,57 @@ test_expect_success 'sparse-index is not expanded: write-tree' '
ensure_not_expanded write-tree
'
+test_expect_success 'diff-files with pathspec inside sparse definition' '
+ init_repos &&
+
+ write_script edit-contents <<-\EOF &&
+ echo text >>"$1"
+ EOF
+
+ run_on_all ../edit-contents deep/a &&
+
+ test_all_match git diff-files &&
+
+ test_all_match git diff-files -- deep/a &&
+
+ # test wildcard
+ test_all_match git diff-files -- "deep/*"
+'
+
+test_expect_success 'diff-files with pathspec outside sparse definition' '
+ init_repos &&
+
+ test_sparse_match git diff-files -- folder2/a &&
+
+ write_script edit-contents <<-\EOF &&
+ echo text >>"$1"
+ EOF
+
+ # The directory "folder1" is outside the cone of interest
+ # and will not exist in the sparse checkout repositories.
+ # Create it as needed, add file "folder1/a" there with
+ # contents that is different from the staged version.
+ run_on_all mkdir -p folder1 &&
+ run_on_all cp a folder1/a &&
+
+ run_on_all ../edit-contents folder1/a &&
+ test_all_match git diff-files &&
+ test_all_match git diff-files -- folder1/a &&
+ test_all_match git diff-files -- "folder*/a"
+'
+
+test_expect_success 'sparse index is not expanded: diff-files' '
+ init_repos &&
+
+ write_script edit-contents <<-\EOF &&
+ echo text >>"$1"
+ EOF
+
+ run_on_all ../edit-contents deep/a &&
+
+ ensure_not_expanded diff-files &&
+ ensure_not_expanded diff-files -- deep/a &&
+ ensure_not_expanded diff-files -- "deep/*"
+'
+
test_done
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index 2575279ab8..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
@@ -617,6 +634,36 @@ test_expect_success 'renaming to bogus section is rejected' '
test_must_fail git config --rename-section branch.zwei "bogus name"
'
+test_expect_success 'renaming a section with a long line' '
+ {
+ printf "[b]\\n" &&
+ printf " c = d %1024s [a] e = f\\n" " " &&
+ printf "[a] g = h\\n"
+ } >y &&
+ git config -f y --rename-section a xyz &&
+ test_must_fail git config -f y b.e
+'
+
+test_expect_success 'renaming an embedded section with a long line' '
+ {
+ printf "[b]\\n" &&
+ printf " c = d %1024s [a] [foo] e = f\\n" " " &&
+ printf "[a] g = h\\n"
+ } >y &&
+ git config -f y --rename-section a xyz &&
+ test_must_fail git config -f y foo.e
+'
+
+test_expect_success 'renaming a section with an overly-long line' '
+ {
+ printf "[b]\\n" &&
+ printf " c = d %525000s e" " " &&
+ printf "[a] g = h\\n"
+ } >y &&
+ test_must_fail git config -f y --rename-section a xyz 2>err &&
+ grep "refusing to work with overly long line in .y. on line 2" err
+'
+
cat >> .git/config << EOF
[branch "zwei"] a = 1 [branch "vier"]
EOF
@@ -1458,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
'
@@ -1571,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
'
@@ -1585,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/t2024-checkout-dwim.sh b/t/t2024-checkout-dwim.sh
index 4a1c901456..74049a9812 100755
--- a/t/t2024-checkout-dwim.sh
+++ b/t/t2024-checkout-dwim.sh
@@ -305,10 +305,13 @@ test_expect_success 'loosely defined local base branch is reported correctly' '
test_config branch.strict.merge refs/heads/main &&
test_config branch.loose.merge main &&
- git checkout strict | sed -e "s/strict/BRANCHNAME/g" >expect &&
+ git checkout strict >expect.raw 2>&1 &&
+ sed -e "s/strict/BRANCHNAME/g" <expect.raw >expect &&
status_uno_is_clean &&
- git checkout loose | sed -e "s/loose/BRANCHNAME/g" >actual &&
+ git checkout loose >actual.raw 2>&1 &&
+ sed -e "s/loose/BRANCHNAME/g" <actual.raw >actual &&
status_uno_is_clean &&
+ grep BRANCHNAME actual &&
test_cmp expect actual
'
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/t3203-branch-output.sh b/t/t3203-branch-output.sh
index 1c0f7ea24e..93f8295339 100755
--- a/t/t3203-branch-output.sh
+++ b/t/t3203-branch-output.sh
@@ -355,6 +355,30 @@ test_expect_success 'git branch with --format=%(rest) must fail' '
test_must_fail git branch --format="%(rest)" >actual
'
+test_expect_success 'git branch --format --omit-empty' '
+ cat >expect <<-\EOF &&
+ Refname is (HEAD detached from fromtag)
+ Refname is refs/heads/ambiguous
+ Refname is refs/heads/branch-one
+ Refname is refs/heads/branch-two
+
+ Refname is refs/heads/ref-to-branch
+ Refname is refs/heads/ref-to-remote
+ EOF
+ git branch --format="%(if:notequals=refs/heads/main)%(refname)%(then)Refname is %(refname)%(end)" >actual &&
+ test_cmp expect actual &&
+ cat >expect <<-\EOF &&
+ Refname is (HEAD detached from fromtag)
+ Refname is refs/heads/ambiguous
+ Refname is refs/heads/branch-one
+ Refname is refs/heads/branch-two
+ Refname is refs/heads/ref-to-branch
+ Refname is refs/heads/ref-to-remote
+ EOF
+ git branch --omit-empty --format="%(if:notequals=refs/heads/main)%(refname)%(then)Refname is %(refname)%(end)" >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'worktree colors correct' '
cat >expect <<-EOF &&
* <GREEN>(HEAD detached from fromtag)<RESET>
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/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 7f1d4e8d58..3cf2b7a7fb 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -470,6 +470,11 @@ test_expect_success 'thread' '
check_threading expect.thread --thread main
'
+test_expect_success '--thread overrides format.thread=deep' '
+ test_config format.thread deep &&
+ check_threading expect.thread --thread main
+'
+
cat >expect.in-reply-to <<EOF
---
Message-ID: <0>
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/t4034-diff-words.sh b/t/t4034-diff-words.sh
index 15764ee9ac..74586f3813 100755
--- a/t/t4034-diff-words.sh
+++ b/t/t4034-diff-words.sh
@@ -69,6 +69,10 @@ test_language_driver () {
echo "* diff='"$lang"'" >.gitattributes &&
word_diff --color-words
'
+ test_expect_success "diff driver '$lang' in Islandic" '
+ LANG=is_IS.UTF-8 LANGUAGE=is LC_ALL="$is_IS_locale" \
+ word_diff --color-words
+ '
}
test_expect_success setup '
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/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh
index 65ac7df2d7..e95e6d4e7d 100755
--- a/t/t4115-apply-symlink.sh
+++ b/t/t4115-apply-symlink.sh
@@ -126,4 +126,19 @@ test_expect_success SYMLINKS 'symlink escape when deleting file' '
test_path_is_file .git/delete-me
'
+test_expect_success SYMLINKS '--reject removes .rej symlink if it exists' '
+ test_when_finished "git reset --hard && git clean -dfx" &&
+
+ test_commit file &&
+ echo modified >file.t &&
+ git diff -- file.t >patch &&
+ echo modified-again >file.t &&
+
+ ln -s foo file.t.rej &&
+ test_must_fail git apply patch --reject 2>err &&
+ test_i18ngrep "Rejected hunk" err &&
+ test_path_is_missing foo &&
+ test_path_is_file file.t.rej
+'
+
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/t4300-merge-tree.sh b/t/t4300-merge-tree.sh
index c52c8a21fa..57c4f26e46 100755
--- a/t/t4300-merge-tree.sh
+++ b/t/t4300-merge-tree.sh
@@ -334,4 +334,22 @@ test_expect_success 'turn tree to file' '
test_cmp expect actual
'
+test_expect_success 'merge-tree respects core.useReplaceRefs=false' '
+ test_commit merge-to &&
+ test_commit valid base &&
+ git reset --hard HEAD^ &&
+ test_commit malicious base &&
+
+ test_when_finished "git replace -d $(git rev-parse valid^0)" &&
+ git replace valid^0 malicious^0 &&
+
+ tree=$(git -c core.useReplaceRefs=true merge-tree --write-tree merge-to valid) &&
+ merged=$(git cat-file -p $tree:base) &&
+ test malicious = $merged &&
+
+ tree=$(git -c core.useReplaceRefs=false merge-tree --write-tree merge-to valid) &&
+ merged=$(git cat-file -p $tree:base) &&
+ test valid = $merged
+'
+
test_done
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index f0bd70dbd6..4b4c3315d8 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -426,6 +426,19 @@ test_expect_success 'catch non-matching pathspec' '
test_must_fail git archive -v HEAD -- "*.abc" >/dev/null
'
+test_expect_success 'reject paths outside the current directory' '
+ test_must_fail git -C a/bin archive HEAD .. >/dev/null 2>err &&
+ grep "outside the current directory" err
+'
+
+test_expect_success 'allow pathspecs that resolve to the current directory' '
+ git -C a/bin archive -v HEAD ../bin >/dev/null 2>actual &&
+ cat >expect <<-\EOF &&
+ sh
+ EOF
+ test_cmp expect actual
+'
+
# Pull the size and date of each entry in a tarfile using the system tar.
#
# We'll pull out only the year from the date; that avoids any question of
diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh
index 04d300eeda..0ff47a239d 100755
--- a/t/t5001-archive-attr.sh
+++ b/t/t5001-archive-attr.sh
@@ -33,6 +33,13 @@ test_expect_success 'setup' '
echo ignored-by-tree.d export-ignore >>.gitattributes &&
git add ignored-by-tree ignored-by-tree.d .gitattributes &&
+ mkdir subdir &&
+ >subdir/included &&
+ >subdir/ignored-by-subtree &&
+ >subdir/ignored-by-tree &&
+ echo ignored-by-subtree export-ignore >subdir/.gitattributes &&
+ git add subdir &&
+
echo ignored by worktree >ignored-by-worktree &&
echo ignored-by-worktree export-ignore >.gitattributes &&
git add ignored-by-worktree &&
@@ -93,6 +100,15 @@ test_expect_exists archive-pathspec-wildcard/ignored-by-worktree
test_expect_missing archive-pathspec-wildcard/excluded-by-pathspec.d
test_expect_missing archive-pathspec-wildcard/excluded-by-pathspec.d/file
+test_expect_success 'git -C subdir archive' '
+ git -C subdir archive HEAD >archive-subdir.tar &&
+ extract_tar_to_dir archive-subdir
+'
+
+test_expect_exists archive-subdir/included
+test_expect_missing archive-subdir/ignored-by-subtree
+test_expect_missing archive-subdir/ignored-by-tree
+
test_expect_success 'git archive with worktree attributes' '
git archive --worktree-attributes HEAD >worktree.tar &&
(mkdir worktree && cd worktree && "$TAR" xf -) <worktree.tar
diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh
index f8a0f309e2..d2ce236d61 100755
--- a/t/t5300-pack-object.sh
+++ b/t/t5300-pack-object.sh
@@ -589,141 +589,6 @@ test_expect_success 'prefetch objects' '
test_line_count = 1 donelines
'
-test_expect_success 'setup for --stdin-packs tests' '
- git init stdin-packs &&
- (
- cd stdin-packs &&
-
- test_commit A &&
- test_commit B &&
- test_commit C &&
-
- for id in A B C
- do
- git pack-objects .git/objects/pack/pack-$id \
- --incremental --revs <<-EOF || exit 1
- refs/tags/$id
- EOF
- done &&
-
- ls -la .git/objects/pack
- )
-'
-
-test_expect_success '--stdin-packs with excluded packs' '
- (
- cd stdin-packs &&
-
- PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
- PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
- PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
-
- git pack-objects test --stdin-packs <<-EOF &&
- $PACK_A
- ^$PACK_B
- $PACK_C
- EOF
-
- (
- git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
- git show-index <$(ls .git/objects/pack/pack-C-*.idx)
- ) >expect.raw &&
- git show-index <$(ls test-*.idx) >actual.raw &&
-
- cut -d" " -f2 <expect.raw | sort >expect &&
- cut -d" " -f2 <actual.raw | sort >actual &&
- test_cmp expect actual
- )
-'
-
-test_expect_success '--stdin-packs is incompatible with --filter' '
- (
- cd stdin-packs &&
- test_must_fail git pack-objects --stdin-packs --stdout \
- --filter=blob:none </dev/null 2>err &&
- test_i18ngrep "cannot use --filter with --stdin-packs" err
- )
-'
-
-test_expect_success '--stdin-packs is incompatible with --revs' '
- (
- cd stdin-packs &&
- test_must_fail git pack-objects --stdin-packs --revs out \
- </dev/null 2>err &&
- test_i18ngrep "cannot use internal rev list with --stdin-packs" err
- )
-'
-
-test_expect_success '--stdin-packs with loose objects' '
- (
- cd stdin-packs &&
-
- PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
- PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
- PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
-
- test_commit D && # loose
-
- git pack-objects test2 --stdin-packs --unpacked <<-EOF &&
- $PACK_A
- ^$PACK_B
- $PACK_C
- EOF
-
- (
- git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
- git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
- git rev-list --objects --no-object-names \
- refs/tags/C..refs/tags/D
-
- ) >expect.raw &&
- ls -la . &&
- git show-index <$(ls test2-*.idx) >actual.raw &&
-
- cut -d" " -f2 <expect.raw | sort >expect &&
- cut -d" " -f2 <actual.raw | sort >actual &&
- test_cmp expect actual
- )
-'
-
-test_expect_success '--stdin-packs with broken links' '
- (
- cd stdin-packs &&
-
- # make an unreachable object with a bogus parent
- git cat-file -p HEAD >commit &&
- sed "s/$(git rev-parse HEAD^)/$(test_oid zero)/" <commit |
- git hash-object -w -t commit --stdin >in &&
-
- git pack-objects .git/objects/pack/pack-D <in &&
-
- PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
- PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
- PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
- PACK_D="$(basename .git/objects/pack/pack-D-*.pack)" &&
-
- git pack-objects test3 --stdin-packs --unpacked <<-EOF &&
- $PACK_A
- ^$PACK_B
- $PACK_C
- $PACK_D
- EOF
-
- (
- git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
- git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
- git show-index <$(ls .git/objects/pack/pack-D-*.idx) &&
- git rev-list --objects --no-object-names \
- refs/tags/C..refs/tags/D
- ) >expect.raw &&
- git show-index <$(ls test3-*.idx) >actual.raw &&
-
- cut -d" " -f2 <expect.raw | sort >expect &&
- cut -d" " -f2 <actual.raw | sort >actual &&
- test_cmp expect actual
- )
-'
-
test_expect_success 'negative window clamps to 0' '
git pack-objects --progress --window=-1 neg-window <obj-list 2>stderr &&
check_deltas stderr = 0
diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh
index 5500dd0842..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,23 +51,23 @@ 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
'
test_expect_success 'gc: implicit prune --expire' '
add_blob &&
test-tool chmtime =-$((2*$week-30)) $BLOB_FILE &&
- git gc &&
- verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
+ git gc --no-cruft &&
+ test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE &&
test-tool chmtime =-$((2*$week+1)) $BLOB_FILE &&
- git gc &&
- verbose test $before = $(git count-objects | sed "s/ .*//") &&
+ git gc --no-cruft &&
+ test $before = $(git count-objects | sed "s/ .*//") &&
test_path_is_missing $BLOB_FILE
'
@@ -86,7 +86,7 @@ test_expect_success 'gc: refuse to start with invalid gc.pruneExpire' '
test_expect_success 'gc: start with ok gc.pruneExpire' '
git config gc.pruneExpire 2.days.ago &&
- git gc
+ git gc --no-cruft
'
test_expect_success 'prune: prune nonsense parameters' '
@@ -137,44 +137,44 @@ test_expect_success 'gc --no-prune' '
add_blob &&
test-tool chmtime =-$((5001*$day)) $BLOB_FILE &&
git config gc.pruneExpire 2.days.ago &&
- git gc --no-prune &&
- verbose test 1 = $(git count-objects | sed "s/ .*//") &&
+ git gc --no-prune --no-cruft &&
+ test 1 = $(git count-objects | sed "s/ .*//") &&
test_path_is_file $BLOB_FILE
'
test_expect_success 'gc respects gc.pruneExpire' '
git config gc.pruneExpire 5002.days.ago &&
- git gc &&
+ git gc --no-cruft &&
test_path_is_file $BLOB_FILE &&
git config gc.pruneExpire 5000.days.ago &&
- git gc &&
+ git gc --no-cruft &&
test_path_is_missing $BLOB_FILE
'
test_expect_success 'gc --prune=<date>' '
add_blob &&
test-tool chmtime =-$((5001*$day)) $BLOB_FILE &&
- git gc --prune=5002.days.ago &&
+ git gc --prune=5002.days.ago --no-cruft &&
test_path_is_file $BLOB_FILE &&
- git gc --prune=5000.days.ago &&
+ git gc --prune=5000.days.ago --no-cruft &&
test_path_is_missing $BLOB_FILE
'
test_expect_success 'gc --prune=never' '
add_blob &&
- git gc --prune=never &&
+ git gc --prune=never --no-cruft &&
test_path_is_file $BLOB_FILE &&
- git gc --prune=now &&
+ git gc --prune=now --no-cruft &&
test_path_is_missing $BLOB_FILE
'
test_expect_success 'gc respects gc.pruneExpire=never' '
git config gc.pruneExpire never &&
add_blob &&
- git gc &&
+ git gc --no-cruft &&
test_path_is_file $BLOB_FILE &&
git config gc.pruneExpire now &&
- git gc &&
+ git gc --no-cruft &&
test_path_is_missing $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 &&
- verbose test 0 = $(git count-objects | sed "s/ .*//") &&
+ git gc --prune --no-cruft &&
+ test 0 = $(git count-objects | sed "s/ .*//") &&
test_path_is_missing $BLOB_FILE
)
'
@@ -237,7 +237,7 @@ test_expect_success 'clean pack garbage with gc' '
>.git/objects/pack/fake2.keep &&
>.git/objects/pack/fake2.idx &&
>.git/objects/pack/fake3.keep &&
- git gc &&
+ git gc --no-cruft &&
git count-objects -v 2>stderr &&
grep "^warning:" stderr | sort >actual &&
cat >expected <<\EOF &&
diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh
index 499d5d4c78..0883c7c6bd 100755
--- a/t/t5319-multi-pack-index.sh
+++ b/t/t5319-multi-pack-index.sh
@@ -183,6 +183,18 @@ test_expect_success 'write midx with --stdin-packs' '
compare_results_with_midx "mixed mode (one pack + extra)"
+test_expect_success 'write with no objects and preferred pack' '
+ test_when_finished "rm -rf empty" &&
+ git init empty &&
+ test_must_fail git -C empty multi-pack-index write \
+ --stdin-packs --preferred-pack=does-not-exist </dev/null 2>err &&
+ cat >expect <<-EOF &&
+ warning: unknown preferred pack: ${SQ}does-not-exist${SQ}
+ error: no pack files to index.
+ EOF
+ test_cmp expect err
+'
+
test_expect_success 'write progress off for redirected stderr' '
git multi-pack-index --object-dir=$objdir write 2>err &&
test_line_count = 0 err
diff --git a/t/t5325-reverse-index.sh b/t/t5325-reverse-index.sh
index d042d26f2b..431a603ca0 100755
--- a/t/t5325-reverse-index.sh
+++ b/t/t5325-reverse-index.sh
@@ -1,17 +1,20 @@
#!/bin/sh
test_description='on-disk reverse index'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# The below tests want control over the 'pack.writeReverseIndex' setting
# themselves to assert various combinations of it with other options.
-sane_unset GIT_TEST_WRITE_REV_INDEX
+sane_unset GIT_TEST_NO_WRITE_REV_INDEX
packdir=.git/objects/pack
test_expect_success 'setup' '
test_commit base &&
+ test_config pack.writeReverseIndex false &&
pack=$(git pack-objects --all $packdir/pack) &&
rev=$packdir/pack-$pack.rev &&
@@ -94,6 +97,17 @@ test_expect_success 'reverse index is not generated when available on disk' '
--batch-check="%(objectsize:disk)" <tip
'
+test_expect_success 'reverse index is ignored when pack.readReverseIndex is false' '
+ test_index_pack true &&
+ test_path_is_file $rev &&
+
+ test_config pack.readReverseIndex false &&
+
+ git rev-parse HEAD >tip &&
+ GIT_TEST_REV_INDEX_DIE_ON_DISK=1 git cat-file \
+ --batch-check="%(objectsize:disk)" <tip
+'
+
test_expect_success 'revindex in-memory vs on-disk' '
git init repo &&
test_when_finished "rm -fr repo" &&
@@ -117,4 +131,78 @@ test_expect_success 'revindex in-memory vs on-disk' '
test_cmp on-disk in-core
)
'
+
+test_expect_success 'fsck succeeds on good rev-index' '
+ test_when_finished rm -fr repo &&
+ git init repo &&
+ (
+ cd repo &&
+
+ test_commit commit &&
+ git -c pack.writeReverseIndex=true repack -ad &&
+ git fsck 2>err &&
+ test_must_be_empty err
+ )
+'
+
+test_expect_success 'set up rev-index corruption tests' '
+ git init corrupt &&
+ (
+ cd corrupt &&
+
+ test_commit commit &&
+ git -c pack.writeReverseIndex=true repack -ad &&
+
+ revfile=$(ls .git/objects/pack/pack-*.rev) &&
+ chmod a+w $revfile &&
+ cp $revfile $revfile.bak
+ )
+'
+
+corrupt_rev_and_verify () {
+ (
+ pos="$1" &&
+ value="$2" &&
+ error="$3" &&
+
+ cd corrupt &&
+ revfile=$(ls .git/objects/pack/pack-*.rev) &&
+
+ # Reset to original rev-file.
+ cp $revfile.bak $revfile &&
+
+ printf "$value" | dd of=$revfile bs=1 seek="$pos" conv=notrunc &&
+ test_must_fail git fsck 2>err &&
+ grep "$error" err
+ )
+}
+
+test_expect_success 'fsck catches invalid checksum' '
+ revfile=$(ls corrupt/.git/objects/pack/pack-*.rev) &&
+ orig_size=$(wc -c <$revfile) &&
+ hashpos=$((orig_size - 10)) &&
+ corrupt_rev_and_verify $hashpos bogus \
+ "invalid checksum"
+'
+
+test_expect_success 'fsck catches invalid row position' '
+ corrupt_rev_and_verify 14 "\07" \
+ "invalid rev-index position"
+'
+
+test_expect_success 'fsck catches invalid header: magic number' '
+ corrupt_rev_and_verify 1 "\07" \
+ "reverse-index file .* has unknown signature"
+'
+
+test_expect_success 'fsck catches invalid header: version' '
+ corrupt_rev_and_verify 7 "\02" \
+ "reverse-index file .* has unsupported version"
+'
+
+test_expect_success 'fsck catches invalid header: hash function' '
+ corrupt_rev_and_verify 11 "\03" \
+ "reverse-index file .* has unsupported hash id"
+'
+
test_done
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/t5331-pack-objects-stdin.sh b/t/t5331-pack-objects-stdin.sh
new file mode 100755
index 0000000000..acab31667a
--- /dev/null
+++ b/t/t5331-pack-objects-stdin.sh
@@ -0,0 +1,240 @@
+#!/bin/sh
+
+test_description='pack-objects --stdin'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+packed_objects () {
+ git show-index <"$1" >tmp-object-list &&
+ cut -d' ' -f2 tmp-object-list | sort &&
+ rm tmp-object-list
+ }
+
+test_expect_success 'setup for --stdin-packs tests' '
+ git init stdin-packs &&
+ (
+ cd stdin-packs &&
+
+ test_commit A &&
+ test_commit B &&
+ test_commit C &&
+
+ for id in A B C
+ do
+ git pack-objects .git/objects/pack/pack-$id \
+ --incremental --revs <<-EOF || exit 1
+ refs/tags/$id
+ EOF
+ done &&
+
+ ls -la .git/objects/pack
+ )
+'
+
+test_expect_success '--stdin-packs with excluded packs' '
+ (
+ cd stdin-packs &&
+
+ PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
+ PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
+ PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
+
+ git pack-objects test --stdin-packs <<-EOF &&
+ $PACK_A
+ ^$PACK_B
+ $PACK_C
+ EOF
+
+ (
+ git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
+ git show-index <$(ls .git/objects/pack/pack-C-*.idx)
+ ) >expect.raw &&
+ git show-index <$(ls test-*.idx) >actual.raw &&
+
+ cut -d" " -f2 <expect.raw | sort >expect &&
+ cut -d" " -f2 <actual.raw | sort >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success '--stdin-packs is incompatible with --filter' '
+ (
+ cd stdin-packs &&
+ test_must_fail git pack-objects --stdin-packs --stdout \
+ --filter=blob:none </dev/null 2>err &&
+ test_i18ngrep "cannot use --filter with --stdin-packs" err
+ )
+'
+
+test_expect_success '--stdin-packs is incompatible with --revs' '
+ (
+ cd stdin-packs &&
+ test_must_fail git pack-objects --stdin-packs --revs out \
+ </dev/null 2>err &&
+ test_i18ngrep "cannot use internal rev list with --stdin-packs" err
+ )
+'
+
+test_expect_success '--stdin-packs with loose objects' '
+ (
+ cd stdin-packs &&
+
+ PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
+ PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
+ PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
+
+ test_commit D && # loose
+
+ git pack-objects test2 --stdin-packs --unpacked <<-EOF &&
+ $PACK_A
+ ^$PACK_B
+ $PACK_C
+ EOF
+
+ (
+ git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
+ git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
+ git rev-list --objects --no-object-names \
+ refs/tags/C..refs/tags/D
+
+ ) >expect.raw &&
+ ls -la . &&
+ git show-index <$(ls test2-*.idx) >actual.raw &&
+
+ cut -d" " -f2 <expect.raw | sort >expect &&
+ cut -d" " -f2 <actual.raw | sort >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success '--stdin-packs with broken links' '
+ (
+ cd stdin-packs &&
+
+ # make an unreachable object with a bogus parent
+ git cat-file -p HEAD >commit &&
+ sed "s/$(git rev-parse HEAD^)/$(test_oid zero)/" <commit |
+ git hash-object -w -t commit --stdin >in &&
+
+ git pack-objects .git/objects/pack/pack-D <in &&
+
+ PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
+ PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
+ PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
+ PACK_D="$(basename .git/objects/pack/pack-D-*.pack)" &&
+
+ git pack-objects test3 --stdin-packs --unpacked <<-EOF &&
+ $PACK_A
+ ^$PACK_B
+ $PACK_C
+ $PACK_D
+ EOF
+
+ (
+ git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
+ git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
+ git show-index <$(ls .git/objects/pack/pack-D-*.idx) &&
+ git rev-list --objects --no-object-names \
+ refs/tags/C..refs/tags/D
+ ) >expect.raw &&
+ git show-index <$(ls test3-*.idx) >actual.raw &&
+
+ cut -d" " -f2 <expect.raw | sort >expect &&
+ cut -d" " -f2 <actual.raw | sort >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'pack-objects --stdin with duplicate packfile' '
+ test_when_finished "rm -fr repo" &&
+
+ git init repo &&
+ (
+ cd repo &&
+ test_commit "commit" &&
+ git repack -ad &&
+
+ {
+ basename .git/objects/pack/pack-*.pack &&
+ basename .git/objects/pack/pack-*.pack
+ } >packfiles &&
+
+ git pack-objects --stdin-packs generated-pack <packfiles &&
+ packed_objects .git/objects/pack/pack-*.idx >expect &&
+ packed_objects generated-pack-*.idx >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'pack-objects --stdin with same packfile excluded and included' '
+ test_when_finished "rm -fr repo" &&
+
+ git init repo &&
+ (
+ cd repo &&
+ test_commit "commit" &&
+ git repack -ad &&
+
+ {
+ basename .git/objects/pack/pack-*.pack &&
+ printf "^%s\n" "$(basename .git/objects/pack/pack-*.pack)"
+ } >packfiles &&
+
+ git pack-objects --stdin-packs generated-pack <packfiles &&
+ packed_objects generated-pack-*.idx >packed-objects &&
+ test_must_be_empty packed-objects
+ )
+'
+
+test_expect_success 'pack-objects --stdin with packfiles from alternate object database' '
+ test_when_finished "rm -fr shared member" &&
+
+ # Set up a shared repository with a single packfile.
+ git init shared &&
+ test_commit -C shared "shared-objects" &&
+ git -C shared repack -ad &&
+ basename shared/.git/objects/pack/pack-*.pack >packfile &&
+
+ # Set up a repository that is connected to the shared repository. This
+ # repository has no objects on its own, but we still expect to be able
+ # to pack objects from its alternate.
+ git clone --shared shared member &&
+ git -C member pack-objects --stdin-packs generated-pack <packfile &&
+ test_cmp shared/.git/objects/pack/pack-*.pack member/generated-pack-*.pack
+'
+
+test_expect_success 'pack-objects --stdin with packfiles from main and alternate object database' '
+ test_when_finished "rm -fr shared member" &&
+
+ # Set up a shared repository with a single packfile.
+ git init shared &&
+ test_commit -C shared "shared-commit" &&
+ git -C shared repack -ad &&
+
+ # Set up a repository that is connected to the shared repository. This
+ # repository has a second packfile so that we can verify that it is
+ # possible to write packs that include packfiles from different object
+ # databases.
+ git clone --shared shared member &&
+ test_commit -C member "local-commit" &&
+ git -C member repack -dl &&
+
+ {
+ basename shared/.git/objects/pack/pack-*.pack &&
+ basename member/.git/objects/pack/pack-*.pack
+ } >packfiles &&
+
+ {
+ packed_objects shared/.git/objects/pack/pack-*.idx &&
+ packed_objects member/.git/objects/pack/pack-*.idx
+ } | sort >expected-objects &&
+
+ git -C member pack-objects --stdin-packs generated-pack <packfiles &&
+ packed_objects member/generated-pack-*.idx >actual-objects &&
+ test_cmp expected-objects actual-objects
+'
+
+test_done
diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
index 20d063fb9a..151c76eb09 100755
--- a/t/t5512-ls-remote.sh
+++ b/t/t5512-ls-remote.sh
@@ -15,6 +15,19 @@ generate_references () {
done
}
+test_expect_success 'set up fake upload-pack' '
+ # This can be used to simulate an upload-pack that just shows the
+ # contents of the "input" file (prepared with the test-tool pkt-line
+ # helper), and does not do any negotiation (since ls-remote does not
+ # need it).
+ write_script cat-input <<-\EOF
+ # send our initial advertisement/response
+ cat input
+ # soak up the flush packet from the client
+ cat
+ EOF
+'
+
test_expect_success 'dies when no remote found' '
test_must_fail git ls-remote
'
@@ -231,22 +244,25 @@ test_expect_success 'protocol v2 supports hiderefs' '
test_expect_success 'ls-remote --symref' '
git fetch origin &&
- echo "ref: refs/heads/main HEAD" >expect &&
+ echo "ref: refs/heads/main HEAD" >expect.v2 &&
generate_references \
HEAD \
- refs/heads/main >>expect &&
+ refs/heads/main >>expect.v2 &&
+ echo "ref: refs/remotes/origin/main refs/remotes/origin/HEAD" >>expect.v2 &&
oid=$(git rev-parse HEAD) &&
- echo "$oid refs/remotes/origin/HEAD" >>expect &&
+ echo "$oid refs/remotes/origin/HEAD" >>expect.v2 &&
generate_references \
refs/remotes/origin/main \
refs/tags/mark \
refs/tags/mark1.1 \
refs/tags/mark1.10 \
- refs/tags/mark1.2 >>expect &&
- # Protocol v2 supports sending symrefs for refs other than HEAD, so use
- # protocol v0 here.
- GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref >actual &&
- test_cmp expect actual
+ refs/tags/mark1.2 >>expect.v2 &&
+ # v0 does not show non-HEAD symrefs
+ grep -v "ref: refs/remotes" <expect.v2 >expect.v0 &&
+ git -c protocol.version=0 ls-remote --symref >actual.v0 &&
+ test_cmp expect.v0 actual.v0 &&
+ git -c protocol.version=2 ls-remote --symref >actual.v2 &&
+ test_cmp expect.v2 actual.v2
'
test_expect_success 'ls-remote with filtered symref (refname)' '
@@ -255,76 +271,41 @@ test_expect_success 'ls-remote with filtered symref (refname)' '
ref: refs/heads/main HEAD
$rev HEAD
EOF
- # Protocol v2 supports sending symrefs for refs other than HEAD, so use
- # protocol v0 here.
- GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref . HEAD >actual &&
+ git ls-remote --symref . HEAD >actual &&
test_cmp expect actual
'
-test_expect_failure 'ls-remote with filtered symref (--heads)' '
+test_expect_success 'ls-remote with filtered symref (--heads)' '
git symbolic-ref refs/heads/foo refs/tags/mark &&
- cat >expect <<-EOF &&
+ cat >expect.v2 <<-EOF &&
ref: refs/tags/mark refs/heads/foo
$rev refs/heads/foo
$rev refs/heads/main
EOF
- # Protocol v2 supports sending symrefs for refs other than HEAD, so use
- # protocol v0 here.
- GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref --heads . >actual &&
- test_cmp expect actual
+ grep -v "^ref: refs/tags/" <expect.v2 >expect.v0 &&
+ git -c protocol.version=0 ls-remote --symref --heads . >actual.v0 &&
+ test_cmp expect.v0 actual.v0 &&
+ git -c protocol.version=2 ls-remote --symref --heads . >actual.v2 &&
+ test_cmp expect.v2 actual.v2
'
-test_expect_success 'ls-remote --symref omits filtered-out matches' '
- cat >expect <<-EOF &&
- $rev refs/heads/foo
- $rev refs/heads/main
+test_expect_success 'indicate no refs in v0 standards-compliant empty remote' '
+ # Git does not produce an output like this, but it does match the
+ # standard and is produced by other implementations like JGit. So
+ # hard-code the case we care about.
+ #
+ # The actual capabilities do not matter; there are none that would
+ # change how ls-remote behaves.
+ oid=0000000000000000000000000000000000000000 &&
+ test-tool pkt-line pack >input.q <<-EOF &&
+ $oid capabilities^{}Qcaps-go-here
+ 0000
EOF
- # Protocol v2 supports sending symrefs for refs other than HEAD, so use
- # protocol v0 here.
- GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref --heads . >actual &&
- test_cmp expect actual &&
- GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref . "refs/heads/*" >actual &&
- test_cmp expect actual
-'
-
-test_lazy_prereq GIT_DAEMON '
- test_bool_env GIT_TEST_GIT_DAEMON true
-'
+ q_to_nul <input.q >input &&
-# This test spawns a daemon, so run it only if the user would be OK with
-# testing with git-daemon.
-test_expect_success PIPE,JGIT,GIT_DAEMON 'indicate no refs in standards-compliant empty remote' '
- test_set_port JGIT_DAEMON_PORT &&
- JGIT_DAEMON_PID= &&
- git init --bare empty.git &&
- >empty.git/git-daemon-export-ok &&
- mkfifo jgit_daemon_output &&
- {
- jgit daemon --port="$JGIT_DAEMON_PORT" . >jgit_daemon_output &
- JGIT_DAEMON_PID=$!
- } &&
- test_when_finished kill "$JGIT_DAEMON_PID" &&
- {
- read line &&
- case $line in
- Exporting*)
- ;;
- *)
- echo "Expected: Exporting" &&
- false;;
- esac &&
- read line &&
- case $line in
- "Listening on"*)
- ;;
- *)
- echo "Expected: Listening on" &&
- false;;
- esac
- } <jgit_daemon_output &&
# --exit-code asks the command to exit with 2 when no
# matching refs are found.
- test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git
+ test_expect_code 2 git ls-remote --exit-code --upload-pack=./cat-input .
'
test_expect_success 'ls-remote works outside repository' '
@@ -345,8 +326,8 @@ test_expect_success 'ls-remote --sort fails gracefully outside repository' '
test_expect_success 'ls-remote patterns work with all protocol versions' '
git for-each-ref --format="%(objectname) %(refname)" \
refs/heads/main refs/remotes/origin/main >expect &&
- git -c protocol.version=1 ls-remote . main >actual.v1 &&
- test_cmp expect actual.v1 &&
+ git -c protocol.version=0 ls-remote . main >actual.v0 &&
+ test_cmp expect actual.v0 &&
git -c protocol.version=2 ls-remote . main >actual.v2 &&
test_cmp expect actual.v2
'
@@ -354,10 +335,49 @@ test_expect_success 'ls-remote patterns work with all protocol versions' '
test_expect_success 'ls-remote prefixes work with all protocol versions' '
git for-each-ref --format="%(objectname) %(refname)" \
refs/heads/ refs/tags/ >expect &&
- git -c protocol.version=1 ls-remote --heads --tags . >actual.v1 &&
- test_cmp expect actual.v1 &&
+ git -c protocol.version=0 ls-remote --heads --tags . >actual.v0 &&
+ test_cmp expect actual.v0 &&
git -c protocol.version=2 ls-remote --heads --tags . >actual.v2 &&
test_cmp expect actual.v2
'
+test_expect_success 'v0 clients can handle multiple symrefs' '
+ # Modern versions of Git will not return multiple symref capabilities
+ # for v0, so we have to hard-code the response. Note that we will
+ # always use both v0 and object-format=sha1 here, as the hard-coded
+ # response reflects a server that only supports those.
+ oid=1234567890123456789012345678901234567890 &&
+ symrefs="symref=refs/remotes/origin/HEAD:refs/remotes/origin/main" &&
+ symrefs="$symrefs symref=HEAD:refs/heads/main" &&
+
+ # Likewise we want to make sure our parser is not fooled by the string
+ # "symref" appearing as part of an earlier cap. But there is no way to
+ # do that via upload-pack, as arbitrary strings can appear only in a
+ # "symref" value itself (where we skip past the values as a whole)
+ # and "agent" (which always appears after "symref", so putting our
+ # parser in a confused state is less interesting).
+ caps="some other caps including a-fake-symref-cap" &&
+
+ test-tool pkt-line pack >input.q <<-EOF &&
+ $oid HEADQ$caps $symrefs
+ $oid refs/heads/main
+ $oid refs/remotes/origin/HEAD
+ $oid refs/remotes/origin/main
+ 0000
+ EOF
+ q_to_nul <input.q >input &&
+
+ cat >expect <<-EOF &&
+ ref: refs/heads/main HEAD
+ $oid HEAD
+ $oid refs/heads/main
+ ref: refs/remotes/origin/main refs/remotes/origin/HEAD
+ $oid refs/remotes/origin/HEAD
+ $oid refs/remotes/origin/main
+ EOF
+
+ git ls-remote --symref --upload-pack=./cat-input . >actual &&
+ test_cmp expect actual
+'
+
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/t5604-clone-reference.sh b/t/t5604-clone-reference.sh
index 83e3c97861..9845fc04d5 100755
--- a/t/t5604-clone-reference.sh
+++ b/t/t5604-clone-reference.sh
@@ -358,7 +358,7 @@ test_expect_success SYMLINKS 'clone repo with symlinked objects directory' '
test_must_fail git clone --local malicious clone 2>err &&
test_path_is_missing clone &&
- grep "failed to start iterator over" err
+ grep "is a symlink, refusing to clone with --local" err
'
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/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index 6614469d2d..5c00607608 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -1374,6 +1374,14 @@ test_expect_success 'for-each-ref --ignore-case ignores case' '
test_cmp expect actual
'
+test_expect_success 'for-each-ref --omit-empty works' '
+ git for-each-ref --format="%(refname)" >actual &&
+ test_line_count -gt 1 actual &&
+ git for-each-ref --format="%(if:equals=refs/heads/main)%(refname)%(then)%(refname)%(end)" --omit-empty >actual &&
+ echo refs/heads/main >expect &&
+ test_cmp expect actual
+'
+
test_expect_success 'for-each-ref --ignore-case works on multiple sort keys' '
# name refs numerically to avoid case-insensitive filesystem conflicts
nr=0 &&
diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh
index d9acb63951..69509d0c11 100755
--- a/t/t6500-gc.sh
+++ b/t/t6500-gc.sh
@@ -210,90 +210,95 @@ prepare_cruft_history () {
git reset HEAD^^
}
-assert_cruft_packs () {
- find .git/objects/pack -name "*.mtimes" >mtimes &&
- sed -e 's/\.mtimes$/\.pack/g' mtimes >packs &&
-
- test_file_not_empty packs &&
- while read pack
- do
- test_path_is_file "$pack" || return 1
- done <packs
-}
-
assert_no_cruft_packs () {
find .git/objects/pack -name "*.mtimes" >mtimes &&
test_must_be_empty mtimes
}
-test_expect_success 'gc --cruft generates a cruft pack' '
- test_when_finished "rm -fr crufts" &&
- git init crufts &&
+for argv in \
+ "gc" \
+ "-c gc.cruftPacks=true gc" \
+ "-c gc.cruftPacks=false gc --cruft"
+do
+ test_expect_success "git $argv generates a cruft pack" '
+ test_when_finished "rm -fr repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ prepare_cruft_history &&
+ git $argv &&
+
+ find .git/objects/pack -name "*.mtimes" >mtimes &&
+ sed -e 's/\.mtimes$/\.pack/g' mtimes >packs &&
+
+ test_file_not_empty packs &&
+ while read pack
+ do
+ test_path_is_file "$pack" || return 1
+ done <packs
+ )
+ '
+done
+
+for argv in \
+ "gc --no-cruft" \
+ "-c gc.cruftPacks=false gc" \
+ "-c gc.cruftPacks=true gc --no-cruft"
+do
+ test_expect_success "git $argv does not generate a cruft pack" '
+ test_when_finished "rm -fr repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ prepare_cruft_history &&
+ git $argv &&
+
+ assert_no_cruft_packs
+ )
+ '
+done
+
+test_expect_success '--keep-largest-pack ignores cruft packs' '
+ test_when_finished "rm -fr repo" &&
+ git init repo &&
(
- cd crufts &&
+ cd repo &&
+ # Generate a pack for reachable objects (of which there
+ # are 3), and one for unreachable objects (of which
+ # there are 6).
prepare_cruft_history &&
git gc --cruft &&
- assert_cruft_packs
- )
-'
-
-test_expect_success 'gc.cruftPacks=true generates a cruft pack' '
- test_when_finished "rm -fr crufts" &&
- git init crufts &&
- (
- cd crufts &&
-
- prepare_cruft_history &&
- git -c gc.cruftPacks=true gc &&
- assert_cruft_packs
- )
-'
-
-test_expect_success 'feature.experimental=true generates a cruft pack' '
- git init crufts &&
- test_when_finished "rm -fr crufts" &&
- (
- cd crufts &&
- prepare_cruft_history &&
- git -c feature.experimental=true gc &&
- assert_cruft_packs
- )
-'
+ mtimes="$(find .git/objects/pack -type f -name "pack-*.mtimes")" &&
+ sz="$(test_file_size "${mtimes%.mtimes}.pack")" &&
-test_expect_success 'feature.experimental=false allows explicit cruft packs' '
- git init crufts &&
- test_when_finished "rm -fr crufts" &&
- (
- cd crufts &&
+ # Ensure that the cruft pack gets removed (due to
+ # `--prune=now`) despite it being the largest pack.
+ git -c gc.bigPackThreshold=$sz gc --cruft --prune=now &&
- prepare_cruft_history &&
- git -c gc.cruftPacks=true -c feature.experimental=false gc &&
- assert_cruft_packs
+ assert_no_cruft_packs
)
'
-test_expect_success 'feature.experimental=true can be overridden' '
- git init crufts &&
- test_when_finished "rm -fr crufts" &&
+test_expect_success 'gc.bigPackThreshold ignores cruft packs' '
+ test_when_finished "rm -fr repo" &&
+ git init repo &&
(
- cd crufts &&
+ cd repo &&
+ # Generate a pack for reachable objects (of which there
+ # are 3), and one for unreachable objects (of which
+ # there are 6).
prepare_cruft_history &&
- git -c feature.expiremental=true -c gc.cruftPacks=false gc &&
- assert_no_cruft_packs
- )
-'
+ git gc --cruft &&
-test_expect_success 'feature.experimental=false avoids cruft packs by default' '
- git init crufts &&
- test_when_finished "rm -fr crufts" &&
- (
- cd crufts &&
+ # Ensure that the cruft pack gets removed (due to
+ # `--prune=now`) despite it being the largest pack.
+ git gc --cruft --prune=now --keep-largest-pack &&
- prepare_cruft_history &&
- git -c feature.experimental=false gc &&
assert_no_cruft_packs
)
'
diff --git a/t/t6501-freshen-objects.sh b/t/t6501-freshen-objects.sh
index 3968b47ed5..4521508b83 100755
--- a/t/t6501-freshen-objects.sh
+++ b/t/t6501-freshen-objects.sh
@@ -101,7 +101,7 @@ do
'
test_expect_success "simultaneous gc ($title)" '
- git gc --prune=12.hours.ago
+ git gc --no-cruft --prune=12.hours.ago
'
test_expect_success "finish writing out commit ($title)" '
@@ -131,7 +131,7 @@ do
'
test_expect_success "simultaneous gc ($title)" '
- git gc --prune=12.hours.ago
+ git gc --no-cruft --prune=12.hours.ago
'
# tree should have been refreshed by write-tree
@@ -151,8 +151,8 @@ test_expect_success 'do not complain about existing broken links (commit)' '
some message
EOF
commit=$(git hash-object -t commit -w broken-commit) &&
- git gc -q 2>stderr &&
- verbose git cat-file -e $commit &&
+ git gc --no-cruft -q 2>stderr &&
+ git cat-file -e $commit &&
test_must_be_empty stderr
'
@@ -161,7 +161,7 @@ test_expect_success 'do not complain about existing broken links (tree)' '
100644 blob $(test_oid 003) foo
EOF
tree=$(git mktree --missing <broken-tree) &&
- git gc -q 2>stderr &&
+ git gc --no-cruft -q 2>stderr &&
git cat-file -e $tree &&
test_must_be_empty stderr
'
@@ -176,7 +176,7 @@ test_expect_success 'do not complain about existing broken links (tag)' '
this is a broken tag
EOF
tag=$(git hash-object -t tag -w broken-tag) &&
- git gc -q 2>stderr &&
+ git gc --no-cruft -q 2>stderr &&
git cat-file -e $tag &&
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/t7004-tag.sh b/t/t7004-tag.sh
index 32b312fa80..0fe6ba93a2 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -2046,6 +2046,22 @@ test_expect_success '--format should list tags as per format given' '
test_cmp expect actual
'
+test_expect_success '--format --omit-empty works' '
+ cat >expect <<-\EOF &&
+ refname : refs/tags/v1.0
+
+ refname : refs/tags/v1.1.3
+ EOF
+ git tag -l --format="%(if:notequals=refs/tags/v1.0.1)%(refname)%(then)refname : %(refname)%(end)" "v1*" >actual &&
+ test_cmp expect actual &&
+ cat >expect <<-\EOF &&
+ refname : refs/tags/v1.0
+ refname : refs/tags/v1.1.3
+ EOF
+ git tag -l --omit-empty --format="%(if:notequals=refs/tags/v1.0.1)%(refname)%(then)refname : %(refname)%(end)" "v1*" >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'git tag -l with --format="%(rest)" must fail' '
test_must_fail git tag -l --format="%(rest)" "v1*"
'
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/t7510-signed-commit.sh b/t/t7510-signed-commit.sh
index 48f86cb367..ccbc416402 100755
--- a/t/t7510-signed-commit.sh
+++ b/t/t7510-signed-commit.sh
@@ -221,84 +221,91 @@ test_expect_success GPG 'amending already signed commit' '
test_expect_success GPG 'show good signature with custom format' '
cat >expect <<-\EOF &&
G
+ ultimate
13B6F51ECDDE430D
C O Mitter <committer@example.com>
73D758744BE721698EC54E8713B6F51ECDDE430D
73D758744BE721698EC54E8713B6F51ECDDE430D
EOF
- git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show bad signature with custom format' '
cat >expect <<-\EOF &&
B
+ undefined
13B6F51ECDDE430D
C O Mitter <committer@example.com>
EOF
- git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" $(cat forged1.commit) >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" $(cat forged1.commit) >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show untrusted signature with custom format' '
cat >expect <<-\EOF &&
U
+ undefined
65A0EEA02E30CAD7
Eris Discordia <discord@example.net>
F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7
D4BE22311AD3131E5EDA29A461092E85B7227189
EOF
- git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show untrusted signature with undefined trust level' '
cat >expect <<-\EOF &&
+ U
undefined
65A0EEA02E30CAD7
Eris Discordia <discord@example.net>
F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7
D4BE22311AD3131E5EDA29A461092E85B7227189
EOF
- git log -1 --format="%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show untrusted signature with ultimate trust level' '
cat >expect <<-\EOF &&
+ G
ultimate
13B6F51ECDDE430D
C O Mitter <committer@example.com>
73D758744BE721698EC54E8713B6F51ECDDE430D
73D758744BE721698EC54E8713B6F51ECDDE430D
EOF
- git log -1 --format="%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show unknown signature with custom format' '
cat >expect <<-\EOF &&
E
+ undefined
65A0EEA02E30CAD7
EOF
- GNUPGHOME="$GNUPGHOME_NOT_USED" git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
+ GNUPGHOME="$GNUPGHOME_NOT_USED" git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual &&
test_cmp expect actual
'
test_expect_success GPG 'show lack of signature with custom format' '
cat >expect <<-\EOF &&
N
+ undefined
EOF
- git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" seventh-unsigned >actual &&
+ git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" seventh-unsigned >actual &&
test_cmp expect actual
'
diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
index 4aabe98139..faa739eeb9 100755
--- a/t/t7700-repack.sh
+++ b/t/t7700-repack.sh
@@ -106,6 +106,23 @@ test_expect_success SYMLINKS '--local keeps packs when alternate is objectdir '
test_cmp expect actual
'
+test_expect_success '--local disables writing bitmaps when connected to alternate ODB' '
+ test_when_finished "rm -rf shared member" &&
+
+ git init shared &&
+ git clone --shared shared member &&
+ (
+ cd member &&
+ test_commit "object" &&
+ GIT_TEST_MULTI_PACK_INDEX=0 git repack -Adl --write-bitmap-index 2>err &&
+ cat >expect <<-EOF &&
+ warning: disabling bitmap writing, as some objects are not being packed
+ EOF
+ test_cmp expect err &&
+ test_path_is_missing .git/objects/pack-*.bitmap
+ )
+'
+
test_expect_success 'packed obs in alt ODB are repacked even when local repo is packless' '
mkdir alt_objects/pack &&
mv .git/objects/pack/* alt_objects/pack &&
diff --git a/t/t7703-repack-geometric.sh b/t/t7703-repack-geometric.sh
index 8821fbd2dd..00f28fb558 100755
--- a/t/t7703-repack-geometric.sh
+++ b/t/t7703-repack-geometric.sh
@@ -10,6 +10,12 @@ objdir=.git/objects
packdir=$objdir/pack
midx=$objdir/pack/multi-pack-index
+packed_objects () {
+ git show-index <"$1" >tmp-object-list &&
+ cut -d' ' -f2 tmp-object-list | sort &&
+ rm tmp-object-list
+ }
+
test_expect_success '--geometric with no packs' '
git init geometric &&
test_when_finished "rm -fr geometric" &&
@@ -281,4 +287,162 @@ test_expect_success '--geometric with pack.packSizeLimit' '
)
'
+test_expect_success '--geometric --write-midx with packfiles in main and alternate ODB' '
+ test_when_finished "rm -fr shared member" &&
+
+ # Create a shared repository that will serve as the alternate object
+ # database for the member linked to it. It has got some objects on its
+ # own that are packed into a single packfile.
+ git init shared &&
+ test_commit -C shared common-object &&
+ git -C shared repack -ad &&
+
+ # We create member so that its alternates file points to the shared
+ # repository. We then create a commit in it so that git-repack(1) has
+ # something to repack.
+ # of the shared object database.
+ git clone --shared shared member &&
+ test_commit -C member unique-object &&
+ git -C member repack --geometric=2 --write-midx 2>err &&
+ test_must_be_empty err &&
+
+ # We should see that a new packfile was generated.
+ find shared/.git/objects/pack -type f -name "*.pack" >packs &&
+ test_line_count = 1 packs &&
+
+ # We should also see a multi-pack-index. This multi-pack-index should
+ # never refer to any packfiles in the alternate object database.
+ test_path_is_file member/.git/objects/pack/multi-pack-index &&
+ test-tool read-midx member/.git/objects >packs.midx &&
+ grep "^pack-.*\.idx$" packs.midx | sort >actual &&
+ basename member/.git/objects/pack/pack-*.idx >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success '--geometric --with-midx with no local objects' '
+ test_when_finished "rm -fr shared member" &&
+
+ # Create a repository with a single packfile that acts as alternate
+ # object database.
+ git init shared &&
+ test_commit -C shared "shared-objects" &&
+ git -C shared repack -ad &&
+
+ # Create a second repository linked to the first one and perform a
+ # geometric repack on it.
+ git clone --shared shared member &&
+ git -C member repack --geometric 2 --write-midx 2>err &&
+ test_must_be_empty err &&
+
+ # Assert that we wrote neither a new packfile nor a multi-pack-index.
+ # We should not have a packfile because the single packfile in the
+ # alternate object database does not invalidate the geometric sequence.
+ # And we should not have a multi-pack-index because these only index
+ # local packfiles, and there are none.
+ test_dir_is_empty member/$packdir
+'
+
+test_expect_success '--geometric with same pack in main and alternate ODB' '
+ test_when_finished "rm -fr shared member" &&
+
+ # Create a repository with a single packfile that acts as alternate
+ # object database.
+ git init shared &&
+ test_commit -C shared "shared-objects" &&
+ git -C shared repack -ad &&
+
+ # We create the member repository as an exact copy so that it has the
+ # same packfile.
+ cp -r shared member &&
+ test-tool path-utils real_path shared/.git/objects >member/.git/objects/info/alternates &&
+ find shared/.git/objects -type f >expected-files &&
+
+ # Verify that we can repack objects as expected without observing any
+ # error. Having the same packfile in both ODBs used to cause an error
+ # in git-pack-objects(1).
+ git -C member repack --geometric 2 2>err &&
+ test_must_be_empty err &&
+ # Nothing should have changed.
+ find shared/.git/objects -type f >actual-files &&
+ test_cmp expected-files actual-files
+'
+
+test_expect_success '--geometric -l with non-intact geometric sequence across ODBs' '
+ test_when_finished "rm -fr shared member" &&
+
+ git init shared &&
+ test_commit_bulk -C shared --start=1 1 &&
+
+ git clone --shared shared member &&
+ test_commit_bulk -C member --start=2 1 &&
+
+ # Verify that our assumptions actually hold: both generated packfiles
+ # should have three objects and should be non-equal.
+ packed_objects shared/.git/objects/pack/pack-*.idx >shared-objects &&
+ packed_objects member/.git/objects/pack/pack-*.idx >member-objects &&
+ test_line_count = 3 shared-objects &&
+ test_line_count = 3 member-objects &&
+ ! test_cmp shared-objects member-objects &&
+
+ # Perform the geometric repack. With `-l`, we should only see the local
+ # packfile and thus arrive at the conclusion that the geometric
+ # sequence is intact. We thus expect no changes.
+ #
+ # Note that we are tweaking mtimes of the packfiles so that we can
+ # verify they did not change. This is done in order to detect the case
+ # where we do repack objects, but the resulting packfile is the same.
+ test-tool chmtime --verbose =0 member/.git/objects/pack/* >expected-member-packs &&
+ git -C member repack --geometric=2 -l -d &&
+ test-tool chmtime --verbose member/.git/objects/pack/* >actual-member-packs &&
+ test_cmp expected-member-packs actual-member-packs &&
+
+ {
+ packed_objects shared/.git/objects/pack/pack-*.idx &&
+ packed_objects member/.git/objects/pack/pack-*.idx
+ } | sort >expected-objects &&
+
+ # On the other hand, when doing a non-local geometric repack we should
+ # see both packfiles and thus repack them. We expect that the shared
+ # object database was not changed.
+ test-tool chmtime --verbose =0 shared/.git/objects/pack/* >expected-shared-packs &&
+ git -C member repack --geometric=2 -d &&
+ test-tool chmtime --verbose shared/.git/objects/pack/* >actual-shared-packs &&
+ test_cmp expected-shared-packs actual-shared-packs &&
+
+ # Furthermore, we expect that the member repository now has a single
+ # packfile that contains the combined shared and non-shared objects.
+ ls member/.git/objects/pack/pack-*.idx >actual &&
+ test_line_count = 1 actual &&
+ packed_objects member/.git/objects/pack/pack-*.idx >actual-objects &&
+ test_line_count = 6 actual-objects &&
+ test_cmp expected-objects actual-objects
+'
+
+test_expect_success '--geometric -l disables writing bitmaps with non-local packfiles' '
+ test_when_finished "rm -fr shared member" &&
+
+ git init shared &&
+ test_commit_bulk -C shared --start=1 1 &&
+
+ git clone --shared shared member &&
+ test_commit_bulk -C member --start=2 1 &&
+
+ # When performing a geometric repack with `-l` while connected to an
+ # alternate object database that has a packfile we do not have full
+ # coverage of objects. As a result, we expect that writing the bitmap
+ # will be disabled.
+ git -C member repack -l --geometric=2 --write-midx --write-bitmap-index 2>err &&
+ cat >expect <<-EOF &&
+ warning: disabling bitmap writing, as some objects are not being packed
+ EOF
+ test_cmp expect err &&
+ test_path_is_missing member/.git/objects/pack/multi-pack-index-*.bitmap &&
+
+ # On the other hand, when we repack without `-l`, we should see that
+ # the bitmap gets created.
+ git -C member repack --geometric=2 --write-midx --write-bitmap-index 2>err &&
+ test_must_be_empty err &&
+ test_path_is_file member/.git/objects/pack/multi-pack-index-*.bitmap
+'
+
test_done
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 0de83b5d2b..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" '
@@ -2326,6 +2416,37 @@ test_expect_success $PREREQ 'invoke hook' '
)
'
+expected_file_counter_output () {
+ total=$1
+ count=0
+ while test $count -ne $total
+ do
+ count=$((count + 1)) &&
+ echo "$count/$total" || return
+ done
+}
+
+test_expect_success $PREREQ '--validate hook allows counting of messages' '
+ test_when_finished "rm -rf my-hooks.log" &&
+ test_config core.hooksPath "my-hooks" &&
+ mkdir -p my-hooks &&
+
+ write_script my-hooks/sendemail-validate <<-\EOF &&
+ num=$GIT_SENDEMAIL_FILE_COUNTER &&
+ tot=$GIT_SENDEMAIL_FILE_TOTAL &&
+ echo "$num/$tot" >>my-hooks.log || exit 1
+ EOF
+
+ >my-hooks.log &&
+ expected_file_counter_output 4 >expect &&
+ git send-email \
+ --from="Example <from@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ --validate -3 --cover-letter --force &&
+ test_cmp expect my-hooks.log
+'
+
test_expect_success $PREREQ 'test that send-email works outside a repo' '
nongit git send-email \
--from="Example <nobody@example.com>" \
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index aa55b41b9a..ac237a1f90 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -388,9 +388,7 @@ test_expect_success 'B: accept branch name "TEMP_TAG"' '
INPUT_END
- test_when_finished "rm -f .git/TEMP_TAG
- git gc
- git prune" &&
+ test_when_finished "rm -f .git/TEMP_TAG && git gc --prune=now" &&
git fast-import <input &&
test $(test-tool ref-store main resolve-ref TEMP_TAG 0 | cut -f1 -d " " ) != "$ZERO_OID" &&
test $(git rev-parse main) = $(git rev-parse TEMP_TAG^)
@@ -406,8 +404,7 @@ test_expect_success 'B: accept empty committer' '
INPUT_END
test_when_finished "git update-ref -d refs/heads/empty-committer-1
- git gc
- git prune" &&
+ git gc --prune=now" &&
git fast-import <input &&
out=$(git fsck) &&
echo "$out" &&
@@ -452,8 +449,7 @@ test_expect_success 'B: accept and fixup committer with no name' '
INPUT_END
test_when_finished "git update-ref -d refs/heads/empty-committer-2
- git gc
- git prune" &&
+ git gc --prune=now" &&
git fast-import <input &&
out=$(git fsck) &&
echo "$out" &&
@@ -1778,8 +1774,7 @@ test_expect_success 'P: verbatim SHA gitlinks' '
INPUT_END
git branch -D sub &&
- git gc &&
- git prune &&
+ git gc --prune=now &&
git fast-import <input &&
test $(git rev-parse --verify subuse2) = $(git rev-parse --verify subuse1)
'
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/tag.c b/tag.c
index 01ed67d6fa..96dbd5b2d5 100644
--- a/tag.c
+++ b/tag.c
@@ -1,6 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "environment.h"
#include "tag.h"
+#include "object-name.h"
#include "object-store.h"
#include "commit.h"
#include "tree.h"
diff --git a/templates/hooks--sendemail-validate.sample b/templates/hooks--sendemail-validate.sample
new file mode 100755
index 0000000000..640bcf874d
--- /dev/null
+++ b/templates/hooks--sendemail-validate.sample
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+# An example hook script to validate a patch (and/or patch series) before
+# sending it via email.
+#
+# The hook should exit with non-zero status after issuing an appropriate
+# message if it wants to prevent the email(s) from being sent.
+#
+# To enable this hook, rename this file to "sendemail-validate".
+#
+# By default, it will only check that the patch(es) can be applied on top of
+# the default upstream branch without conflicts in a secondary worktree. After
+# validation (successful or not) of the last patch of a series, the worktree
+# will be deleted.
+#
+# The following config variables can be set to change the default remote and
+# remote ref that are used to apply the patches against:
+#
+# sendemail.validateRemote (default: origin)
+# sendemail.validateRemoteRef (default: HEAD)
+#
+# Replace the TODO placeholders with appropriate checks according to your
+# needs.
+
+validate_cover_letter () {
+ file="$1"
+ # TODO: Replace with appropriate checks (e.g. spell checking).
+ true
+}
+
+validate_patch () {
+ file="$1"
+ # Ensure that the patch applies without conflicts.
+ git am -3 "$file" || return
+ # TODO: Replace with appropriate checks for this patch
+ # (e.g. checkpatch.pl).
+ true
+}
+
+validate_series () {
+ # TODO: Replace with appropriate checks for the whole series
+ # (e.g. quick build, coding style checks, etc.).
+ true
+}
+
+# main -------------------------------------------------------------------------
+
+if test "$GIT_SENDEMAIL_FILE_COUNTER" = 1
+then
+ remote=$(git config --default origin --get sendemail.validateRemote) &&
+ ref=$(git config --default HEAD --get sendemail.validateRemoteRef) &&
+ worktree=$(mktemp --tmpdir -d sendemail-validate.XXXXXXX) &&
+ git worktree add -fd --checkout "$worktree" "refs/remotes/$remote/$ref" &&
+ git config --replace-all sendemail.validateWorktree "$worktree"
+else
+ worktree=$(git config --get sendemail.validateWorktree)
+fi || {
+ echo "sendemail-validate: error: failed to prepare worktree" >&2
+ exit 1
+}
+
+unset GIT_DIR GIT_WORK_TREE
+cd "$worktree" &&
+
+if grep -q "^diff --git " "$1"
+then
+ validate_patch "$1"
+else
+ validate_cover_letter "$1"
+fi &&
+
+if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL"
+then
+ git config --unset-all sendemail.validateWorktree &&
+ trap 'git worktree remove -ff "$worktree"' EXIT &&
+ validate_series
+fi
diff --git a/tmp-objdir.c b/tmp-objdir.c
index 5adad1925d..c33a554f92 100644
--- a/tmp-objdir.c
+++ b/tmp-objdir.c
@@ -1,9 +1,10 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "tmp-objdir.h"
#include "abspath.h"
#include "chdir-notify.h"
#include "dir.h"
#include "environment.h"
+#include "object-file.h"
#include "sigchain.h"
#include "string-list.h"
#include "strbuf.h"
diff --git a/trace.c b/trace.c
index 81318a2455..592c141d78 100644
--- a/trace.c
+++ b/trace.c
@@ -21,11 +21,12 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "cache.h"
+#include "git-compat-util.h"
#include "abspath.h"
#include "environment.h"
#include "quote.h"
#include "setup.h"
+#include "trace.h"
#include "wrapper.h"
struct trace_key trace_default_key = { "GIT_TRACE", 0, 0, 0 };
diff --git a/trace2.c b/trace2.c
index e8ba62c0c3..0efc4e7b95 100644
--- a/trace2.c
+++ b/trace2.c
@@ -2,11 +2,13 @@
#include "config.h"
#include "json-writer.h"
#include "quote.h"
+#include "repository.h"
#include "run-command.h"
#include "sigchain.h"
#include "thread-utils.h"
#include "version.h"
#include "trace.h"
+#include "trace2.h"
#include "trace2/tr2_cfg.h"
#include "trace2/tr2_cmd_name.h"
#include "trace2/tr2_ctr.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/transport-helper.c b/transport-helper.c
index 76d146ee88..6b816940dc 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "transport.h"
#include "quote.h"
#include "run-command.h"
@@ -7,6 +7,7 @@
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "revision.h"
#include "remote.h"
#include "string-list.h"
diff --git a/transport.c b/transport.c
index 89a220425e..67afdae57c 100644
--- a/transport.c
+++ b/transport.c
@@ -1,4 +1,5 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "advice.h"
#include "alloc.h"
#include "config.h"
#include "environment.h"
@@ -22,8 +23,10 @@
#include "string-list.h"
#include "oid-array.h"
#include "sigchain.h"
+#include "trace2.h"
#include "transport-internal.h"
#include "protocol.h"
+#include "object-name.h"
#include "object-store.h"
#include "color.h"
#include "bundle-uri.h"
@@ -317,7 +320,7 @@ static struct ref *handshake(struct transport *transport, int for_push,
struct git_transport_data *data = transport->data;
struct ref *refs = NULL;
struct packet_reader reader;
- int sid_len;
+ size_t sid_len;
const char *server_sid;
connect_setup(transport, for_push);
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 38b6556478..d3c48e06df 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -1,10 +1,12 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "tree-walk.h"
#include "alloc.h"
#include "dir.h"
#include "gettext.h"
#include "hex.h"
+#include "object-file.h"
#include "object-store.h"
+#include "trace2.h"
#include "tree.h"
#include "pathspec.h"
#include "json-writer.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 2b78708766..0dd2029a8a 100644
--- a/tree.c
+++ b/tree.c
@@ -1,7 +1,8 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "cache-tree.h"
#include "hex.h"
#include "tree.h"
+#include "object-name.h"
#include "object-store.h"
#include "blob.h"
#include "commit.h"
@@ -93,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 3ded68ecb6..e8c32a40dc 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1,4 +1,5 @@
#include "cache.h"
+#include "advice.h"
#include "strvec.h"
#include "repository.h"
#include "config.h"
@@ -17,6 +18,8 @@
#include "sparse-index.h"
#include "submodule.h"
#include "submodule-config.h"
+#include "symlinks.h"
+#include "trace2.h"
#include "fsmonitor.h"
#include "object-store.h"
#include "promisor-remote.h"
diff --git a/unpack-trees.h b/unpack-trees.h
index 61c06eb7c5..30622aeebf 100644
--- a/unpack-trees.h
+++ b/unpack-trees.h
@@ -2,6 +2,7 @@
#define UNPACK_TREES_H
#include "cache.h"
+#include "convert.h"
#include "strvec.h"
#include "string-list.h"
#include "tree-walk.h"
diff --git a/upload-pack.c b/upload-pack.c
index e23f16dfdd..08633dc121 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "environment.h"
#include "gettext.h"
@@ -8,6 +8,7 @@
#include "sideband.h"
#include "repository.h"
#include "object-store.h"
+#include "oid-array.h"
#include "tag.h"
#include "object.h"
#include "commit.h"
@@ -22,6 +23,7 @@
#include "version.h"
#include "string-list.h"
#include "strvec.h"
+#include "trace2.h"
#include "prio-queue.h"
#include "protocol.h"
#include "quote.h"
@@ -30,6 +32,7 @@
#include "commit-graph.h"
#include "commit-reach.h"
#include "shallow.h"
+#include "wrapper.h"
#include "write-or-die.h"
/* Remember to update object flag allocation in object.h */
@@ -1067,7 +1070,7 @@ static void receive_needs(struct upload_pack_data *data,
const char *features;
struct object_id oid_buf;
const char *arg;
- int feature_len;
+ size_t feature_len;
reset_timeout(data->timeout);
if (packet_reader_read(reader) != PACKET_READ_NORMAL)
diff --git a/userdiff.c b/userdiff.c
index 09203fbc35..eaec6ebb5e 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -17,6 +17,7 @@ static int drivers_alloc;
.cflags = REG_EXTENDED, \
}, \
.word_regex = wrx "|[^[:space:]]|[\xc0-\xff][\x80-\xbf]+", \
+ .word_regex_multi_byte = wrx "|[^[:space:]]", \
}
#define IPATTERN(lang, rx, wrx) { \
.name = lang, \
@@ -26,6 +27,7 @@ static int drivers_alloc;
.cflags = REG_EXTENDED | REG_ICASE, \
}, \
.word_regex = wrx "|[^[:space:]]|[\xc0-\xff][\x80-\xbf]+", \
+ .word_regex_multi_byte = wrx "|[^[:space:]]", \
}
/*
@@ -294,7 +296,7 @@ PATTERNS("scheme",
/* All other words should be delimited by spaces or parentheses */
"|([^][)(}{[ \t])+"),
PATTERNS("tex", "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$",
- "\\\\[a-zA-Z@]+|\\\\.|[a-zA-Z0-9\x80-\xff]+"),
+ "\\\\[a-zA-Z@]+|\\\\.|([a-zA-Z0-9]|[^\x01-\x7f])+"),
{ "default", NULL, NULL, -1, { NULL, 0 } },
};
#undef PATTERNS
@@ -330,6 +332,25 @@ static int userdiff_find_by_namelen_cb(struct userdiff_driver *driver,
return 0;
}
+static int regexec_supports_multi_byte_chars(void)
+{
+ static const char not_space[] = "[^[:space:]]";
+ static const char utf8_multi_byte_char[] = "\xc2\xa3";
+ regex_t re;
+ regmatch_t match;
+ static int result = -1;
+
+ if (result != -1)
+ return result;
+ if (regcomp(&re, not_space, REG_EXTENDED))
+ BUG("invalid regular expression: %s", not_space);
+ result = !regexec(&re, utf8_multi_byte_char, 1, &match, 0) &&
+ match.rm_so == 0 &&
+ match.rm_eo == strlen(utf8_multi_byte_char);
+ regfree(&re);
+ return result;
+}
+
static struct userdiff_driver *userdiff_find_by_namelen(const char *name, size_t len)
{
struct find_by_namelen_data udcbdata = {
@@ -405,7 +426,13 @@ int userdiff_config(const char *k, const char *v)
struct userdiff_driver *userdiff_find_by_name(const char *name)
{
int len = strlen(name);
- return userdiff_find_by_namelen(name, len);
+ struct userdiff_driver *driver = userdiff_find_by_namelen(name, len);
+ if (driver && driver->word_regex_multi_byte) {
+ if (regexec_supports_multi_byte_chars())
+ driver->word_regex = driver->word_regex_multi_byte;
+ driver->word_regex_multi_byte = NULL;
+ }
+ return driver;
}
struct userdiff_driver *userdiff_find_by_path(struct index_state *istate,
diff --git a/userdiff.h b/userdiff.h
index 24419db697..d726804c3e 100644
--- a/userdiff.h
+++ b/userdiff.h
@@ -18,6 +18,7 @@ struct userdiff_driver {
int binary;
struct userdiff_funcname funcname;
const char *word_regex;
+ const char *word_regex_multi_byte;
const char *textconv;
struct notes_cache *textconv_cache;
int textconv_want_cache;
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/walker.c b/walker.c
index cfbd257fdb..24ff7dfdc2 100644
--- a/walker.c
+++ b/walker.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "gettext.h"
#include "hex.h"
#include "walker.h"
diff --git a/wrapper.c b/wrapper.c
index ee83757590..67f5f5dbe1 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -1,10 +1,14 @@
/*
* 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"
static intmax_t count_fsync_writeout_only;
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 4bef09de1c..068b76ef6d 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1,4 +1,5 @@
#include "cache.h"
+#include "advice.h"
#include "wt-status.h"
#include "object.h"
#include "dir.h"
@@ -7,6 +8,7 @@
#include "environment.h"
#include "gettext.h"
#include "hex.h"
+#include "object-name.h"
#include "revision.h"
#include "diffcore.h"
#include "quote.h"
@@ -18,6 +20,9 @@
#include "column.h"
#include "setup.h"
#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"
/*