From f80fcd36751c85b11722f8c7cfd537c28956400e Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Wed, 3 Mar 2021 15:16:52 +0900 Subject: [PATCH] Imported Upstream version 2.21.0 --- .gitignore | 3 +- .mailmap | 3 + .travis.yml | 2 + Documentation/Makefile | 22 +- Documentation/RelNotes/2.14.6.txt | 54 - Documentation/RelNotes/2.15.4.txt | 11 - Documentation/RelNotes/2.16.6.txt | 8 - Documentation/RelNotes/2.17.3.txt | 12 - Documentation/RelNotes/2.17.4.txt | 16 - Documentation/RelNotes/2.17.5.txt | 22 - Documentation/RelNotes/2.18.2.txt | 8 - Documentation/RelNotes/2.18.3.txt | 5 - Documentation/RelNotes/2.18.4.txt | 5 - Documentation/RelNotes/2.19.3.txt | 8 - Documentation/RelNotes/2.19.4.txt | 5 - Documentation/RelNotes/2.19.5.txt | 5 - Documentation/RelNotes/2.20.2.txt | 18 - Documentation/RelNotes/2.20.3.txt | 5 - Documentation/RelNotes/2.20.4.txt | 5 - Documentation/RelNotes/2.21.0.txt | 451 + Documentation/config/advice.txt | 7 + Documentation/config/core.txt | 7 +- Documentation/config/http.txt | 9 + Documentation/config/pack.txt | 9 + Documentation/config/rebase.txt | 5 + Documentation/config/worktree.txt | 4 +- Documentation/diff-options.txt | 20 +- Documentation/doc-diff | 5 +- Documentation/git-add.txt | 8 +- Documentation/git-branch.txt | 8 +- Documentation/git-cat-file.txt | 14 +- Documentation/git-checkout.txt | 22 +- Documentation/git-cherry-pick.txt | 14 +- Documentation/git-clone.txt | 6 + Documentation/git-column.txt | 2 +- Documentation/git-commit.txt | 18 +- Documentation/git-diff-tree.txt | 51 +- Documentation/git-diff.txt | 18 +- Documentation/git-fast-export.txt | 23 +- Documentation/git-fast-import.txt | 38 +- Documentation/git-fetch.txt | 2 +- Documentation/git-for-each-ref.txt | 21 +- Documentation/git-format-patch.txt | 14 +- Documentation/git-fsck.txt | 6 +- Documentation/git-gc.txt | 2 +- Documentation/git-help.txt | 4 +- Documentation/git-init.txt | 6 +- Documentation/git-instaweb.txt | 3 +- Documentation/git-log.txt | 4 + Documentation/git-p4.txt | 8 +- Documentation/git-pack-objects.txt | 11 +- Documentation/git-push.txt | 23 + Documentation/git-quiltimport.txt | 5 +- Documentation/git-rebase.txt | 32 +- Documentation/git-reset.txt | 70 +- Documentation/git-send-email.txt | 2 +- Documentation/git-show-ref.txt | 2 +- Documentation/git-status.txt | 162 +- Documentation/git-tag.txt | 16 +- Documentation/git-upload-pack.txt | 1 - Documentation/gitattributes.txt | 8 +- Documentation/gitdiffcore.txt | 3 +- Documentation/gitmodules.txt | 5 +- Documentation/gitweb.conf.txt | 6 +- Documentation/glossary-content.txt | 2 + Documentation/pretty-formats.txt | 4 +- Documentation/rev-list-options.txt | 26 +- Documentation/technical/api-oid-array.txt | 5 + Documentation/technical/commit-graph-format.txt | 4 +- Documentation/technical/pack-protocol.txt | 20 +- Documentation/technical/partial-clone.txt | 2 +- Documentation/technical/protocol-v2.txt | 18 +- GIT-VERSION-GEN | 2 +- Makefile | 71 +- README.md | 2 + RelNotes | 2 +- advice.c | 2 + advice.h | 1 + alias.c | 4 +- alloc.c | 11 +- alloc.h | 2 +- apply.c | 15 +- archive-tar.c | 2 +- archive.c | 18 +- attr.c | 21 +- azure-pipelines.yml | 387 + banned.h | 2 + bisect.c | 53 +- bisect.h | 5 +- blame.c | 43 +- branch.c | 21 +- branch.h | 8 +- builtin/add.c | 7 +- builtin/am.c | 46 +- builtin/archive.c | 19 +- builtin/bisect--helper.c | 565 +- builtin/blame.c | 7 +- builtin/branch.c | 6 +- builtin/bundle.c | 6 +- builtin/cat-file.c | 18 +- builtin/check-attr.c | 1 + builtin/check-ignore.c | 1 + builtin/checkout-index.c | 7 +- builtin/checkout.c | 83 +- builtin/clean.c | 1 + builtin/clone.c | 42 +- builtin/commit-graph.c | 4 +- builtin/commit-tree.c | 8 +- builtin/commit.c | 18 +- builtin/config.c | 5 +- builtin/count-objects.c | 4 +- builtin/describe.c | 4 +- builtin/diff-files.c | 1 + builtin/diff-index.c | 1 + builtin/diff-tree.c | 3 +- builtin/diff.c | 5 +- builtin/difftool.c | 3 +- builtin/fast-export.c | 190 +- builtin/fetch-pack.c | 12 +- builtin/fetch.c | 39 +- builtin/fsck.c | 202 +- builtin/gc.c | 6 +- builtin/grep.c | 66 +- builtin/hash-object.c | 3 +- builtin/index-pack.c | 2 +- builtin/init-db.c | 6 +- builtin/log.c | 17 +- builtin/ls-files.c | 15 +- builtin/ls-tree.c | 3 +- builtin/merge-index.c | 1 + builtin/merge-ours.c | 3 +- builtin/merge-recursive.c | 17 +- builtin/merge-tree.c | 26 +- builtin/merge.c | 9 +- builtin/mv.c | 1 + builtin/notes.c | 23 +- builtin/pack-objects.c | 73 +- builtin/pack-redundant.c | 4 +- builtin/prune.c | 1 - builtin/pull.c | 4 +- builtin/push.c | 7 +- builtin/read-tree.c | 5 +- builtin/rebase--interactive.c | 22 +- builtin/rebase.c | 536 +- builtin/receive-pack.c | 62 +- builtin/reflog.c | 38 +- builtin/repack.c | 28 +- builtin/replace.c | 2 +- builtin/rerere.c | 10 +- builtin/reset.c | 5 +- builtin/rev-list.c | 11 +- builtin/rev-parse.c | 4 +- builtin/revert.c | 11 +- builtin/rm.c | 1 + builtin/send-pack.c | 3 +- builtin/show-ref.c | 2 +- builtin/stripspace.c | 3 +- builtin/submodule--helper.c | 38 +- builtin/update-index.c | 1 + builtin/worktree.c | 29 +- builtin/write-tree.c | 1 + bulk-checkin.c | 2 +- bundle.c | 24 +- bundle.h | 9 +- cache-tree.c | 34 +- cache-tree.h | 6 +- cache.h | 126 +- ci/install-dependencies.sh | 12 +- ci/lib-travisci.sh | 129 - ci/lib.sh | 191 + ci/make-test-artifacts.sh | 12 + ci/mount-fileshare.sh | 25 + ci/print-test-failures.sh | 15 +- ci/run-build-and-tests.sh | 13 +- ci/run-linux32-build.sh | 4 +- ci/run-linux32-docker.sh | 2 +- ci/run-static-analysis.sh | 4 +- ci/run-test-slice.sh | 17 + ci/run-windows-build.sh | 2 +- ci/test-documentation.sh | 7 +- column.c | 4 +- combine-diff.c | 19 +- commit-graph.c | 305 +- commit-graph.h | 5 +- commit-reach.c | 73 +- commit-reach.h | 38 +- commit.c | 41 +- commit.h | 43 +- compat/cygwin.c | 19 - compat/cygwin.h | 2 - compat/fileno.c | 7 + compat/mingw.c | 210 +- compat/mingw.h | 34 - compat/obstack.c | 17 +- compat/obstack.h | 18 +- compat/precompose_utf8.c | 2 +- compat/regex/regcomp.c | 8 + compat/win32/path-utils.c | 28 + compat/win32/path-utils.h | 20 + config.c | 3 +- config.mak.dev | 1 + config.mak.uname | 46 +- connect.c | 5 +- contrib/coccinelle/object_id.cocci | 30 - contrib/coccinelle/strbuf.cocci | 30 + contrib/coccinelle/the_repository.pending.cocci | 144 + contrib/completion/git-completion.bash | 37 +- contrib/completion/git-completion.zsh | 4 +- contrib/hooks/multimail/CHANGES | 56 + contrib/hooks/multimail/CONTRIBUTING.rst | 28 +- contrib/hooks/multimail/README.Git | 4 +- contrib/hooks/multimail/{README => README.rst} | 38 +- contrib/hooks/multimail/doc/gitolite.rst | 9 + contrib/hooks/multimail/git_multimail.py | 188 +- contrib/hooks/multimail/migrate-mailhook-config | 13 +- contrib/hooks/multimail/post-receive.example | 2 +- convert.c | 38 +- credential-cache--daemon.c | 3 +- credential.c | 67 +- credential.h | 16 - date.c | 156 +- delta-islands.c | 24 +- delta-islands.h | 9 +- diff-lib.c | 7 +- diff.c | 273 +- diff.h | 8 +- diffcore-pickaxe.c | 10 +- dir.c | 42 +- entry.c | 10 +- environment.c | 10 +- fast-import.c | 205 +- fetch-pack.c | 150 +- fsck.c | 176 +- fuzz-commit-graph.c | 19 + git-bisect.sh | 314 +- git-compat-util.h | 30 +- git-instaweb.sh | 127 +- git-legacy-rebase.sh | 87 +- git-p4.py | 4 + git-quiltimport.sh | 6 +- git-rebase--am.sh | 2 +- git-rebase--common.sh | 3 +- git-rebase--merge.sh | 164 - git-stash.sh | 17 + git-submodule.sh | 15 +- git.c | 39 +- grep.c | 2 +- hash.h | 41 +- help.c | 3 +- hex.c | 30 +- http-backend.c | 2 + http-push.c | 8 +- http-walker.c | 10 +- http.c | 86 +- http.h | 7 +- imap-send.c | 5 +- line-log.c | 2 +- list-objects-filter-options.c | 29 +- list-objects-filter-options.h | 20 +- list-objects-filter.c | 132 +- list-objects-filter.h | 2 + list-objects.c | 88 +- list-objects.h | 4 +- ll-merge.c | 4 +- ll-merge.h | 1 + log-tree.c | 1 + ls-refs.c | 18 +- match-trees.c | 43 +- merge-recursive.c | 713 +- merge-recursive.h | 6 +- merge.c | 4 +- midx.c | 2 +- name-hash.c | 1 - notes-cache.c | 12 +- notes-cache.h | 6 +- notes-merge.c | 20 +- notes-merge.h | 5 +- notes-utils.c | 17 +- notes-utils.h | 11 +- notes.c | 4 +- object-store.h | 107 +- object.c | 45 +- pack-bitmap-write.c | 6 +- pack-bitmap.c | 13 +- pack-bitmap.h | 3 +- pack-check.c | 9 +- pack-objects.c | 10 +- pack-objects.h | 16 +- pack-revindex.c | 10 +- pack.h | 4 +- packfile.c | 24 +- packfile.h | 2 +- parse-options-cb.c | 7 +- parse-options.c | 66 +- parse-options.h | 11 +- path.c | 98 +- path.h | 2 +- pathspec.c | 39 +- pathspec.h | 27 +- pkt-line.c | 111 +- pkt-line.h | 42 +- po/TEAMS | 9 +- po/bg.po | 6799 +++--- po/ca.po | 199 +- po/de.po | 7203 +++--- po/el.po | 21468 ++++++++++++++++++ po/es.po | 6789 +++--- po/fr.po | 7376 ++++--- po/git.pot | 6725 +++--- po/it.po | 24299 +++++++++++++++++---- po/sv.po | 6811 +++--- po/zh_CN.po | 6720 +++--- preload-index.c | 11 +- pretty.c | 40 +- pretty.h | 8 +- quote.c | 2 +- read-cache.c | 258 +- rebase-interactive.c | 6 +- rebase-interactive.h | 5 +- ref-filter.c | 45 +- refs.c | 2 +- remote-curl.c | 129 +- remote.c | 124 +- repository.c | 51 +- repository.h | 28 +- rerere.c | 34 +- rerere.h | 6 +- revision.c | 191 +- revision.h | 6 +- send-pack.c | 41 +- sequencer.c | 526 +- sequencer.h | 34 +- serve.c | 5 +- setup.c | 80 +- sha1-array.c | 17 + sha1-array.h | 3 + sha1-file.c | 491 +- sha1-name.c | 150 +- sha256/block/sha256.c | 196 + sha256/block/sha256.h | 24 + sha256/gcrypt.h | 30 + shallow.c | 7 + sideband.c | 183 +- sideband.h | 25 +- streaming.c | 18 +- string-list.c | 3 +- submodule-config.c | 12 +- submodule.c | 426 +- submodule.h | 7 +- symlinks.c | 2 +- t/.gitignore | 1 + t/README | 42 +- t/check-non-portable-shell.pl | 3 +- t/helper/test-date.c | 27 +- t/helper/test-drop-caches.c | 11 +- t/helper/test-dump-fsmonitor.c | 4 +- t/helper/test-dump-untracked-cache.c | 1 + t/helper/test-genzeros.c | 21 + t/helper/test-hash-speed.c | 61 + t/helper/test-hash.c | 58 + t/helper/test-path-utils.c | 155 +- t/helper/test-ref-store.c | 2 +- t/helper/test-repository.c | 10 + t/helper/test-run-command.c | 138 +- t/helper/test-sha1.c | 52 +- t/helper/test-sha256.c | 7 + t/helper/test-sigchain.c | 3 +- t/helper/test-submodule-nested-repo-config.c | 8 +- t/helper/test-tool.c | 4 + t/helper/test-tool.h | 7 + t/helper/test-xml-encode.c | 80 + t/lib-credential.sh | 2 +- t/lib-git-daemon.sh | 16 +- t/lib-git-p4.sh | 9 +- t/lib-git-svn.sh | 2 +- t/lib-gpg.sh | 3 +- t/lib-httpd.sh | 4 +- t/lib-httpd/apache.conf | 6 + t/lib-httpd/error-smart-http.sh | 3 + t/lib-submodule-update.sh | 5 +- t/t0003-attributes.sh | 20 + t/t0006-date.sh | 22 +- t/t0015-hash.sh | 55 + t/t0021-conversion.sh | 2 +- t/t0025-crlf-renormalize.sh | 9 + t/t0027-auto-crlf.sh | 4 +- t/t0028-working-tree-encoding.sh | 54 +- t/t0030-stripspace.sh | 12 +- t/t0040-parse-options.sh | 4 +- t/t0060-path-utils.sh | 32 +- t/t0061-run-command.sh | 23 +- t/t0300-credentials.sh | 151 +- t/t0410-partial-clone.sh | 17 +- t/t1014-read-tree-confusing.sh | 1 - t/t1050-large.sh | 2 +- t/t1300-config.sh | 1 + t/t1404-update-ref-errors.sh | 2 +- t/t1410-reflog.sh | 6 +- t/t1450-fsck.sh | 63 +- t/t1512-rev-parse-disambiguation.sh | 10 + t/t2018-checkout-branch.sh | 9 + t/t2024-checkout-dwim.sh | 31 + t/t2028-worktree-move.sh | 37 + t/t3404-rebase-interactive.sh | 27 + t/t3406-rebase-message.sh | 7 +- t/t3418-rebase-continue.sh | 11 + t/t3420-rebase-autostash.sh | 78 +- t/t3421-rebase-topology-linear.sh | 10 +- t/t3425-rebase-topology-merges.sh | 15 +- t/t3430-rebase-merges.sh | 2 +- t/t3502-cherry-pick-merge.sh | 12 +- t/t3506-cherry-pick-ff.sh | 6 +- t/t3510-cherry-pick-sequence.sh | 8 +- t/t3700-add.sh | 7 + t/t3903-stash.sh | 28 + t/t4006-diff-mode.sh | 55 +- t/t4013-diff-various.sh | 9 + t/t4013/diff.diff-tree_--cc_--shortstat_master | 4 + t/t4013/diff.diff-tree_--cc_--summary_REVERSE | 6 + t/t4013/diff.diff_--dirstat_--cc_master~1_master | 3 + t/t4015-diff-whitespace.sh | 117 +- t/t4066-diff-emit-delay.sh | 79 + t/t4205-log-pretty-formats.sh | 50 + t/t4209-log-pickaxe.sh | 35 + t/t4211-line-log.sh | 2 +- t/t5004-archive-corner-cases.sh | 17 +- t/t5315-pack-objects-compression.sh | 2 +- t/t5318-commit-graph.sh | 30 +- t/t5322-pack-objects-sparse.sh | 136 + t/t5403-post-checkout-hook.sh | 96 +- t/t5407-post-rewrite-hook.sh | 34 + t/t5409-colorize-remote-messages.sh | 2 + t/t5500-fetch-pack.sh | 22 +- t/t5505-remote.sh | 55 + t/t5512-ls-remote.sh | 8 +- t/t5526-fetch-submodules.sh | 119 + t/t5537-fetch-shallow.sh | 3 +- t/t5550-http-fetch-dumb.sh | 16 +- t/t5551-http-fetch-smart.sh | 5 + t/t5562-http-backend-content-length.sh | 10 +- t/t5570-git-daemon.sh | 13 - t/t5580-clone-push-unc.sh | 5 + t/t5581-http-curl-verbose.sh | 28 + t/t5601-clone.sh | 2 +- t/t5611-clone-config.sh | 47 + t/t5616-partial-clone.sh | 2 +- t/t5701-git-serve.sh | 2 +- t/t5702-protocol-v2.sh | 72 +- t/t5703-upload-pack-ref-in-want.sh | 4 +- t/t6006-rev-list-format.sh | 4 + t/t6030-bisect-porcelain.sh | 2 +- t/t6036-recursive-corner-cases.sh | 430 +- t/t6042-merge-rename-corner-cases.sh | 333 +- t/t6043-merge-rename-directories.sh | 144 +- t/t6050-replace.sh | 4 +- t/t6112-rev-list-filters-objects.sh | 139 +- t/t6120-describe.sh | 39 + t/t6130-pathspec-noglob.sh | 1 - t/t6135-pathspec-with-attrs.sh | 58 +- t/t6300-for-each-ref.sh | 6 + t/t7400-submodule-basic.sh | 5 + t/t7406-submodule-update.sh | 28 +- t/t7412-submodule-absorbgitdirs.sh | 7 +- t/t7415-submodule-names.sh | 62 +- t/t7416-submodule-dash-url.sh | 157 +- t/t7417-submodule-path-url.sh | 17 - t/t7505-prepare-commit-msg-hook.sh | 10 +- t/t7510-signed-commit.sh | 21 +- t/t9300-fast-import.sh | 58 +- t/t9303-fast-import-compression.sh | 2 +- t/t9350-fast-export.sh | 83 +- t/t9807-git-p4-submit.sh | 57 +- t/t9833-errors.sh | 27 - t/t9902-completion.sh | 13 +- t/t9903-bash-prompt.sh | 2 +- t/test-lib-functions.sh | 46 + t/test-lib.sh | 519 +- transport-helper.c | 24 +- transport.c | 14 +- transport.h | 3 +- tree-diff.c | 9 +- tree-walk.c | 120 +- tree-walk.h | 36 +- tree.c | 30 +- tree.h | 18 +- unpack-trees.c | 24 +- upload-pack.c | 194 +- url.c | 3 +- userdiff.c | 8 +- userdiff.h | 4 +- utf8.c | 56 +- utf8.h | 2 +- walker.c | 4 +- wrapper.c | 13 + wt-status.c | 96 +- wt-status.h | 21 +- 496 files changed, 82544 insertions(+), 31365 deletions(-) delete mode 100644 Documentation/RelNotes/2.14.6.txt delete mode 100644 Documentation/RelNotes/2.15.4.txt delete mode 100644 Documentation/RelNotes/2.16.6.txt delete mode 100644 Documentation/RelNotes/2.17.3.txt delete mode 100644 Documentation/RelNotes/2.17.4.txt delete mode 100644 Documentation/RelNotes/2.17.5.txt delete mode 100644 Documentation/RelNotes/2.18.2.txt delete mode 100644 Documentation/RelNotes/2.18.3.txt delete mode 100644 Documentation/RelNotes/2.18.4.txt delete mode 100644 Documentation/RelNotes/2.19.3.txt delete mode 100644 Documentation/RelNotes/2.19.4.txt delete mode 100644 Documentation/RelNotes/2.19.5.txt delete mode 100644 Documentation/RelNotes/2.20.2.txt delete mode 100644 Documentation/RelNotes/2.20.3.txt delete mode 100644 Documentation/RelNotes/2.20.4.txt create mode 100644 Documentation/RelNotes/2.21.0.txt create mode 100644 azure-pipelines.yml delete mode 100755 ci/lib-travisci.sh create mode 100755 ci/lib.sh create mode 100755 ci/make-test-artifacts.sh create mode 100755 ci/mount-fileshare.sh create mode 100755 ci/run-test-slice.sh delete mode 100644 compat/cygwin.c delete mode 100644 compat/cygwin.h create mode 100644 compat/fileno.c create mode 100644 compat/win32/path-utils.c create mode 100644 compat/win32/path-utils.h create mode 100644 contrib/coccinelle/the_repository.pending.cocci rename contrib/hooks/multimail/{README => README.rst} (95%) create mode 100644 fuzz-commit-graph.c delete mode 100644 git-rebase--merge.sh create mode 100644 po/el.po create mode 100644 sha256/block/sha256.c create mode 100644 sha256/block/sha256.h create mode 100644 sha256/gcrypt.h create mode 100644 t/helper/test-genzeros.c create mode 100644 t/helper/test-hash-speed.c create mode 100644 t/helper/test-hash.c create mode 100644 t/helper/test-sha256.c create mode 100644 t/helper/test-xml-encode.c create mode 100644 t/lib-httpd/error-smart-http.sh create mode 100755 t/t0015-hash.sh create mode 100644 t/t4013/diff.diff-tree_--cc_--shortstat_master create mode 100644 t/t4013/diff.diff-tree_--cc_--summary_REVERSE create mode 100644 t/t4013/diff.diff_--dirstat_--cc_master~1_master create mode 100755 t/t4066-diff-emit-delay.sh create mode 100755 t/t5322-pack-objects-sparse.sh create mode 100755 t/t5581-http-curl-verbose.sh diff --git a/.gitignore b/.gitignore index 0d77ea5..7374587 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/fuzz-commit-graph /fuzz_corpora /fuzz-pack-headers /fuzz-pack-idx @@ -124,7 +125,6 @@ /git-rebase--am /git-rebase--common /git-rebase--interactive -/git-rebase--merge /git-rebase--preserve-merges /git-receive-pack /git-reflog @@ -229,3 +229,4 @@ *.pdb /Debug/ /Release/ +*.dSYM diff --git a/.mailmap b/.mailmap index eb7b5fc..82cd056 100644 --- a/.mailmap +++ b/.mailmap @@ -27,6 +27,7 @@ Ben Walton Benoit Sigoure Bernt Hansen Brandon Casey +Brandon Williams brian m. carlson brian m. carlson Bryan Larsen @@ -39,6 +40,8 @@ Cord Seele Christian Couder Christian Stimming Christopher Díaz Riveros Christopher Diaz Riveros +Clemens Buchacher +Clemens Buchacher Csaba Henk Dan Johnson Dana L. How diff --git a/.travis.yml b/.travis.yml index 03c8e4c..36cbdea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,8 @@ os: - linux - osx +osx_image: xcode10.1 + compiler: - clang - gcc diff --git a/Documentation/Makefile b/Documentation/Makefile index d5d936e..26a2342 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -36,14 +36,19 @@ MAN7_TXT += gittutorial-2.txt MAN7_TXT += gittutorial.txt MAN7_TXT += gitworkflows.txt +ifdef MAN_FILTER +MAN_TXT = $(filter $(MAN_FILTER),$(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)) +else MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT) +MAN_FILTER = $(MAN_TXT) +endif + MAN_XML = $(patsubst %.txt,%.xml,$(MAN_TXT)) MAN_HTML = $(patsubst %.txt,%.html,$(MAN_TXT)) GIT_MAN_REF = master OBSOLETE_HTML += everyday.html OBSOLETE_HTML += git-remote-helpers.html -DOC_HTML = $(MAN_HTML) $(OBSOLETE_HTML) ARTICLES += howto-index ARTICLES += git-tools @@ -89,11 +94,13 @@ TECH_DOCS += technical/trivial-merge SP_ARTICLES += $(TECH_DOCS) SP_ARTICLES += technical/api-index -DOC_HTML += $(patsubst %,%.html,$(ARTICLES) $(SP_ARTICLES)) +ARTICLES_HTML += $(patsubst %,%.html,$(ARTICLES) $(SP_ARTICLES)) +HTML_FILTER ?= $(ARTICLES_HTML) $(OBSOLETE_HTML) +DOC_HTML = $(MAN_HTML) $(filter $(HTML_FILTER),$(ARTICLES_HTML) $(OBSOLETE_HTML)) -DOC_MAN1 = $(patsubst %.txt,%.1,$(MAN1_TXT)) -DOC_MAN5 = $(patsubst %.txt,%.5,$(MAN5_TXT)) -DOC_MAN7 = $(patsubst %.txt,%.7,$(MAN7_TXT)) +DOC_MAN1 = $(patsubst %.txt,%.1,$(filter $(MAN_FILTER),$(MAN1_TXT))) +DOC_MAN5 = $(patsubst %.txt,%.5,$(filter $(MAN_FILTER),$(MAN5_TXT))) +DOC_MAN7 = $(patsubst %.txt,%.7,$(filter $(MAN_FILTER),$(MAN7_TXT))) prefix ?= $(HOME) bindir ?= $(prefix)/bin @@ -457,4 +464,9 @@ print-man1: lint-docs:: $(QUIET_LINT)$(PERL_PATH) lint-gitlink.perl +ifeq ($(wildcard po/Makefile),po/Makefile) +doc-l10n install-l10n:: + $(MAKE) -C po $@ +endif + .PHONY: FORCE diff --git a/Documentation/RelNotes/2.14.6.txt b/Documentation/RelNotes/2.14.6.txt deleted file mode 100644 index 72b7af6..0000000 --- a/Documentation/RelNotes/2.14.6.txt +++ /dev/null @@ -1,54 +0,0 @@ -Git v2.14.6 Release Notes -========================= - -This release addresses the security issues CVE-2019-1348, -CVE-2019-1349, CVE-2019-1350, CVE-2019-1351, CVE-2019-1352, -CVE-2019-1353, CVE-2019-1354, and CVE-2019-1387. - -Fixes since v2.14.5 -------------------- - - * CVE-2019-1348: - The --export-marks option of git fast-import is exposed also via - the in-stream command feature export-marks=... and it allows - overwriting arbitrary paths. - - * CVE-2019-1349: - When submodules are cloned recursively, under certain circumstances - Git could be fooled into using the same Git directory twice. We now - require the directory to be empty. - - * CVE-2019-1350: - Incorrect quoting of command-line arguments allowed remote code - execution during a recursive clone in conjunction with SSH URLs. - - * CVE-2019-1351: - While the only permitted drive letters for physical drives on - Windows are letters of the US-English alphabet, this restriction - does not apply to virtual drives assigned via subst : - . Git mistook such paths for relative paths, allowing writing - outside of the worktree while cloning. - - * CVE-2019-1352: - Git was unaware of NTFS Alternate Data Streams, allowing files - inside the .git/ directory to be overwritten during a clone. - - * CVE-2019-1353: - When running Git in the Windows Subsystem for Linux (also known as - "WSL") while accessing a working directory on a regular Windows - drive, none of the NTFS protections were active. - - * CVE-2019-1354: - Filenames on Linux/Unix can contain backslashes. On Windows, - backslashes are directory separators. Git did not use to refuse to - write out tracked files with such filenames. - - * CVE-2019-1387: - Recursive clones are currently affected by a vulnerability that is - caused by too-lax validation of submodule names, allowing very - targeted attacks via remote code execution in recursive clones. - -Credit for finding these vulnerabilities goes to Microsoft Security -Response Center, in particular to Nicolas Joly. The `fast-import` -fixes were provided by Jeff King, the other fixes by Johannes -Schindelin with help from Garima Singh. diff --git a/Documentation/RelNotes/2.15.4.txt b/Documentation/RelNotes/2.15.4.txt deleted file mode 100644 index dc241cb..0000000 --- a/Documentation/RelNotes/2.15.4.txt +++ /dev/null @@ -1,11 +0,0 @@ -Git v2.15.4 Release Notes -========================= - -This release merges up the fixes that appear in v2.14.6 to address -the security issues CVE-2019-1348, CVE-2019-1349, CVE-2019-1350, -CVE-2019-1351, CVE-2019-1352, CVE-2019-1353, CVE-2019-1354, and -CVE-2019-1387; see the release notes for that version for details. - -In conjunction with a vulnerability that was fixed in v2.20.2, -`.gitmodules` is no longer allowed to contain entries of the form -`submodule..update=!command`. diff --git a/Documentation/RelNotes/2.16.6.txt b/Documentation/RelNotes/2.16.6.txt deleted file mode 100644 index 438306e..0000000 --- a/Documentation/RelNotes/2.16.6.txt +++ /dev/null @@ -1,8 +0,0 @@ -Git v2.16.6 Release Notes -========================= - -This release merges up the fixes that appear in v2.14.6 and in -v2.15.4 addressing the security issues CVE-2019-1348, CVE-2019-1349, -CVE-2019-1350, CVE-2019-1351, CVE-2019-1352, CVE-2019-1353, -CVE-2019-1354, and CVE-2019-1387; see the release notes for those -versions for details. diff --git a/Documentation/RelNotes/2.17.3.txt b/Documentation/RelNotes/2.17.3.txt deleted file mode 100644 index 5a46c94..0000000 --- a/Documentation/RelNotes/2.17.3.txt +++ /dev/null @@ -1,12 +0,0 @@ -Git v2.17.3 Release Notes -========================= - -This release merges up the fixes that appear in v2.14.6 and in -v2.15.4 addressing the security issues CVE-2019-1348, CVE-2019-1349, -CVE-2019-1350, CVE-2019-1351, CVE-2019-1352, CVE-2019-1353, -CVE-2019-1354, and CVE-2019-1387; see the release notes for those -versions for details. - -In addition, `git fsck` was taught to identify `.gitmodules` entries -of the form `submodule..update=!command`, which have been -disallowed in v2.15.4. diff --git a/Documentation/RelNotes/2.17.4.txt b/Documentation/RelNotes/2.17.4.txt deleted file mode 100644 index 7d794ca..0000000 --- a/Documentation/RelNotes/2.17.4.txt +++ /dev/null @@ -1,16 +0,0 @@ -Git v2.17.4 Release Notes -========================= - -This release is to address the security issue: CVE-2020-5260 - -Fixes since v2.17.3 -------------------- - - * With a crafted URL that contains a newline in it, the credential - helper machinery can be fooled to give credential information for - a wrong host. The attack has been made impossible by forbidding - a newline character in any value passed via the credential - protocol. - -Credit for finding the vulnerability goes to Felix Wilhelm of Google -Project Zero. diff --git a/Documentation/RelNotes/2.17.5.txt b/Documentation/RelNotes/2.17.5.txt deleted file mode 100644 index 2abb821..0000000 --- a/Documentation/RelNotes/2.17.5.txt +++ /dev/null @@ -1,22 +0,0 @@ -Git v2.17.5 Release Notes -========================= - -This release is to address a security issue: CVE-2020-11008 - -Fixes since v2.17.4 -------------------- - - * With a crafted URL that contains a newline or empty host, or lacks - a scheme, the credential helper machinery can be fooled into - providing credential information that is not appropriate for the - protocol in use and host being contacted. - - Unlike the vulnerability CVE-2020-5260 fixed in v2.17.4, the - credentials are not for a host of the attacker's choosing; instead, - they are for some unspecified host (based on how the configured - credential helper handles an absent "host" parameter). - - The attack has been made impossible by refusing to work with - under-specified credential patterns. - -Credit for finding the vulnerability goes to Carlo Arenas. diff --git a/Documentation/RelNotes/2.18.2.txt b/Documentation/RelNotes/2.18.2.txt deleted file mode 100644 index 98b168a..0000000 --- a/Documentation/RelNotes/2.18.2.txt +++ /dev/null @@ -1,8 +0,0 @@ -Git v2.18.2 Release Notes -========================= - -This release merges up the fixes that appear in v2.14.6, v2.15.4 -and in v2.17.3, addressing the security issues CVE-2019-1348, -CVE-2019-1349, CVE-2019-1350, CVE-2019-1351, CVE-2019-1352, -CVE-2019-1353, CVE-2019-1354, and CVE-2019-1387; see the release notes -for those versions for details. diff --git a/Documentation/RelNotes/2.18.3.txt b/Documentation/RelNotes/2.18.3.txt deleted file mode 100644 index 25143f0..0000000 --- a/Documentation/RelNotes/2.18.3.txt +++ /dev/null @@ -1,5 +0,0 @@ -Git v2.18.3 Release Notes -========================= - -This release merges the security fix that appears in v2.17.4; see -the release notes for that version for details. diff --git a/Documentation/RelNotes/2.18.4.txt b/Documentation/RelNotes/2.18.4.txt deleted file mode 100644 index e8ef858..0000000 --- a/Documentation/RelNotes/2.18.4.txt +++ /dev/null @@ -1,5 +0,0 @@ -Git v2.18.4 Release Notes -========================= - -This release merges the security fix that appears in v2.17.5; see -the release notes for that version for details. diff --git a/Documentation/RelNotes/2.19.3.txt b/Documentation/RelNotes/2.19.3.txt deleted file mode 100644 index 92d7f89..0000000 --- a/Documentation/RelNotes/2.19.3.txt +++ /dev/null @@ -1,8 +0,0 @@ -Git v2.19.3 Release Notes -========================= - -This release merges up the fixes that appear in v2.14.6, v2.15.4 -and in v2.17.3, addressing the security issues CVE-2019-1348, -CVE-2019-1349, CVE-2019-1350, CVE-2019-1351, CVE-2019-1352, -CVE-2019-1353, CVE-2019-1354, and CVE-2019-1387; see the release notes -for those versions for details. diff --git a/Documentation/RelNotes/2.19.4.txt b/Documentation/RelNotes/2.19.4.txt deleted file mode 100644 index 35d0ae5..0000000 --- a/Documentation/RelNotes/2.19.4.txt +++ /dev/null @@ -1,5 +0,0 @@ -Git v2.19.4 Release Notes -========================= - -This release merges the security fix that appears in v2.17.4; see -the release notes for that version for details. diff --git a/Documentation/RelNotes/2.19.5.txt b/Documentation/RelNotes/2.19.5.txt deleted file mode 100644 index 18a4dcb..0000000 --- a/Documentation/RelNotes/2.19.5.txt +++ /dev/null @@ -1,5 +0,0 @@ -Git v2.19.5 Release Notes -========================= - -This release merges the security fix that appears in v2.17.5; see -the release notes for that version for details. diff --git a/Documentation/RelNotes/2.20.2.txt b/Documentation/RelNotes/2.20.2.txt deleted file mode 100644 index 8e680cb..0000000 --- a/Documentation/RelNotes/2.20.2.txt +++ /dev/null @@ -1,18 +0,0 @@ -Git v2.20.2 Release Notes -========================= - -This release merges up the fixes that appear in v2.14.6, v2.15.4 -and in v2.17.3, addressing the security issues CVE-2019-1348, -CVE-2019-1349, CVE-2019-1350, CVE-2019-1351, CVE-2019-1352, -CVE-2019-1353, CVE-2019-1354, and CVE-2019-1387; see the release notes -for those versions for details. - -The change to disallow `submodule..update=!command` entries in -`.gitmodules` which was introduced v2.15.4 (and for which v2.17.3 -added explicit fsck checks) fixes the vulnerability in v2.20.x where a -recursive clone followed by a submodule update could execute code -contained within the repository without the user explicitly having -asked for that (CVE-2019-19604). - -Credit for finding this vulnerability goes to Joern Schneeweisz, -credit for the fixes goes to Jonathan Nieder. diff --git a/Documentation/RelNotes/2.20.3.txt b/Documentation/RelNotes/2.20.3.txt deleted file mode 100644 index f6eccd1..0000000 --- a/Documentation/RelNotes/2.20.3.txt +++ /dev/null @@ -1,5 +0,0 @@ -Git v2.20.3 Release Notes -========================= - -This release merges the security fix that appears in v2.17.4; see -the release notes for that version for details. diff --git a/Documentation/RelNotes/2.20.4.txt b/Documentation/RelNotes/2.20.4.txt deleted file mode 100644 index 5a9e24e..0000000 --- a/Documentation/RelNotes/2.20.4.txt +++ /dev/null @@ -1,5 +0,0 @@ -Git v2.20.4 Release Notes -========================= - -This release merges the security fix that appears in v2.17.5; see -the release notes for that version for details. diff --git a/Documentation/RelNotes/2.21.0.txt b/Documentation/RelNotes/2.21.0.txt new file mode 100644 index 0000000..7a49ded --- /dev/null +++ b/Documentation/RelNotes/2.21.0.txt @@ -0,0 +1,451 @@ +Git 2.21 Release Notes +====================== + +Backward Compatibility Notes +---------------------------- + + * Historically, the "-m" (mainline) option can only be used for "git + cherry-pick" and "git revert" when working with a merge commit. + This version of Git no longer warns or errors out when working with + a single-parent commit, as long as the argument to the "-m" option + is 1 (i.e. it has only one parent, and the request is to pick or + revert relative to that first parent). Scripts that relied on the + behaviour may get broken with this change. + + +Updates since v2.20 +------------------- + +UI, Workflows & Features + + * The "http.version" configuration variable can be used with recent + enough versions of cURL library to force the version of HTTP used + to talk when fetching and pushing. + + * Small fixes and features for fast-export and fast-import, mostly on + the fast-export side has been made. + + * "git push $there $src:$dst" rejects when $dst is not a fully + qualified refname and it is not clear what the end user meant. The + codepath has been taught to give a clearer error message, and also + guess where the push should go by taking the type of the pushed + object into account (e.g. a tag object would want to go under + refs/tags/). + + * "git checkout [] path..." learned to report the number of + paths that have been checked out of the index or the tree-ish, + which gives it the same degree of noisy-ness as the case in which + the command checks out a branch. "git checkout -m " to + undo conflict resolution gives a similar message. + + * "git quiltimport" learned "--keep-non-patch" option. + + * "git worktree remove" and "git worktree move" refused to work when + there is a submodule involved. This has been loosened to ignore + uninitialized submodules. + + * "git cherry-pick -m1" was forbidden when picking a non-merge + commit, even though there _is_ parent number 1 for such a commit. + This was done to avoid mistakes back when "cherry-pick" was about + picking a single commit, but is no longer useful with "cherry-pick" + that can pick a range of commits. Now the "-m$num" option is + allowed when picking any commit, as long as $num names an existing + parent of the commit. + + * Update "git multimail" from the upstream. + + * "git p4" update. + + * The "--format=" option of for-each-ref, branch and tag + learned to show a few more traits of objects that can be learned by + the object_info API. + + * "git rebase -i" learned to re-execute a command given with 'exec' + to run after it failed the last time. + + * "git diff --color-moved-ws" updates. + + * Custom userformat "log --format" learned %S atom that stands for + the tip the traversal reached the commit from, i.e. --source. + + * "git instaweb" learned to drive http.server that comes with + "batteries included" Python installation (both Python2 & 3). + + * A new encoding UTF-16LE-BOM has been invented to force encoding to + UTF-16 with BOM in little endian byte order, which cannot be directly + generated by using iconv. + + * A new date format "--date=human" that morphs its output depending + on how far the time is from the current time has been introduced. + "--date=auto:human" can be used to use this new format (or any + existing format) when the output is going to the pager or to the + terminal, and otherwise the default format. + + +Performance, Internal Implementation, Development Support etc. + + * Code clean-up with optimization for the codepath that checks + (non-)existence of loose objects. + + * More codepaths have become aware of working with in-core repository + instances other than the default "the_repository". + + * The "strncat()" function is now among the banned functions. + + * Portability updates for the HPE NonStop platform. + + * Earlier we added "-Wformat-security" to developer builds, assuming + that "-Wall" (which includes "-Wformat" which in turn is required + to use "-Wformat-security") is always in effect. This is not true + when config.mak.autogen is in use, unfortunately. This has been + fixed by unconditionally adding "-Wall" to developer builds. + + * The loose object cache used to optimize existence look-up has been + updated. + + * Flaky tests can now be repeatedly run under load with the + "--stress" option. + + * Documentation/Makefile is getting prepared for manpage + localization. + + * "git fetch-pack" now can talk the version 2 protocol. + + * sha-256 hash has been added and plumbed through the code to allow + building Git with the "NewHash". + + * Debugging help for http transport. + + * "git fetch --deepen=" has been corrected to work over v2 + protocol. + + * The code to walk tree objects has been taught that we may be + working with object names that are not computed with SHA-1. + + * The in-core repository instances are passed through more codepaths. + + * Update the protocol message specification to allow only the limited + use of scaled quantities. This is to ensure potential compatibility + issues will not get out of hand. + + * Micro-optimize the code that prepares commit objects to be walked + by "git rev-list" when the commit-graph is available. + + * "git fetch" and "git upload-pack" learned to send all exchanges over + the sideband channel while talking the v2 protocol. + + * The codepath to write out commit-graph has been optimized by + following the usual pattern of visiting objects in in-pack order. + + * The codepath to show progress meter while writing out commit-graph + file has been improved. + + * Cocci rules have been updated to encourage use of strbuf_addbuf(). + + * "git rebase --merge" has been reimplemented by reusing the internal + machinery used for "git rebase -i". + + * More code in "git bisect" has been rewritten in C. + + * Instead of going through "git-rebase--am" scriptlet to use the "am" + backend, the built-in version of "git rebase" learned to drive the + "am" backend directly. + + * The assumption to work on the single "in-core index" instance has + been reduced from the library-ish part of the codebase. + + * The test lint learned to catch non-portable "sed" options. + + * "git pack-objects" learned another algorithm to compute the set of + objects to send, that trades the resulting packfile off to save + traversal cost to favor small pushes. + + * The travis CI scripts have been corrected to build Git with the + compiler(s) of our choice. + + * "git submodule update" learned to abort early when core.worktree + for the submodule is not set correctly to prevent spreading damage. + + * Test suite has been adjusted to run on Azure Pipeline. + + * Running "Documentation/doc-diff x" from anywhere other than the + top-level of the working tree did not show the usage string + correctly, which has been fixed. + + * Use of the sparse tool got easier to customize from the command + line to help developers. + + * A new target "coverage-prove" to run the coverage test under + "prove" has been added. + + * A flakey "p4" test has been removed. + + * The code and tests assume that the system supplied iconv() would + always use BOM in its output when asked to encode to UTF-16 (or + UTF-32), but apparently some implementations output big-endian + without BOM. A compile-time knob has been added to help such + systems (e.g. NonStop) to add BOM to the output to increase + portability. + + +Fixes since v2.20 +----------------- + + * Updates for corner cases in merge-recursive. + (merge cc4cb0902c en/merge-path-collision later to maint). + + * "git checkout frotz" (without any double-dash) avoids ambiguity by + making sure 'frotz' cannot be interpreted as a revision and as a + path at the same time. This safety has been updated to check also + a unique remote-tracking branch 'frotz' in a remote, when dwimming + to create a local branch 'frotz' out of a remote-tracking branch + 'frotz' from a remote. + (merge be4908f103 nd/checkout-dwim-fix later to maint). + + * Refspecs configured with "git -c var=val clone" did not propagate + to the resulting repository, which has been corrected. + (merge 7eae4a3ac4 sg/clone-initial-fetch-configuration later to maint). + + * A properly configured username/email is required under + user.useConfigOnly in order to create commits; now "git stash" + (even though it creates commit objects to represent stash entries) + command is exempt from the requirement. + (merge 3bc2111fc2 sd/stash-wo-user-name later to maint). + + * The http-backend CGI process did not correctly clean up the child + processes it spawns to run upload-pack etc. when it dies itself, + which has been corrected. + (merge 02818a98d7 mk/http-backend-kill-children-before-exit later to maint). + + * "git rev-list --exclude-promisor-objects" had to take an object + that does not exist locally (and is lazily available) from the + command line without barfing, but the code dereferenced NULL. + (merge 4cf67869b2 md/list-lazy-objects-fix later to maint). + + * The traversal over tree objects has learned to honor + ":(attr:label)" pathspec match, which has been implemented only for + enumerating paths on the filesystem. + (merge 5a0b97b34c nd/attr-pathspec-in-tree-walk later to maint). + + * BSD port updates. + (merge 4e3ecbd439 cb/openbsd-allows-reading-directory later to maint). + (merge b6bdc2a0f5 cb/t5004-empty-tar-archive-fix later to maint). + (merge 82cbc8cde2 cb/test-lint-cp-a later to maint). + + * Lines that begin with a certain keyword that come over the wire, as + well as lines that consist only of one of these keywords, ought to + be painted in color for easier eyeballing, but the latter was + broken ever since the feature was introduced in 2.19, which has + been corrected. + (merge 1f67290450 hn/highlight-sideband-keywords later to maint). + + * "git log -G" looked for a hunk in the "git log -p" patch + output that contained a string that matches the given pattern. + Optimize this code to ignore binary files, which by default will + not show any hunk that would match any pattern (unless textconv or + the --text option is in effect, that is). + (merge e0e7cb8080 tb/log-G-binary later to maint). + + * "git submodule update" ought to use a single job unless asked, but + by mistake used multiple jobs, which has been fixed. + (merge e3a9d1aca9 sb/submodule-fetchjobs-default-to-one later to maint). + + * "git stripspace" should be usable outside a git repository, but + under the "-s" or "-c" mode, it didn't. + (merge 957da75802 jn/stripspace-wo-repository later to maint). + + * Some of the documentation pages formatted incorrectly with + Asciidoctor, which have been fixed. + (merge b62eb1d2f4 ma/asciidoctor later to maint). + + * The core.worktree setting in a submodule repository should not be + pointing at a directory when the submodule loses its working tree + (e.g. getting deinit'ed), but the code did not properly maintain + this invariant. + + * With zsh, "git cmd path" was completed to "git cmd path name" + when the completed path has a special character like SP in it, + without any attempt to keep "path name" a single filename. This + has been fixed to complete it to "git cmd path\ name" just like + Bash completion does. + + * The test suite tried to see if it is run under bash, but the check + itself failed under some other implementations of shell (notably + under NetBSD). This has been corrected. + (merge 54ea72f09c sg/test-bash-version-fix later to maint). + + * "git gc" and "git repack" did not close the open packfiles that + they found unneeded before removing them, which didn't work on a + platform incapable of removing an open file. This has been + corrected. + (merge 5bdece0d70 js/gc-repack-close-before-remove later to maint). + + * The code to drive GIT_EXTERNAL_DIFF command relied on the string + returned from getenv() to be non-volatile, which is not true, that + has been corrected. + (merge 6776a84dae kg/external-diff-save-env later to maint). + + * There were many places the code relied on the string returned from + getenv() to be non-volatile, which is not true, that have been + corrected. + (merge 0da0e9268b jk/save-getenv-result later to maint). + + * The v2 upload-pack protocol implementation failed to honor + hidden-ref configuration, which has been corrected. + (merge e20b4192a3 jk/proto-v2-hidden-refs-fix later to maint). + + * "git fetch --recurse-submodules" may not fetch the necessary commit + that is bound to the superproject, which is getting corrected. + (merge be76c21282 sb/submodule-recursive-fetch-gets-the-tip later to maint). + + * "git rebase" internally runs "checkout" to switch between branches, + and the command used to call the post-checkout hook, but the + reimplementation stopped doing so, which is getting fixed. + + * "git add -e" got confused when the change it wants to let the user + edit is smaller than the previous change that was left over in a + temporary file. + (merge fa6f225e01 js/add-e-clear-patch-before-stating later to maint). + + * "git p4" failed to update a shelved change when there were moved + files, which has been corrected. + (merge 7a10946ab9 ld/git-p4-shelve-update-fix later to maint). + + * The codepath to read from the commit-graph file attempted to read + past the end of it when the file's table-of-contents was corrupt. + + * The compat/obstack code had casts that -Wcast-function-type + compilation option found questionable. + (merge 764473d257 sg/obstack-cast-function-type-fix later to maint). + + * An obvious typo in an assertion error message has been fixed. + (merge 3c27e2e059 cc/test-ref-store-typofix later to maint). + + * In Git for Windows, "git clone \\server\share\path" etc. that uses + UNC paths from command line had bad interaction with its shell + emulation. + + * "git add --ignore-errors" did not work as advertised and instead + worked as an unintended synonym for "git add --renormalize", which + has been fixed. + (merge e2c2a37545 jk/add-ignore-errors-bit-assignment-fix later to maint). + + * On a case-insensitive filesystem, we failed to compare the part of + the path that is above the worktree directory in an absolute + pathname, which has been corrected. + + * Asking "git check-attr" about a macro (e.g. "binary") on a specific + path did not work correctly, even though "git check-attr -a" listed + such a macro correctly. This has been corrected. + (merge 7b95849be4 jk/attr-macro-fix later to maint). + + * "git pack-objects" incorrectly used uninitialized mutex, which has + been corrected. + (merge edb673cf10 ph/pack-objects-mutex-fix later to maint). + + * "git checkout -b [HEAD]" to create a new branch from the + current commit and check it out ought to be a no-op in the index + and the working tree in normal cases, but there are corner cases + that do require updates to the index and the working tree. Running + it immediately after "git clone --no-checkout" is one of these + cases that an earlier optimization kicked in incorrectly, which has + been fixed. + (merge 8424bfd45b bp/checkout-new-branch-optim later to maint). + + * "git diff --color-moved --cc --stat -p" did not work well due to + funny interaction between a bug in color-moved and the rest, which + has been fixed. + (merge dac03b5518 jk/diff-cc-stat-fixes later to maint). + + * When GIT_SEQUENCE_EDITOR is set, the command was incorrectly + started when modes of "git rebase" that implicitly uses the + machinery for the interactive rebase are run, which has been + corrected. + (merge 891d4a0313 pw/no-editor-in-rebase-i-implicit later to maint). + + * The commit-graph facility did not work when in-core objects that + are promoted from unknown type to commit (e.g. a commit that is + accessed via a tag that refers to it) were involved, which has been + corrected. + (merge 4468d4435c sg/object-as-type-commit-graph-fix later to maint). + + * "git fetch" output cleanup. + (merge dc40b24df4 nd/fetch-compact-update later to maint). + + * "git cat-file --batch" reported a dangling symbolic link by + mistake, when it wanted to report that a given name is ambiguous. + + * Documentation around core.crlf has been updated. + (merge c9446f0504 jk/autocrlf-overrides-eol-doc later to maint). + + * The documentation of "git commit-tree" said that the command + understands "--gpg-sign" in addition to "-S", but the command line + parser did not know about the longhand, which has been corrected. + + * "git rebase -x $cmd" did not reject multi-line command, even though + the command is incapable of handling such a command. It now is + rejected upfront. + (merge c762aada1a pw/rebase-x-sanity-check later to maint). + + * Output from "git help" was not correctly aligned, which has been + fixed. + (merge 6195a76da4 nd/help-align-command-desc later to maint). + + * The "git submodule summary" subcommand showed shortened commit + object names by mechanically truncating them at 7-hexdigit, which + has been improved to let "rev-parse --short" scale the length of + the abbreviation with the size of the repository. + (merge 0586a438f6 sh/submodule-summary-abbrev-fix later to maint). + + * The way the OSX build jobs updates its build environment used the + "--quiet" option to "brew update" command, but it wasn't all that + quiet to be useful. The use of the option has been replaced with + an explicit redirection to the /dev/null (which incidentally would + have worked around a breakage by recent updates to homebrew, which + has fixed itself already). + (merge a1ccaedd62 sg/travis-osx-brew-breakage-workaround later to maint). + + * "git --work-tree=$there --git-dir=$here describe --dirty" did not + work correctly as it did not pay attention to the location of the + worktree specified by the user by mistake, which has been + corrected. + (merge c801170b0c ss/describe-dirty-in-the-right-directory later to maint). + + * "git fetch" over protocol v2 that needs to make a second connection + to backfill tags did not clear a variable that holds shallow + repository information correctly, leading to an access of freed + piece of memory. + + * Some errors from the other side coming over smart HTTP transport + were not noticed, which has been corrected. + + * Code cleanup, docfix, build fix, etc. + (merge 89ba9a79ae hb/t0061-dot-in-path-fix later to maint). + (merge d173e799ea sb/diff-color-moved-config-option-fixup later to maint). + (merge a8f5a59067 en/directory-renames-nothanks-doc-update later to maint). + (merge ec36c42a63 nd/indentation-fix later to maint). + (merge f116ee21cd do/gitweb-strict-export-conf-doc later to maint). + (merge 112ea42663 fd/gitweb-snapshot-conf-doc-fix later to maint). + (merge 1cadad6f65 tb/use-common-win32-pathfuncs-on-cygwin later to maint). + (merge 57e9dcaa65 km/rebase-doc-typofix later to maint). + (merge b8b4cb27e6 ds/gc-doc-typofix later to maint). + (merge 3b3357626e nd/style-opening-brace later to maint). + (merge b4583d5595 es/doc-worktree-guessremote-config later to maint). + (merge cce99cd8c6 ds/commit-graph-assert-missing-parents later to maint). + (merge 0650614982 cy/completion-typofix later to maint). + (merge 6881925ef5 rs/sha1-file-close-mapped-file-on-error later to maint). + (merge bd8d6f0def en/show-ref-doc-fix later to maint). + (merge 1747125e2c cc/partial-clone-doc-typofix later to maint). + (merge e01378753d cc/fetch-error-message-fix later to maint). + (merge 54e8c11215 jk/remote-insteadof-cleanup later to maint). + (merge d609615f48 js/test-git-installed later to maint). + (merge ba170517be ja/doc-style-fix later to maint). + (merge 86fb1c4e77 km/init-doc-typofix later to maint). + (merge 5cfd4a9d10 nd/commit-doc later to maint). + (merge 9fce19a431 ab/diff-tree-doc-fix later to maint). + (merge 2e285e7803 tz/gpg-test-fix later to maint). + (merge 5427de960b kl/pretty-doc-markup-fix later to maint). + (merge 3815f64b0d js/mingw-host-cpu later to maint). + (merge 5fe81438b5 rj/sequencer-sign-off-header-static later to maint). + (merge 18a4f6be6b nd/fileno-may-be-macro later to maint). + (merge 99e9ab54ab kd/t0028-octal-del-is-377-not-777 later to maint). diff --git a/Documentation/config/advice.txt b/Documentation/config/advice.txt index 57fcd4c..8862042 100644 --- a/Documentation/config/advice.txt +++ b/Documentation/config/advice.txt @@ -30,6 +30,13 @@ advice.*:: tries to overwrite a remote ref that points at an object that is not a commit-ish, or make the remote ref point at an object that is not a commit-ish. + pushUnqualifiedRefname:: + Shown when linkgit:git-push[1] gives up trying to + guess based on the source and destination refs what + remote ref namespace the source belongs in, but where + we can still suggest that the user push to either + refs/heads/* or refs/tags/* based on the type of the + source object. statusHints:: Show directions on how to proceed from the current state in the output of linkgit:git-status[1], in diff --git a/Documentation/config/core.txt b/Documentation/config/core.txt index d0e6635..7e9b6c8 100644 --- a/Documentation/config/core.txt +++ b/Documentation/config/core.txt @@ -121,11 +121,14 @@ core.quotePath:: core.eol:: Sets the line ending type to use in the working directory for - files that have the `text` property set when core.autocrlf is false. + files that are marked as text (either by having the `text` + attribute set, or by having `text=auto` and Git auto-detecting + the contents as text). Alternatives are 'lf', 'crlf' and 'native', which uses the platform's native line ending. The default value is `native`. See linkgit:gitattributes[5] for more information on end-of-line - conversion. + conversion. Note that this value is ignored if `core.autocrlf` + is set to `true` or `input`. core.safecrlf:: If true, makes Git check if converting `CRLF` is reversible when diff --git a/Documentation/config/http.txt b/Documentation/config/http.txt index a56d848..5a32f5b 100644 --- a/Documentation/config/http.txt +++ b/Documentation/config/http.txt @@ -68,6 +68,15 @@ http.saveCookies:: If set, store cookies received during requests to the file specified by http.cookieFile. Has no effect if http.cookieFile is unset. +http.version:: + Use the specified HTTP protocol version when communicating with a server. + If you want to force the default. The available and default version depend + on libcurl. Actually the possible values of + this option are: + + - HTTP/2 + - HTTP/1.1 + http.sslVersion:: The SSL version to use when negotiating an SSL connection, if you want to force the default. The available and default version diff --git a/Documentation/config/pack.txt b/Documentation/config/pack.txt index edac75c..425c73a 100644 --- a/Documentation/config/pack.txt +++ b/Documentation/config/pack.txt @@ -105,6 +105,15 @@ pack.useBitmaps:: true. You should not generally need to turn this off unless you are debugging pack bitmaps. +pack.useSparse:: + When true, git will default to using the '--sparse' option in + 'git pack-objects' when the '--revs' option is present. This + algorithm only walks trees that appear in paths that introduce new + objects. This can have significant performance benefits when + computing a pack to send a small change. However, it is possible + that extra objects are added to the pack-file if the included + commits contain certain types of direct renames. + pack.writeBitmaps (deprecated):: This is a deprecated synonym for `repack.writeBitmaps`. diff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.txt index f079bf6..331d250 100644 --- a/Documentation/config/rebase.txt +++ b/Documentation/config/rebase.txt @@ -64,3 +64,8 @@ instead of: ------------------------------------------- + Defaults to false. + +rebase.rescheduleFailedExec:: + Automatically reschedule `exec` commands that failed. This only makes + sense in interactive mode (or when an `--exec` option was provided). + This is the same as specifying the `--reschedule-failed-exec` option. diff --git a/Documentation/config/worktree.txt b/Documentation/config/worktree.txt index b853798..048e349 100644 --- a/Documentation/config/worktree.txt +++ b/Documentation/config/worktree.txt @@ -1,6 +1,6 @@ worktree.guessRemote:: - With `add`, if no branch argument, and neither of `-b` nor - `-B` nor `--detach` are given, the command defaults to + If no branch is specified and neither `-b` nor `-B` nor + `--detach` is used, then `git worktree add` defaults to creating a new branch from HEAD. If `worktree.guessRemote` is set to true, `worktree add` tries to find a remote-tracking branch whose name uniquely matches the new branch name. If diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 0378cd5..554a340 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -293,8 +293,12 @@ dimmed-zebra:: `dimmed_zebra` is a deprecated synonym. -- +--no-color-moved:: + Turn off move detection. This can be used to override configuration + settings. It is the same as `--color-moved=no`. + --color-moved-ws=:: - This configures how white spaces are ignored when performing the + This configures how whitespace is ignored when performing the move detection for `--color-moved`. ifdef::git-diff[] It can be set by the `diff.colorMovedWS` configuration setting. @@ -302,6 +306,8 @@ endif::git-diff[] These modes can be given as a comma separated list: + -- +no:: + Do not ignore whitespace when performing move detection. ignore-space-at-eol:: Ignore changes in whitespace at EOL. ignore-space-change:: @@ -312,12 +318,17 @@ ignore-all-space:: Ignore whitespace when comparing lines. This ignores differences even if one line has whitespace where the other line has none. allow-indentation-change:: - Initially ignore any white spaces in the move detection, then + Initially ignore any whitespace in the move detection, then group the moved code blocks only into a block if the change in whitespace is the same per line. This is incompatible with the other modes. -- +--no-color-moved-ws:: + Do not ignore whitespace when performing move detection. This can be + used to override configuration settings. It is the same as + `--color-moved-ws=no`. + --word-diff[=]:: Show a word diff, using the to delimit changed words. By default, words are delimited by whitespace; see @@ -524,6 +535,8 @@ struct), and want to know the history of that block since it first came into being: use the feature iteratively to feed the interesting block in the preimage back into `-S`, and keep going until you get the very first version of the block. ++ +Binary files are searched as well. -G:: Look for differences whose patch text contains added/removed @@ -543,6 +556,9 @@ While `git log -G"regexec\(regexp"` will show this commit, `git log -S"regexec\(regexp" --pickaxe-regex` will not (because the number of occurrences of that string did not change). + +Unless `--text` is supplied patches of binary files without a textconv +filter will be ignored. ++ See the 'pickaxe' entry in linkgit:gitdiffcore[7] for more information. diff --git a/Documentation/doc-diff b/Documentation/doc-diff index dfd9418..32c83dd 100755 --- a/Documentation/doc-diff +++ b/Documentation/doc-diff @@ -39,8 +39,7 @@ do shift done -cd_to_toplevel -tmp=Documentation/tmp-doc-diff +tmp="$(git rev-parse --show-toplevel)/Documentation/tmp-doc-diff" || exit 1 if test -n "$clean" then @@ -109,7 +108,7 @@ render_tree () { make -j$parallel -C "$tmp/worktree" \ GIT_VERSION=omitted \ SOURCE_DATE_EPOCH=0 \ - DESTDIR="$PWD/$tmp/installed/$1+" \ + DESTDIR="$tmp/installed/$1+" \ install-man && mv "$tmp/installed/$1+" "$tmp/installed/$1" fi && diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt index 45652fe..37bcab9 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.txt @@ -58,9 +58,9 @@ OPTIONS specifying `dir` will record not just a file `dir/file1` modified in the working tree, a file `dir/file2` added to the working tree, but also a file `dir/file3` removed from - the working tree. Note that older versions of Git used + the working tree). Note that older versions of Git used to ignore removed files; use `--no-all` option if you want - to add modified or new files but ignore removed ones. + to add modified or new files but ignore removed ones. + For more details about the syntax, see the 'pathspec' entry in linkgit:gitglossary[7]. @@ -124,7 +124,7 @@ subdirectories). --no-ignore-removal:: Update the index not only where the working tree has a file matching but also where the index already has an - entry. This adds, modifies, and removes index entries to + entry. This adds, modifies, and removes index entries to match the working tree. + If no is given when `-A` option is used, all @@ -206,7 +206,7 @@ EXAMPLES -------- * Adds content from all `*.txt` files under `Documentation` directory -and its subdirectories: + and its subdirectories: + ------------ $ git add Documentation/\*.txt diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index bf5316f..3bd83a7 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -297,7 +297,7 @@ $ git checkout my2.6.14 ------------ + <1> This step and the next one could be combined into a single step with -"checkout -b my2.6.14 v2.6.14". + "checkout -b my2.6.14 v2.6.14". Delete an unneeded branch:: + @@ -309,10 +309,10 @@ $ git branch -D test <2> ------------ + <1> Delete the remote-tracking branches "todo", "html" and "man". The next -'fetch' or 'pull' will create them again unless you configure them not to. -See linkgit:git-fetch[1]. + 'fetch' or 'pull' will create them again unless you configure them not to. + See linkgit:git-fetch[1]. <2> Delete the "test" branch even if the "master" branch (or whichever branch -is currently checked out) does not have all commits from the test branch. + is currently checked out) does not have all commits from the test branch. NOTES diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt index 7401333..8eca671 100644 --- a/Documentation/git-cat-file.txt +++ b/Documentation/git-cat-file.txt @@ -23,8 +23,8 @@ In the second form, a list of objects (separated by linefeeds) is provided on stdin, and the SHA-1, type, and size of each object is printed on stdout. The output format can be overridden using the optional `` argument. If either `--textconv` or `--filters` was specified, the input is expected to -list the object names followed by the path name, separated by a single white -space, so that the appropriate drivers can be determined. +list the object names followed by the path name, separated by a single +whitespace, so that the appropriate drivers can be determined. OPTIONS ------- @@ -79,7 +79,7 @@ OPTIONS Print object information and contents for each object provided on stdin. May not be combined with any other options or arguments except `--textconv` or `--filters`, in which case the input lines - also need to specify the path, separated by white space. See the + also need to specify the path, separated by whitespace. See the section `BATCH OUTPUT` below for details. --batch-check:: @@ -87,7 +87,7 @@ OPTIONS Print object information for each object provided on stdin. May not be combined with any other options or arguments except `--textconv` or `--filters`, in which case the input lines also - need to specify the path, separated by white space. See the + need to specify the path, separated by whitespace. See the section `BATCH OUTPUT` below for details. --batch-all-objects:: @@ -252,6 +252,12 @@ the repository, then `cat-file` will ignore any custom format and print: SP missing LF ------------ +If a name is specified that might refer to more than one object (an ambiguous short sha), then `cat-file` will ignore any custom format and print: + +------------ + SP ambiguous LF +------------ + If --follow-symlinks is used, and a symlink in the repository points outside the repository, then `cat-file` will ignore any custom format and print: diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt index 801de2f..8c3d412 100644 --- a/Documentation/git-checkout.txt +++ b/Documentation/git-checkout.txt @@ -276,6 +276,10 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode. Just like linkgit:git-submodule[1], this will detach the submodules HEAD. +--no-guess:: + Do not attempt to create a branch if a remote tracking branch + of the same name exists. + :: Branch to checkout; if it refers to a branch (i.e., a name that, when prepended with "refs/heads/", is a valid ref), then that @@ -285,7 +289,7 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode. + You can use the `"@{-N}"` syntax to refer to the N-th last branch/commit checked out using "git checkout" operation. You may -also specify `-` which is synonymous to `"@{-1}`. +also specify `-` which is synonymous to `"@{-1}"`. + As a special case, you may use `"A...B"` as a shortcut for the merge base of `A` and `B` if there is exactly one merge base. You can @@ -420,14 +424,14 @@ $ 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. + 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. + but leaves HEAD detached. <3> creates a new tag 'foo', which refers to commit 'f', -leaving HEAD detached. + leaving HEAD detached. If we have moved away from commit 'f', then we must first recover its object name (typically by using git reflog), and then we can create a reference to @@ -455,8 +459,8 @@ 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. + the `Makefile` to two revisions back, deletes hello.c by + mistake, and gets it back from the index. + ------------ $ git checkout master <1> @@ -490,7 +494,7 @@ $ git checkout -- hello.c ------------ . After working in the wrong branch, switching to the correct -branch would be done using: + branch would be done using: + ------------ $ git checkout mytopic @@ -518,7 +522,7 @@ 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: + the `-m` option, you would see something like this: + ------------ $ git checkout -m mytopic diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index d35d771..b8cfeec 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -213,16 +213,16 @@ $ git reset --merge ORIG_HEAD <3> $ git cherry-pick -Xpatience topic^ <4> ------------ <1> apply the change that would be shown by `git show topic^`. -In this example, the patch does not apply cleanly, so -information about the conflict is written to the index and -working tree and no new commit results. + In this example, the patch does not apply cleanly, so + information about the conflict is written to the index and + working tree and no new commit results. <2> summarize changes to be reconciled <3> cancel the cherry-pick. In other words, return to the -pre-cherry-pick state, preserving any local modifications you had in -the working tree. + pre-cherry-pick state, preserving any local modifications + you had in the working tree. <4> try to apply the change introduced by `topic^` again, -spending extra time to avoid mistakes based on incorrectly matching -context lines. + spending extra time to avoid mistakes based on incorrectly + matching context lines. SEE ALSO -------- diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index a55536f..2fd1252 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -189,6 +189,12 @@ objects from the source repository into a pack in the cloned repository. values are given for the same key, each value will be written to the config file. This makes it safe, for example, to add additional fetch refspecs to the origin remote. ++ +Due to limitations of the current implementation, some configuration +variables do not take effect until after the initial fetch and checkout. +Configuration variables known to not take effect are: +`remote..mirror` and `remote..tagOpt`. Use the +corresponding `--mirror` and `--no-tags` options instead. --depth :: Create a 'shallow' clone with a history truncated to the diff --git a/Documentation/git-column.txt b/Documentation/git-column.txt index 763afab..f58e9c4 100644 --- a/Documentation/git-column.txt +++ b/Documentation/git-column.txt @@ -47,7 +47,7 @@ OPTIONS The number of spaces between columns. One space by default. EXAMPLES ------- +-------- Format data by columns: ------------ diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index f970a43..a85c2c2 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -17,16 +17,20 @@ SYNOPSIS DESCRIPTION ----------- -Stores the current contents of the index in a new commit along -with a log message from the user describing the changes. +Create a new commit containing the current contents of the index and +the given log message describing the changes. The new commit is a +direct child of HEAD, usually the tip of the current branch, and the +branch is updated to point to it (unless no branch is associated with +the working tree, in which case HEAD is "detached" as described in +linkgit:git-checkout[1]). -The content to be added can be specified in several ways: +The content to be committed can be specified in several ways: -1. by using 'git add' to incrementally "add" changes to the - index before using the 'commit' command (Note: even modified - files must be "added"); +1. by using linkgit:git-add[1] to incrementally "add" changes to the + index before using the 'commit' command (Note: even modified files + must be "added"); -2. by using 'git rm' to remove files from the working tree +2. by using linkgit:git-rm[1] to remove files from the working tree and the index, again before using the 'commit' command; 3. by listing files as arguments to the 'commit' command diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt index 2319b2b..43daa7c 100644 --- a/Documentation/git-diff-tree.txt +++ b/Documentation/git-diff-tree.txt @@ -31,10 +31,7 @@ include::diff-options.txt[] ...:: If provided, the results are limited to a subset of files - matching one of these prefix strings. - i.e., file matches `/^||.../` - Note that this parameter does not provide any wildcard or regexp - features. + matching one of the provided pathspecs. -r:: recurse into sub-trees @@ -114,52 +111,6 @@ include::pretty-options.txt[] include::pretty-formats.txt[] - - -LIMITING OUTPUT ---------------- -If you're only interested in differences in a subset of files, for -example some architecture-specific files, you might do: - - git diff-tree -r arch/ia64 include/asm-ia64 - -and it will only show you what changed in those two directories. - -Or if you are searching for what changed in just `kernel/sched.c`, just do - - git diff-tree -r kernel/sched.c - -and it will ignore all differences to other files. - -The pattern is always the prefix, and is matched exactly. There are no -wildcards. Even stricter, it has to match a complete path component. -I.e. "foo" does not pick up `foobar.h`. "foo" does match `foo/bar.h` -so it can be used to name subdirectories. - -An example of normal usage is: - - torvalds@ppc970:~/git> git diff-tree --abbrev 5319e4 - :100664 100664 ac348b... a01513... git-fsck-objects.c - -which tells you that the last commit changed just one file (it's from -this one: - ------------------------------------------------------------------------------ -commit 3c6f7ca19ad4043e9e72fa94106f352897e651a8 -tree 5319e4d609cdd282069cc4dce33c1db559539b03 -parent b4e628ea30d5ab3606119d2ea5caeab141d38df7 -author Linus Torvalds Sat Apr 9 12:02:30 2005 -committer Linus Torvalds Sat Apr 9 12:02:30 2005 - -Make "git-fsck-objects" print out all the root commits it finds. - -Once I do the reference tracking, I'll also make it print out all the -HEAD commits it finds, which is even more interesting. ------------------------------------------------------------------------------ - -in case you care). - - include::diff-format.txt[] GIT diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt index 030f162..72179d9 100644 --- a/Documentation/git-diff.txt +++ b/Documentation/git-diff.txt @@ -132,9 +132,9 @@ $ git diff HEAD <3> + <1> Changes in the working tree not yet staged for the next commit. <2> Changes between the index and your last commit; what you -would be committing if you run "git commit" without "-a" option. + would be committing if you run "git commit" without "-a" option. <3> Changes in the working tree since your last commit; what you -would be committing if you run "git commit -a" + would be committing if you run "git commit -a" Comparing with arbitrary commits:: + @@ -145,10 +145,10 @@ $ git diff HEAD^ HEAD <3> ------------ + <1> Instead of using the tip of the current branch, compare with the -tip of "test" branch. + tip of "test" branch. <2> Instead of comparing with the tip of "test" branch, compare with -the tip of the current branch, but limit the comparison to the -file "test". + the tip of the current branch, but limit the comparison to the + file "test". <3> Compare the version before the last commit and the last commit. Comparing branches:: @@ -162,7 +162,7 @@ $ git diff topic...master <3> <1> Changes between the tips of the topic and the master branches. <2> Same as above. <3> Changes that occurred on the master branch since when the topic -branch was started off it. + branch was started off it. Limiting the diff output:: + @@ -173,9 +173,9 @@ $ git diff arch/i386 include/asm-i386 <3> ------------ + <1> Show only modification, rename, and copy, but not addition -or deletion. + or deletion. <2> Show only names and the nature of change, but not actual -diff output. + diff output. <3> Limit diff output to named subtrees. Munging the diff output:: @@ -186,7 +186,7 @@ $ git diff -R <2> ------------ + <1> Spend extra cycles to find renames, copies and complete -rewrites (very expensive). + rewrites (very expensive). <2> Output diff in reverse. SEE ALSO diff --git a/Documentation/git-fast-export.txt b/Documentation/git-fast-export.txt index ce954be..64c01ba 100644 --- a/Documentation/git-fast-export.txt +++ b/Documentation/git-fast-export.txt @@ -110,6 +110,25 @@ marks the same across runs. the shape of the history and stored tree. See the section on `ANONYMIZING` below. +--reference-excluded-parents:: + By default, running a command such as `git fast-export + master~5..master` will not include the commit master{tilde}5 + and will make master{tilde}4 no longer have master{tilde}5 as + a parent (though both the old master{tilde}4 and new + master{tilde}4 will have all the same files). Use + --reference-excluded-parents to instead have the the stream + refer to commits in the excluded range of history by their + sha1sum. Note that the resulting stream can only be used by a + repository which already contains the necessary parent + commits. + +--show-original-ids:: + Add an extra directive to the output for commits and blobs, + `original-oid `. While such directives will likely be + ignored by importers such as git-fast-import, it may be useful + for intermediary filters (e.g. for rewriting commit messages + which refer to older commits, or for stripping blobs by id). + --refspec:: Apply the specified refspec to each ref exported. Multiple of them can be specified. @@ -119,7 +138,9 @@ marks the same across runs. 'git rev-list', that specifies the specific objects and references to export. For example, `master~10..master` causes the current master reference to be exported along with all objects - added since its 10th ancestor commit. + added since its 10th ancestor commit and (unless the + --reference-excluded-parents option is specified) all files + common to master{tilde}9 and master{tilde}10. EXAMPLES -------- diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index 9e3b958..43ab3b1 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -40,9 +40,10 @@ OPTIONS not contain the old commit). --quiet:: - Disable all non-fatal output, making fast-import silent when it - is successful. This option disables the output shown by - --stats. + Disable the output shown by --stats, making fast-import usually + be silent when it is successful. However, if the import stream + has directives intended to show user output (e.g. `progress` + directives), the corresponding messages will still be shown. --stats:: Display some basic statistics about the objects fast-import has @@ -50,21 +51,6 @@ OPTIONS memory used by fast-import during this run. Showing this output is currently the default, but can be disabled with --quiet. ---allow-unsafe-features:: - Many command-line options can be provided as part of the - fast-import stream itself by using the `feature` or `option` - commands. However, some of these options are unsafe (e.g., - allowing fast-import to access the filesystem outside of the - repository). These options are disabled by default, but can be - allowed by providing this option on the command line. This - currently impacts only the `export-marks`, `import-marks`, and - `import-marks-if-exists` feature commands. -+ - Only enable this option if you trust the program generating the - fast-import stream! This option is enabled automatically for - remote-helpers that use the `import` capability, as they are - already trusted to run their own code. - Options for Frontends ~~~~~~~~~~~~~~~~~~~~~ @@ -399,6 +385,7 @@ change to the project. .... 'commit' SP LF mark? + original-oid? ('author' (SP )? SP LT GT SP LF)? 'committer' (SP )? SP LT GT SP LF data @@ -755,6 +742,19 @@ New marks are created automatically. Existing marks can be moved to another object simply by reusing the same `` in another `mark` command. +`original-oid` +~~~~~~~~~~~~~~ +Provides the name of the object in the original source control system. +fast-import will simply ignore this directive, but filter processes +which operate on and modify the stream before feeding to fast-import +may have uses for this information + +.... + 'original-oid' SP LF +.... + +where `` is any string not containing LF. + `tag` ~~~~~ Creates an annotated tag referring to a specific commit. To create @@ -763,6 +763,7 @@ lightweight (non-annotated) tags see the `reset` command below. .... 'tag' SP LF 'from' SP LF + original-oid? 'tagger' (SP )? SP LT GT SP LF data .... @@ -837,6 +838,7 @@ assigned mark. .... 'blob' LF mark? + original-oid? data .... diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt index e319935..266d63c 100644 --- a/Documentation/git-fetch.txt +++ b/Documentation/git-fetch.txt @@ -266,7 +266,7 @@ The `pu` branch will be updated even if it is does not fast-forward, because it is prefixed with a plus sign; `tmp` will not be. * Peek at a remote's branch, without configuring the remote in your local -repository: + repository: + ------------------------------------------------ $ git fetch git://git.kernel.org/pub/scm/git/git.git maint diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt index 901faef..774cecc 100644 --- a/Documentation/git-for-each-ref.txt +++ b/Documentation/git-for-each-ref.txt @@ -128,13 +128,18 @@ objecttype:: objectsize:: The size of the object (the same as 'git cat-file -s' reports). - + Append `:disk` to get the size, in bytes, that the object takes up on + disk. See the note about on-disk sizes in the `CAVEATS` section below. objectname:: The object name (aka SHA-1). For a non-ambiguous abbreviation of the object name append `:short`. For an abbreviation of the object name with desired length append `:short=`, where the minimum length is MINIMUM_ABBREV. The length may be exceeded to ensure unique object names. +deltabase:: + This expands to the object name of the delta base for the + given object, if it is stored as a delta. Otherwise it + expands to the null object name (all zeroes). upstream:: The name of a local ref which can be considered ``upstream'' @@ -361,6 +366,20 @@ This prints the authorname, if present. git for-each-ref --format="%(refname)%(if)%(authorname)%(then) Authored by: %(authorname)%(end)" ------------ +CAVEATS +------- + +Note that the sizes of objects on disk are reported accurately, but care +should be taken in drawing conclusions about which refs or objects are +responsible for disk usage. The size of a packed non-delta object may be +much larger than the size of objects which delta against it, but the +choice of which object is the base and which is the delta is arbitrary +and is subject to change during a repack. + +Note also that multiple copies of an object may be present in the object +database; in this case, it is undefined which copy's size or delta base +will be reported. + SEE ALSO -------- linkgit:git-show-ref[1] diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 2730442..1af85d4 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -504,9 +504,9 @@ Toggle it to make sure it is set to `false`. Also, search for "mailnews.wraplength" and set the value to 0. 3. Disable the use of format=flowed: -Edit..Preferences..Advanced..Config Editor. Search for -"mailnews.send_plaintext_flowed". -Toggle it to make sure it is set to `false`. + Edit..Preferences..Advanced..Config Editor. Search for + "mailnews.send_plaintext_flowed". + Toggle it to make sure it is set to `false`. After that is done, you should be able to compose email as you otherwise would (cut + paste, 'git format-patch' | 'git imap-send', etc), @@ -629,14 +629,14 @@ EXAMPLES -------- * Extract commits between revisions R1 and R2, and apply them on top of -the current branch using 'git am' to cherry-pick them: + the current branch using 'git am' to cherry-pick them: + ------------ $ git format-patch -k --stdout R1..R2 | git am -3 -k ------------ * Extract all commits which are in the current branch but not in the -origin branch: + origin branch: + ------------ $ git format-patch origin @@ -645,7 +645,7 @@ $ git format-patch origin For each commit a separate file is created in the current directory. * Extract all commits that lead to 'origin' since the inception of the -project: + project: + ------------ $ git format-patch --root origin @@ -664,7 +664,7 @@ Note that non-Git "patch" programs won't understand renaming patches, so use it only when you know the recipient uses Git to apply your patch. * Extract three topmost commits from the current branch and format them -as e-mailable patches: + as e-mailable patches: + ------------ $ git format-patch -3 diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt index ab9a93f..55950d9 100644 --- a/Documentation/git-fsck.txt +++ b/Documentation/git-fsck.txt @@ -140,9 +140,9 @@ dangling :: The object , is present in the database but never 'directly' used. A dangling commit could be a root node. -sha1 mismatch :: - The database has an object who's sha1 doesn't match the - database value. +hash mismatch :: + The database has an object whose hash doesn't match the + object database value. This indicates a serious data integrity problem. Environment Variables diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt index c20ee6c..a744249 100644 --- a/Documentation/git-gc.txt +++ b/Documentation/git-gc.txt @@ -137,7 +137,7 @@ The optional configuration variable `gc.packRefs` determines if it within all non-bare repos or it can be set to a boolean value. This defaults to true. -The optional configuration variable `gc.commitGraph` determines if +The optional configuration variable `gc.writeCommitGraph` determines if 'git gc' should run 'git commit-graph write'. This can be set to a boolean value. This defaults to false. diff --git a/Documentation/git-help.txt b/Documentation/git-help.txt index aab5453..c318bf8 100644 --- a/Documentation/git-help.txt +++ b/Documentation/git-help.txt @@ -118,9 +118,9 @@ format is chosen. The following values are currently supported: * "man": use the 'man' program as usual, * "woman": use 'emacsclient' to launch the "woman" mode in emacs -(this only works starting with emacsclient versions 22), + (this only works starting with emacsclient versions 22), * "konqueror": use 'kfmclient' to open the man page in a new konqueror -tab (see 'Note about konqueror' below). + tab (see 'Note about konqueror' below). Values for other tools can be used if there is a corresponding `man..cmd` configuration entry (see below). diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt index 3c5a67f..32880aa 100644 --- a/Documentation/git-init.txt +++ b/Documentation/git-init.txt @@ -38,8 +38,6 @@ the repository to another place if --separate-git-dir is given). OPTIONS ------- --- - -q:: --quiet:: @@ -111,8 +109,6 @@ into it. If you provide a 'directory', the command is run inside it. If this directory does not exist, it will be created. --- - TEMPLATE DIRECTORY ------------------ @@ -132,7 +128,7 @@ The template directory will be one of the following (in order): The default template directory includes some directory structure, suggested "exclude patterns" (see linkgit:gitignore[5]), and sample hook files. -The sample hooks are all disabled by default, To enable one of the +The sample hooks are all disabled by default. To enable one of the sample hooks rename it by removing its `.sample` suffix. See linkgit:githooks[5] for more general info on hook execution. diff --git a/Documentation/git-instaweb.txt b/Documentation/git-instaweb.txt index e8ecdbf..a54fe44 100644 --- a/Documentation/git-instaweb.txt +++ b/Documentation/git-instaweb.txt @@ -29,7 +29,8 @@ OPTIONS The HTTP daemon command-line that will be executed. Command-line options may be specified here, and the configuration file will be added at the end of the command-line. - Currently apache2, lighttpd, mongoose, plackup and webrick are supported. + Currently apache2, lighttpd, mongoose, plackup, python and + webrick are supported. (Default: lighttpd) -m:: diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt index 90761f1..b02e922 100644 --- a/Documentation/git-log.txt +++ b/Documentation/git-log.txt @@ -192,6 +192,10 @@ log.date:: Default format for human-readable dates. (Compare the `--date` option.) Defaults to "default", which means to write dates like `Sat May 8 19:35:34 2010 -0500`. ++ +If the format is set to "auto:foo" and the pager is in use, format +"foo" will be the used for the date format. Otherwise "default" will +be used. log.follow:: If `true`, `git log` will act as if the `--follow` option was used when diff --git a/Documentation/git-p4.txt b/Documentation/git-p4.txt index f0a0280..3494a1d 100644 --- a/Documentation/git-p4.txt +++ b/Documentation/git-p4.txt @@ -71,12 +71,12 @@ $ git p4 clone //depot/path/project ------------ This: -1. Creates an empty Git repository in a subdirectory called 'project'. +1. Creates an empty Git repository in a subdirectory called 'project'. + -2. Imports the full contents of the head revision from the given p4 -depot path into a single commit in the Git branch 'refs/remotes/p4/master'. +2. Imports the full contents of the head revision from the given p4 + depot path into a single commit in the Git branch 'refs/remotes/p4/master'. + -3. Creates a local branch, 'master' from this remote and checks it out. +3. Creates a local branch, 'master' from this remote and checks it out. To reproduce the entire p4 history in Git, use the '@all' modifier on the depot path: diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt index 40c825c..e45f3e6 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.txt @@ -14,7 +14,7 @@ SYNOPSIS [--local] [--incremental] [--window=] [--depth=] [--revs [--unpacked | --all]] [--keep-pack=] [--stdout [--filter=] | base-name] - [--shallow] [--keep-true-parents] < object-list + [--shallow] [--keep-true-parents] [--sparse] < object-list DESCRIPTION @@ -196,6 +196,15 @@ depth is 4095. Add --no-reuse-object if you want to force a uniform compression level on all data no matter the source. +--sparse:: + Use the "sparse" algorithm to determine which objects to include in + the pack, when combined with the "--revs" option. This algorithm + only walks trees that appear in paths that introduce new objects. + This can have significant performance benefits when computing + a pack to send a small change. However, it is possible that extra + objects are added to the pack-file if the included commits contain + certain types of direct renames. + --thin:: Create a "thin" pack by omitting the common objects between a sender and a receiver in order to reduce network transfer. This diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt index a5fc54a..6a8a0d9 100644 --- a/Documentation/git-push.txt +++ b/Documentation/git-push.txt @@ -73,6 +73,26 @@ be omitted--such a push will update a ref that `` normally updates without any `` on the command line. Otherwise, missing `:` means to update the same ref as the ``. + +If doesn't start with `refs/` (e.g. `refs/heads/master`) we will +try to infer where in `refs/*` on the destination it +belongs based on the the type of being pushed and whether +is ambiguous. ++ +-- +* If unambiguously refers to a ref on the remote, + then push to that ref. + +* If resolves to a ref starting with refs/heads/ or refs/tags/, + then prepend that to . + +* Other ambiguity resolutions might be added in the future, but for + now any other cases will error out with an error indicating what we + tried, and depending on the `advice.pushUnqualifiedRefname` + configuration (see linkgit:git-config[1]) suggest what refs/ + namespace you may have wanted to push to. + +-- ++ The object referenced by is used to update the reference on the remote side. Whether this is allowed depends on where in `refs/*` the reference lives as described in detail below, in @@ -591,6 +611,9 @@ the ones in the examples below) can be configured as the default for `refs/remotes/satellite/master`) in the `mothership` repository; do the same for `dev` and `satellite/dev`. + +See the section describing `...` above for a discussion of +the matching semantics. ++ This is to emulate `git fetch` run on the `mothership` using `git push` that is run in the opposite direction in order to integrate the work done on `satellite`, and is often necessary when you can diff --git a/Documentation/git-quiltimport.txt b/Documentation/git-quiltimport.txt index 8cf952b..70562dc 100644 --- a/Documentation/git-quiltimport.txt +++ b/Documentation/git-quiltimport.txt @@ -10,7 +10,7 @@ SYNOPSIS -------- [verse] 'git quiltimport' [--dry-run | -n] [--author ] [--patches ] - [--series ] + [--series ] [--keep-non-patch] DESCRIPTION @@ -56,6 +56,9 @@ The default for the series file is /series or the value of the `$QUILT_SERIES` environment variable. +--keep-non-patch:: + Pass `-b` flag to 'git mailinfo' (see linkgit:git-mailinfo[1]). + GIT --- Part of the linkgit:git[1] suite diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index dff17b3..5629ba4 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -501,18 +501,15 @@ See also INCOMPATIBLE OPTIONS below. with care: the final stash application after a successful rebase might result in non-trivial conflicts. +--reschedule-failed-exec:: +--no-reschedule-failed-exec:: + Automatically reschedule `exec` commands that failed. This only makes + sense in interactive mode (or when an `--exec` option was provided). + INCOMPATIBLE OPTIONS -------------------- -git-rebase has many flags that are incompatible with each other, -predominantly due to the fact that it has three different underlying -implementations: - - * one based on linkgit:git-am[1] (the default) - * one based on git-merge-recursive (merge backend) - * one based on linkgit:git-cherry-pick[1] (interactive backend) - -Flags only understood by the am backend: +The following options: * --committer-date-is-author-date * --ignore-date @@ -520,26 +517,22 @@ Flags only understood by the am backend: * --ignore-whitespace * -C -Flags understood by both merge and interactive backends: +are incompatible with the following options: * --merge * --strategy * --strategy-option * --allow-empty-message - -Flags only understood by the interactive backend: - * --[no-]autosquash * --rebase-merges * --preserve-merges * --interactive * --exec * --keep-empty - * --autosquash * --edit-todo * --root when used in combination with --onto -Other incompatible flag pairs: +In addition, the following pairs of options are incompatible: * --preserve-merges and --interactive * --preserve-merges and --signoff @@ -560,8 +553,6 @@ commit started empty (had no changes relative to its parent to start with) or ended empty (all changes were already applied upstream in other commits). -The merge backend does the same. - The interactive backend drops commits by default that started empty and halts if it hits a commit that ended up empty. The `--keep-empty` option exists for the interactive backend to allow @@ -570,8 +561,9 @@ it to keep commits that started empty. Directory rename detection ~~~~~~~~~~~~~~~~~~~~~~~~~~ -The merge and interactive backends work fine with -directory rename detection. The am backend sometimes does not. +Directory rename heuristics are enabled in the merge and interactive +backends. Due to the lack of accurate tree information, directory +rename detection is disabled in the am backend. include::merge-strategies.txt[] @@ -979,7 +971,7 @@ when the merge operation did not even start), it is rescheduled immediately. At this time, the `merge` command will *always* use the `recursive` merge strategy for regular merges, and `octopus` for octopus merges, -strategy, with no way to choose a different one. To work around +with no way to choose a different one. To work around this, an `exec` command can be used to call `git merge` explicitly, using the fact that the labels are worktree-local refs (the ref `refs/rewritten/onto` would correspond to the label `onto`, for example). diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt index 9f69ae8..132f8e5 100644 --- a/Documentation/git-reset.txt +++ b/Documentation/git-reset.txt @@ -115,17 +115,17 @@ $ git pull git://info.example.com/ nitfol <4> ------------ + <1> You are happily working on something, and find the changes -in these files are in good order. You do not want to see them -when you run `git diff`, because you plan to work on other files -and changes with these files are distracting. + in these files are in good order. You do not want to see them + when you run `git diff`, because you plan to work on other files + and changes with these files are distracting. <2> Somebody asks you to pull, and the changes sound worthy of merging. <3> However, you already dirtied the index (i.e. your index does -not match the `HEAD` commit). But you know the pull you are going -to make does not affect `frotz.c` or `filfre.c`, so you revert the -index changes for these two files. Your changes in working tree -remain there. + not match the `HEAD` commit). But you know the pull you are going + to make does not affect `frotz.c` or `filfre.c`, so you revert the + index changes for these two files. Your changes in working tree + remain there. <4> Then you can pull and merge, leaving `frotz.c` and `filfre.c` -changes still in the working tree. + changes still in the working tree. Undo a commit and redo:: + @@ -137,12 +137,12 @@ $ git commit -a -c ORIG_HEAD <3> ------------ + <1> This is most often done when you remembered what you -just committed is incomplete, or you misspelled your commit -message, or both. Leaves working tree as it was before "reset". + just committed is incomplete, or you misspelled your commit + message, or both. Leaves working tree as it was before "reset". <2> Make corrections to working tree files. <3> "reset" copies the old head to `.git/ORIG_HEAD`; redo the -commit by starting with its log message. If you do not need to -edit the message further, you can give `-C` option instead. + commit by starting with its log message. If you do not need to + edit the message further, you can give `-C` option instead. + See also the `--amend` option to linkgit:git-commit[1]. @@ -155,9 +155,9 @@ $ git checkout topic/wip <3> ------------ + <1> You have made some commits, but realize they were premature -to be in the `master` branch. You want to continue polishing -them in a topic branch, so create `topic/wip` branch off of the -current `HEAD`. + to be in the `master` branch. You want to continue polishing + them in a topic branch, so create `topic/wip` branch off of the + current `HEAD`. <2> Rewind the master branch to get rid of those three commits. <3> Switch to `topic/wip` branch and keep working. @@ -169,10 +169,10 @@ $ git reset --hard HEAD~3 <1> ------------ + <1> The last three commits (`HEAD`, `HEAD^`, and `HEAD~2`) were bad -and you do not want to ever see them again. Do *not* do this if -you have already given these commits to somebody else. (See the -"RECOVERING FROM UPSTREAM REBASE" section in linkgit:git-rebase[1] for -the implications of doing so.) + and you do not want to ever see them again. Do *not* do this if + you have already given these commits to somebody else. (See the + "RECOVERING FROM UPSTREAM REBASE" section in linkgit:git-rebase[1] + for the implications of doing so.) Undo a merge or pull:: + @@ -189,18 +189,18 @@ $ git reset --hard ORIG_HEAD <4> ------------ + <1> Try to update from the upstream resulted in a lot of -conflicts; you were not ready to spend a lot of time merging -right now, so you decide to do that later. + conflicts; you were not ready to spend a lot of time merging + right now, so you decide to do that later. <2> "pull" has not made merge commit, so `git reset --hard` -which is a synonym for `git reset --hard HEAD` clears the mess -from the index file and the working tree. + which is a synonym for `git reset --hard HEAD` clears the mess + from the index file and the working tree. <3> Merge a topic branch into the current branch, which resulted -in a fast-forward. + in a fast-forward. <4> But you decided that the topic branch is not ready for public -consumption yet. "pull" or "merge" always leaves the original -tip of the current branch in `ORIG_HEAD`, so resetting hard to it -brings your index file and the working tree back to that state, -and resets the tip of the branch to that commit. + consumption yet. "pull" or "merge" always leaves the original + tip of the current branch in `ORIG_HEAD`, so resetting hard to it + brings your index file and the working tree back to that state, + and resets the tip of the branch to that commit. Undo a merge or pull inside a dirty working tree:: + @@ -214,14 +214,14 @@ $ git reset --merge ORIG_HEAD <2> ------------ + <1> Even if you may have local modifications in your -working tree, you can safely say `git pull` when you know -that the change in the other branch does not overlap with -them. + working tree, you can safely say `git pull` when you know + that the change in the other branch does not overlap with + them. <2> After inspecting the result of the merge, you may find -that the change in the other branch is unsatisfactory. Running -`git reset --hard ORIG_HEAD` will let you go back to where you -were, but it will discard your local changes, which you do not -want. `git reset --merge` keeps your local changes. + that the change in the other branch is unsatisfactory. Running + `git reset --hard ORIG_HEAD` will let you go back to where you + were, but it will discard your local changes, which you do not + want. `git reset --merge` keeps your local changes. Interrupted workflow:: diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt index 62c6c76..1afe9fc 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@ -33,7 +33,7 @@ This is what linkgit:git-format-patch[1] generates. Most headers and MIME formatting are ignored. 2. The original format used by Greg Kroah-Hartman's 'send_lots_of_email.pl' -script + script + This format expects the first line of the file to contain the "Cc:" value and the "Subject:" of the message as the second line. diff --git a/Documentation/git-show-ref.txt b/Documentation/git-show-ref.txt index d28e615..ab4d271 100644 --- a/Documentation/git-show-ref.txt +++ b/Documentation/git-show-ref.txt @@ -37,8 +37,8 @@ OPTIONS Show the HEAD reference, even if it would normally be filtered out. ---tags:: --heads:: +--tags:: Limit to "refs/heads" and "refs/tags", respectively. These options are not mutually exclusive; when given both, references stored in diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt index d9f422d..861d821 100644 --- a/Documentation/git-status.txt +++ b/Documentation/git-status.txt @@ -197,31 +197,33 @@ codes can be interpreted as follows: Ignored files are not listed, unless `--ignored` option is in effect, in which case `XY` are `!!`. - X Y Meaning - ------------------------------------------------- - [AMD] not updated - M [ MD] updated in index - A [ MD] added to index - D deleted from index - R [ MD] renamed in index - C [ MD] copied in index - [MARC] index and work tree matches - [ MARC] M work tree changed since index - [ MARC] D deleted in work tree - [ D] R renamed in work tree - [ D] C copied in work tree - ------------------------------------------------- - D D unmerged, both deleted - A U unmerged, added by us - U D unmerged, deleted by them - U A unmerged, added by them - D U unmerged, deleted by us - A A unmerged, both added - U U unmerged, both modified - ------------------------------------------------- - ? ? untracked - ! ! ignored - ------------------------------------------------- +.... +X Y Meaning +------------------------------------------------- + [AMD] not updated +M [ MD] updated in index +A [ MD] added to index +D deleted from index +R [ MD] renamed in index +C [ MD] copied in index +[MARC] index and work tree matches +[ MARC] M work tree changed since index +[ MARC] D deleted in work tree +[ D] R renamed in work tree +[ D] C copied in work tree +------------------------------------------------- +D D unmerged, both deleted +A U unmerged, added by us +U D unmerged, deleted by them +U A unmerged, added by them +D U unmerged, deleted by us +A A unmerged, both added +U U unmerged, both modified +------------------------------------------------- +? ? untracked +! ! ignored +------------------------------------------------- +.... Submodules have more state and instead report M the submodule has a different HEAD than @@ -281,14 +283,16 @@ don't recognize. If `--branch` is given, a series of header lines are printed with information about the current branch. - Line Notes - ------------------------------------------------------------ - # branch.oid | (initial) Current commit. - # branch.head | (detached) Current branch. - # branch.upstream If upstream is set. - # branch.ab + - If upstream is set and - the commit is present. - ------------------------------------------------------------ +.... +Line Notes +------------------------------------------------------------ +# branch.oid | (initial) Current commit. +# branch.head | (detached) Current branch. +# branch.upstream If upstream is set. +# branch.ab + - If upstream is set and + the commit is present. +------------------------------------------------------------ +.... ### Changed Tracked Entries @@ -306,56 +310,60 @@ Renamed or copied entries have the following format: 2 - Field Meaning - -------------------------------------------------------- - A 2 character field containing the staged and - unstaged XY values described in the short format, - with unchanged indicated by a "." rather than - a space. - A 4 character field describing the submodule state. - "N..." when the entry is not a submodule. - "S" when the entry is a submodule. - is "C" if the commit changed; otherwise ".". - is "M" if it has tracked changes; otherwise ".". - is "U" if there are untracked changes; otherwise ".". - The octal file mode in HEAD. - The octal file mode in the index. - The octal file mode in the worktree. - The object name in HEAD. - The object name in the index. - The rename or copy score (denoting the percentage - of similarity between the source and target of the - move or copy). For example "R100" or "C75". - The pathname. In a renamed/copied entry, this - is the target path. - When the `-z` option is used, the 2 pathnames are separated - with a NUL (ASCII 0x00) byte; otherwise, a tab (ASCII 0x09) - byte separates them. - The pathname in the commit at HEAD or in the index. - This is only present in a renamed/copied entry, and - tells where the renamed/copied contents came from. - -------------------------------------------------------- +.... +Field Meaning +-------------------------------------------------------- + A 2 character field containing the staged and + unstaged XY values described in the short format, + with unchanged indicated by a "." rather than + a space. + A 4 character field describing the submodule state. + "N..." when the entry is not a submodule. + "S" when the entry is a submodule. + is "C" if the commit changed; otherwise ".". + is "M" if it has tracked changes; otherwise ".". + is "U" if there are untracked changes; otherwise ".". + The octal file mode in HEAD. + The octal file mode in the index. + The octal file mode in the worktree. + The object name in HEAD. + The object name in the index. + The rename or copy score (denoting the percentage + of similarity between the source and target of the + move or copy). For example "R100" or "C75". + The pathname. In a renamed/copied entry, this + is the target path. + When the `-z` option is used, the 2 pathnames are separated + with a NUL (ASCII 0x00) byte; otherwise, a tab (ASCII 0x09) + byte separates them. + The pathname in the commit at HEAD or in the index. + This is only present in a renamed/copied entry, and + tells where the renamed/copied contents came from. +-------------------------------------------------------- +.... Unmerged entries have the following format; the first character is a "u" to distinguish from ordinary changed entries. u

- Field Meaning - -------------------------------------------------------- - A 2 character field describing the conflict type - as described in the short format. - A 4 character field describing the submodule state - as described above. - The octal file mode in stage 1. - The octal file mode in stage 2. - The octal file mode in stage 3. - The octal file mode in the worktree. -

The object name in stage 1. -

The object name in stage 2. -

The object name in stage 3. - The pathname. - -------------------------------------------------------- +.... +Field Meaning +-------------------------------------------------------- + A 2 character field describing the conflict type + as described in the short format. + A 4 character field describing the submodule state + as described above. + The octal file mode in stage 1. + The octal file mode in stage 2. + The octal file mode in stage 3. + The octal file mode in the worktree. +

The object name in stage 1. +

The object name in stage 2. +

The object name in stage 3. + The pathname. +-------------------------------------------------------- +.... ### Other Items diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt index f2d644e..a74e7b9 100644 --- a/Documentation/git-tag.txt +++ b/Documentation/git-tag.txt @@ -237,16 +237,16 @@ your repository directly), then others will have already seen the old tag. In that case you can do one of two things: . The sane thing. -Just admit you screwed up, and use a different name. Others have -already seen one tag-name, and if you keep the same name, you -may be in the situation that two people both have "version X", -but they actually have 'different' "X"'s. So just call it "X.1" -and be done with it. + Just admit you screwed up, and use a different name. Others have + already seen one tag-name, and if you keep the same name, you + may be in the situation that two people both have "version X", + but they actually have 'different' "X"'s. So just call it "X.1" + and be done with it. . The insane thing. -You really want to call the new version "X" too, 'even though' -others have already seen the old one. So just use 'git tag -f' -again, as if you hadn't already published the old one. + You really want to call the new version "X" too, 'even though' + others have already seen the old one. So just use 'git tag -f' + again, as if you hadn't already published the old one. However, Git does *not* (and it should not) change tags behind users back. So if somebody already got the old tag, doing a diff --git a/Documentation/git-upload-pack.txt b/Documentation/git-upload-pack.txt index 998f52d..9822c1e 100644 --- a/Documentation/git-upload-pack.txt +++ b/Documentation/git-upload-pack.txt @@ -22,7 +22,6 @@ The UI for the protocol is on the 'git fetch-pack' side, and the program pair is meant to be used to pull updates from a remote repository. For push operations, see 'git send-pack'. - OPTIONS ------- diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index b8392fc..9b41f81 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -124,7 +124,9 @@ 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 `core.autocrlf` overrides `core.eol` +Note that setting `core.autocrlf` to `true` or `input` overrides +`core.eol` (see the definitions of those options in +linkgit:git-config[1]). Set:: @@ -344,7 +346,9 @@ automatic line ending conversion based on your platform. Use the following attributes if your '*.ps1' files are UTF-16 little endian encoded without BOM and you want Git to use Windows line endings -in the working directory. Please note, it is highly recommended to +in the working directory (use `UTF-16-LE-BOM` instead of `UTF-16LE` if +you want UTF-16 little endian with BOM). +Please note, it is highly recommended to explicitly define the line endings with `eol` if the `working-tree-encoding` attribute is used to avoid ambiguity. diff --git a/Documentation/gitdiffcore.txt b/Documentation/gitdiffcore.txt index c0a60f3..c970d9f 100644 --- a/Documentation/gitdiffcore.txt +++ b/Documentation/gitdiffcore.txt @@ -242,7 +242,8 @@ textual diff has an added or a deleted line that matches the given regular expression. This means that it will detect in-file (or what rename-detection considers the same file) moves, which is noise. The implementation runs diff twice and greps, and this can be quite -expensive. +expensive. To speed things up binary files without textconv filters +will be ignored. When `-S` or `-G` are used without `--pickaxe-all`, only filepairs that match their respective criterion are kept in the output. When diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt index 164995d..312b6f9 100644 --- a/Documentation/gitmodules.txt +++ b/Documentation/gitmodules.txt @@ -44,8 +44,9 @@ submodule..update:: submodule init` to initialize the configuration variable of the same name. Allowed values here are 'checkout', 'rebase', 'merge' or 'none'. See description of 'update' command in - linkgit:git-submodule[1] for their meaning. For security - reasons, the '!command' form is not accepted here. + linkgit:git-submodule[1] for their meaning. Note that the + '!command' form is intentionally ignored here for security + reasons. submodule..branch:: A remote branch name for tracking updates in the upstream submodule. diff --git a/Documentation/gitweb.conf.txt b/Documentation/gitweb.conf.txt index c0a326e..92535db 100644 --- a/Documentation/gitweb.conf.txt +++ b/Documentation/gitweb.conf.txt @@ -207,8 +207,8 @@ subsection on linkgit:gitweb[1] manpage. $strict_export:: Only allow viewing of repositories also shown on the overview page. - This for example makes `$gitweb_export_ok` file decide if repository is - available and not only if it is shown. If `$gitweb_list` points to + This for example makes `$export_ok` file decide if repository is + available and not only if it is shown. If `$projects_list` points to file with list of project, only those repositories listed would be available for gitweb. Can be set during building gitweb via `GITWEB_STRICT_EXPORT`. By default this variable is not set, which @@ -684,7 +684,7 @@ compressed tar archive) and "zip"; please consult gitweb sources for a definitive list. By default only "tgz" is offered. + This feature can be configured on a per-repository basis via -repository's `gitweb.blame` configuration variable, which contains +repository's `gitweb.snapshot` configuration variable, which contains a comma separated list of formats or "none" to disable snapshots. Unknown values are ignored. diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt index 0d2aa48..023ca95 100644 --- a/Documentation/glossary-content.txt +++ b/Documentation/glossary-content.txt @@ -404,6 +404,8 @@ these forms: - "`!ATTR`" requires that the attribute `ATTR` be unspecified. + +Note that when matching against a tree object, attributes are still +obtained from working tree, not from the given tree object. exclude;; After a path matches any non-exclude pathspec, it will be run diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt index 417b638..7bfffae 100644 --- a/Documentation/pretty-formats.txt +++ b/Documentation/pretty-formats.txt @@ -134,6 +134,8 @@ The placeholders are: - '%cI': committer date, strict ISO 8601 format - '%d': ref names, like the --decorate option of linkgit:git-log[1] - '%D': ref names without the " (", ")" wrapping. +- '%S': ref name given on the command line by which the commit was reached + (like `git log --source`), only works with `git log` - '%e': encoding - '%s': subject - '%f': sanitized subject line, suitable for a filename @@ -181,7 +183,7 @@ endif::git-rev-list[] `color.diff`, `color.ui`, or `--color`, and respecting the `auto` settings of the former if we are going to a terminal). `%C(auto,...)` is accepted as a historical synonym for the default (e.g., - `%C(auto,red)`). Specifying `%C(always,...) will show the colors + `%C(auto,red)`). Specifying `%C(always,...)` will show the colors even when color is not otherwise enabled (though consider just using `--color=always` to enable color for the whole output, including this format and anything else git might color). `auto` diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index bab5f50..cad711c 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@ -13,8 +13,6 @@ has a line that matches ``), unless otherwise noted. Note that these are applied before commit ordering and formatting options, such as `--reverse`. --- - -:: -n :: --max-count=:: @@ -272,13 +270,13 @@ depending on a few rules: + -- 1. If the starting point is specified as `ref@{Nth}`, show the index -format. + format. + 2. If the starting point was specified as `ref@{now}`, show the -timestamp format. + timestamp format. + 3. If neither was used, but `--date` was given on the command line, show -the timestamp in the format requested by `--date`. + the timestamp in the format requested by `--date`. + 4. Otherwise, show the index format. -- @@ -308,8 +306,6 @@ ifdef::git-rev-list[] `
` text will be printed with each progress update. endif::git-rev-list[] --- - History Simplification ~~~~~~~~~~~~~~~~~~~~~~ @@ -734,8 +730,13 @@ specification contained in . + The form '--filter=tree:' omits all blobs and trees whose depth from the root tree is >= (minimum depth if an object is located -at multiple depths in the commits traversed). Currently, only =0 -is supported, which omits all blobs and trees. +at multiple depths in the commits traversed). =0 will not include +any trees or blobs unless included explicitly in the command-line (or +standard input when --stdin is used). =1 will include only the +tree and blobs which are referenced directly by a commit reachable from + or an explicitly-given object. =2 is like =1 +while also including trees and blobs one more level removed from an +explicitly-given commit or tree. --no-filter:: Turn off any previous `--filter=` argument. @@ -835,6 +836,13 @@ Note that the `-local` option does not affect the seconds-since-epoch value (which is always measured in UTC), but does switch the accompanying timezone value. + +`--date=human` shows the timezone if the timezone does not match the +current time-zone, and doesn't print the whole date if that matches +(ie skip printing year for dates that are "this year", but also skip +the whole date itself if it's in the last few days and we can just say +what weekday it was). For older dates the hour and minute is also +omitted. ++ `--date=unix` shows the date as a Unix epoch timestamp (seconds since 1970). As with `--raw`, this is always in UTC and therefore `-local` has no effect. diff --git a/Documentation/technical/api-oid-array.txt b/Documentation/technical/api-oid-array.txt index 9febfb1..c97428c 100644 --- a/Documentation/technical/api-oid-array.txt +++ b/Documentation/technical/api-oid-array.txt @@ -48,6 +48,11 @@ Functions is not sorted, this function has the side effect of sorting it. +`oid_array_filter`:: + Apply the callback function `want` to each entry in the array, + retaining only the entries for which the function returns true. + Preserve the order of the entries that are retained. + Examples -------- diff --git a/Documentation/technical/commit-graph-format.txt b/Documentation/technical/commit-graph-format.txt index cc0474b..16452a0 100644 --- a/Documentation/technical/commit-graph-format.txt +++ b/Documentation/technical/commit-graph-format.txt @@ -76,7 +76,7 @@ CHUNK DATA: of the ith commit. Stores value 0x7000000 if no parent in that position. If there are more than two parents, the second value has its most-significant bit on and the other bits store an array - position into the Large Edge List chunk. + position into the Extra Edge List chunk. * The next 8 bytes store the generation number of the commit and the commit time in seconds since EPOCH. The generation number uses the higher 30 bits of the first 4 bytes, while the commit @@ -84,7 +84,7 @@ CHUNK DATA: 2 bits of the lowest byte, storing the 33rd and 34th bit of the commit time. - Large Edge List (ID: {'E', 'D', 'G', 'E'}) [Optional] + Extra Edge List (ID: {'E', 'D', 'G', 'E'}) [Optional] This list of 4-byte values store the second through nth parents for all octopus merges. The second parent value in the commit data stores an array position within this list along with the most-significant bit diff --git a/Documentation/technical/pack-protocol.txt b/Documentation/technical/pack-protocol.txt index 6ac774d..7a2375a 100644 --- a/Documentation/technical/pack-protocol.txt +++ b/Documentation/technical/pack-protocol.txt @@ -22,6 +22,16 @@ protocol-common.txt. When the grammar indicate `PKT-LINE(...)`, unless otherwise noted the usual pkt-line LF rules apply: the sender SHOULD include a LF, but the receiver MUST NOT complain if it is not present. +An error packet is a special pkt-line that contains an error string. + +---- + error-line = PKT-LINE("ERR" SP explanation-text) +---- + +Throughout the protocol, where `PKT-LINE(...)` is expected, an error packet MAY +be sent. Once this packet is sent by a client or a server, the data transfer +process defined in this protocol is terminated. + Transports ---------- There are three transports over which the packfile protocol is @@ -89,13 +99,6 @@ process on the server side over the Git protocol is this: "0039git-upload-pack /schacon/gitbook.git\0host=example.com\0" | nc -v example.com 9418 -If the server refuses the request for some reasons, it could abort -gracefully with an error message. - ----- - error-line = PKT-LINE("ERR" SP explanation-text) ----- - SSH Transport ------------- @@ -398,12 +401,11 @@ from the client). Then the server will start sending its packfile data. ---- - server-response = *ack_multi ack / nak / error-line + server-response = *ack_multi ack / nak ack_multi = PKT-LINE("ACK" SP obj-id ack_status) ack_status = "continue" / "common" / "ready" ack = PKT-LINE("ACK" SP obj-id) nak = PKT-LINE("NAK") - error-line = PKT-LINE("ERR" SP explanation-text) ---- A simple clone may look like this (with no 'have' lines): diff --git a/Documentation/technical/partial-clone.txt b/Documentation/technical/partial-clone.txt index 1ef66bd..896c7b3 100644 --- a/Documentation/technical/partial-clone.txt +++ b/Documentation/technical/partial-clone.txt @@ -114,7 +114,7 @@ their ".pack" and ".idx" files. that it has, either because the local repository has that object in one of its promisor packfiles, or because another promisor object refers to it. + -When Git encounters a missing object, Git can see if it a promisor object +When Git encounters a missing object, Git can see if it is a promisor object and handle it appropriately. If not, Git can report a corruption. + This means that there is no need for the client to explicitly maintain an diff --git a/Documentation/technical/protocol-v2.txt b/Documentation/technical/protocol-v2.txt index 09e4e02..ead85ce 100644 --- a/Documentation/technical/protocol-v2.txt +++ b/Documentation/technical/protocol-v2.txt @@ -296,7 +296,13 @@ included in the client's request: Request that various objects from the packfile be omitted using one of several filtering techniques. These are intended for use with partial clone and partial fetch operations. See - `rev-list` for possible "filter-spec" values. + `rev-list` for possible "filter-spec" values. When communicating + with other processes, senders SHOULD translate scaled integers + (e.g. "1k") into a fully-expanded form (e.g. "1024") to aid + interoperability with older receivers that may not understand + newly-invented scaling suffixes. However, receivers SHOULD + accept the following suffixes: 'k', 'm', and 'g' for 1024, + 1048576, and 1073741824, respectively. If the 'ref-in-want' feature is advertised, the following argument can be included in the client's request as well as the potential addition of @@ -307,6 +313,16 @@ the 'wanted-refs' section in the server's response as explained below. particular ref, where is the full name of a ref on the server. +If the 'sideband-all' feature is advertised, the following argument can be +included in the client's request: + + sideband-all + Instruct the server to send the whole response multiplexed, not just + the packfile section. All non-flush and non-delim PKT-LINE in the + response (not only in the packfile section) will then start with a byte + indicating its sideband (1, 2, or 3), and the server may send "0005\2" + (a PKT-LINE of sideband 2 with no payload) as a keepalive packet. + The response of `fetch` is broken into a number of sections separated by delimiter packets (0001), with each section beginning with its section header. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index de22ee7..13f835f 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.20.4 +DEF_VER=v2.21.0 LF=' ' diff --git a/Makefile b/Makefile index 1a44c81..c524094 100644 --- a/Makefile +++ b/Makefile @@ -186,6 +186,12 @@ all:: # in one call to the platform's SHA1_Update(). e.g. APPLE_COMMON_CRYPTO # wants 'SHA1_MAX_BLOCK_SIZE=1024L*1024L*1024L' defined. # +# Define BLK_SHA256 to use the built-in SHA-256 routines. +# +# Define GCRYPT_SHA256 to use the SHA-256 routines in libgcrypt. +# +# Define OPENSSL_SHA256 to use the SHA-256 routines in OpenSSL. +# # Define NEEDS_CRYPTO_WITH_SSL if you need -lcrypto when using -lssl (Darwin). # # Define NEEDS_SSL_WITH_CRYPTO if you need -lssl when using -lcrypto (Darwin). @@ -253,6 +259,10 @@ all:: # Define OLD_ICONV if your library has an old iconv(), where the second # (input buffer pointer) parameter is declared with type (const char **). # +# Define ICONV_OMITS_BOM if your iconv implementation does not write a +# byte-order mark (BOM) when writing UTF-16 or UTF-32 and always writes in +# big-endian format. +# # Define NO_DEFLATE_BOUND if your zlib does not have deflateBound. # # Define NO_R_TO_GCC_LINKER if your gcc does not like "-R/path/lib" @@ -427,6 +437,8 @@ all:: # # Define HAVE_GETDELIM if your system has the getdelim() function. # +# Define FILENO_IS_A_MACRO if fileno() is a macro, not a real function. +# # Define PAGER_ENV to a SP separated VAR=VAL pairs to define # default environment variables to be passed when a pager is spawned, e.g. # @@ -568,7 +580,11 @@ SPATCH = spatch export TCL_PATH TCLTK_PATH -SPARSE_FLAGS = +# user customisation variable for 'sparse' target +SPARSE_FLAGS ?= +# internal/platform customisation variable for 'sparse' +SP_EXTRA_FLAGS = + SPATCH_FLAGS = --all-includes --patch . @@ -628,7 +644,6 @@ SCRIPT_LIB += git-parse-remote SCRIPT_LIB += git-rebase--am SCRIPT_LIB += git-rebase--common SCRIPT_LIB += git-rebase--preserve-merges -SCRIPT_LIB += git-rebase--merge SCRIPT_LIB += git-sh-setup SCRIPT_LIB += git-sh-i18n @@ -684,6 +699,7 @@ SCRIPTS = $(SCRIPT_SH_INS) \ ETAGS_TARGET = TAGS +FUZZ_OBJS += fuzz-commit-graph.o FUZZ_OBJS += fuzz-pack-headers.o FUZZ_OBJS += fuzz-pack-idx.o @@ -724,7 +740,10 @@ TEST_BUILTINS_OBJS += test-dump-split-index.o TEST_BUILTINS_OBJS += test-dump-untracked-cache.o TEST_BUILTINS_OBJS += test-example-decorate.o TEST_BUILTINS_OBJS += test-genrandom.o +TEST_BUILTINS_OBJS += test-genzeros.o +TEST_BUILTINS_OBJS += test-hash.o TEST_BUILTINS_OBJS += test-hashmap.o +TEST_BUILTINS_OBJS += test-hash-speed.o TEST_BUILTINS_OBJS += test-index-version.o TEST_BUILTINS_OBJS += test-json-writer.o TEST_BUILTINS_OBJS += test-lazy-init-name-hash.o @@ -747,6 +766,7 @@ TEST_BUILTINS_OBJS += test-run-command.o TEST_BUILTINS_OBJS += test-scrap-cache-tree.o TEST_BUILTINS_OBJS += test-sha1.o TEST_BUILTINS_OBJS += test-sha1-array.o +TEST_BUILTINS_OBJS += test-sha256.o TEST_BUILTINS_OBJS += test-sigchain.o TEST_BUILTINS_OBJS += test-strcmp-offset.o TEST_BUILTINS_OBJS += test-string-list.o @@ -754,6 +774,7 @@ TEST_BUILTINS_OBJS += test-submodule-config.o TEST_BUILTINS_OBJS += test-submodule-nested-repo-config.o TEST_BUILTINS_OBJS += test-subprocess.o TEST_BUILTINS_OBJS += test-urlmatch-normalization.o +TEST_BUILTINS_OBJS += test-xml-encode.o TEST_BUILTINS_OBJS += test-wildmatch.o TEST_BUILTINS_OBJS += test-windows-named-pipe.o TEST_BUILTINS_OBJS += test-write-cache.o @@ -1401,6 +1422,9 @@ ifndef NO_ICONV EXTLIBS += $(ICONV_LINK) -liconv endif endif +ifdef ICONV_OMITS_BOM + BASIC_CFLAGS += -DICONV_OMITS_BOM +endif ifdef NEEDS_LIBGEN EXTLIBS += -lgen endif @@ -1646,6 +1670,19 @@ endif endif endif +ifdef OPENSSL_SHA256 + EXTLIBS += $(LIB_4_CRYPTO) + BASIC_CFLAGS += -DSHA256_OPENSSL +else +ifdef GCRYPT_SHA256 + BASIC_CFLAGS += -DSHA256_GCRYPT + EXTLIBS += -lgcrypt +else + LIB_OBJS += sha256/block/sha256.o + BASIC_CFLAGS += -DSHA256_BLK +endif +endif + ifdef SHA1_MAX_BLOCK_SIZE LIB_OBJS += compat/sha1-chunked.o BASIC_CFLAGS += -DSHA1_MAX_BLOCK_SIZE="$(SHA1_MAX_BLOCK_SIZE)" @@ -1773,6 +1810,11 @@ ifdef HAVE_WPGMPTR BASIC_CFLAGS += -DHAVE_WPGMPTR endif +ifdef FILENO_IS_A_MACRO + COMPAT_CFLAGS += -DFILENO_IS_A_MACRO + COMPAT_OBJS += compat/fileno.o +endif + ifeq ($(TCLTK_PATH),) NO_TCLTK = NoThanks endif @@ -2347,10 +2389,10 @@ gettext.sp gettext.s gettext.o: GIT-PREFIX gettext.sp gettext.s gettext.o: EXTRA_CPPFLAGS = \ -DGIT_LOCALE_PATH='"$(localedir_relative_SQ)"' -http-push.sp http.sp http-walker.sp remote-curl.sp imap-send.sp: SPARSE_FLAGS += \ +http-push.sp http.sp http-walker.sp remote-curl.sp imap-send.sp: SP_EXTRA_FLAGS += \ -DCURL_DISABLE_TYPECHECK -pack-revindex.sp: SPARSE_FLAGS += -Wno-memcpy-max-count +pack-revindex.sp: SP_EXTRA_FLAGS += -Wno-memcpy-max-count ifdef NO_EXPAT http-walker.sp http-walker.s http-walker.o: EXTRA_CPPFLAGS = -DNO_EXPAT @@ -2364,7 +2406,7 @@ endif ifdef USE_NED_ALLOCATOR compat/nedmalloc/nedmalloc.sp compat/nedmalloc/nedmalloc.o: EXTRA_CPPFLAGS = \ -DNDEBUG -DREPLACE_SYSTEM_ALLOCATOR -compat/nedmalloc/nedmalloc.sp: SPARSE_FLAGS += -Wno-non-pointer-null +compat/nedmalloc/nedmalloc.sp: SP_EXTRA_FLAGS += -Wno-non-pointer-null endif git-%$X: %.o GIT-LDFLAGS $(GITLIBS) @@ -2688,7 +2730,7 @@ SP_OBJ = $(patsubst %.o,%.sp,$(C_OBJ)) $(SP_OBJ): %.sp: %.c GIT-CFLAGS FORCE $(QUIET_SP)cgcc -no-compile $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) \ - $(SPARSE_FLAGS) $< + $(SPARSE_FLAGS) $(SP_EXTRA_FLAGS) $< .PHONY: sparse $(SP_OBJ) sparse: $(SP_OBJ) @@ -2926,6 +2968,16 @@ rpm:: @false .PHONY: rpm +artifacts-tar:: $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS) \ + GIT-BUILD-OPTIONS $(TEST_PROGRAMS) $(test_bindir_programs) \ + $(NO_INSTALL) $(MOFILES) + $(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1) \ + SHELL_PATH='$(SHELL_PATH_SQ)' PERL_PATH='$(PERL_PATH_SQ)' + test -n "$(ARTIFACTS_DIRECTORY)" + mkdir -p "$(ARTIFACTS_DIRECTORY)" + $(TAR) czf "$(ARTIFACTS_DIRECTORY)/artifacts.tar.gz" $^ templates/blt/ +.PHONY: artifacts-tar + htmldocs = git-htmldocs-$(GIT_VERSION) manpages = git-manpages-$(GIT_VERSION) .PHONY: dist-doc distclean @@ -3077,6 +3129,11 @@ coverage-test: coverage-clean-results coverage-compile $(MAKE) CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" \ DEFAULT_TEST_TARGET=test -j1 test +coverage-prove: coverage-clean-results coverage-compile + $(MAKE) CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" \ + DEFAULT_TEST_TARGET=prove GIT_PROVE_OPTS="$(GIT_PROVE_OPTS) -j1" \ + -j1 test + coverage-report: $(QUIET_GCOV)for dir in $(object_dirs); do \ $(GCOV) $(GCOVFLAGS) --object-directory=$$dir $$dir*.c || exit; \ @@ -3103,7 +3160,7 @@ cover_db_html: cover_db # An example command to build against libFuzzer from LLVM 4.0.0: # # make CC=clang CXX=clang++ \ -# FUZZ_CXXFLAGS="-fsanitize-coverage=trace-pc-guard -fsanitize=address" \ +# CFLAGS="-fsanitize-coverage=trace-pc-guard -fsanitize=address" \ # LIB_FUZZING_ENGINE=/usr/lib/llvm-4.0/lib/libFuzzer.a \ # fuzz-all # diff --git a/README.md b/README.md index f920a42..88f1261 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Build Status](https://dev.azure.com/git/git/_apis/build/status/git.git)](https://dev.azure.com/git/git/_build/latest?definitionId=11) + Git - fast, scalable, distributed revision control system ========================================================= diff --git a/RelNotes b/RelNotes index 0c3010e..31e2135 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.20.4.txt \ No newline at end of file +Documentation/RelNotes/2.21.0.txt \ No newline at end of file diff --git a/advice.c b/advice.c index 5f35656..567209a 100644 --- a/advice.c +++ b/advice.c @@ -9,6 +9,7 @@ int advice_push_non_ff_matching = 1; int advice_push_already_exists = 1; int advice_push_fetch_first = 1; int advice_push_needs_force = 1; +int advice_push_unqualified_ref_name = 1; int advice_status_hints = 1; int advice_status_u_option = 1; int advice_commit_before_merge = 1; @@ -63,6 +64,7 @@ static struct { { "pushAlreadyExists", &advice_push_already_exists }, { "pushFetchFirst", &advice_push_fetch_first }, { "pushNeedsForce", &advice_push_needs_force }, + { "pushUnqualifiedRefName", &advice_push_unqualified_ref_name }, { "statusHints", &advice_status_hints }, { "statusUoption", &advice_status_u_option }, { "commitBeforeMerge", &advice_commit_before_merge }, diff --git a/advice.h b/advice.h index 696bf0e..f875f8c 100644 --- a/advice.h +++ b/advice.h @@ -9,6 +9,7 @@ extern int advice_push_non_ff_matching; extern int advice_push_already_exists; extern int advice_push_fetch_first; extern int advice_push_needs_force; +extern int advice_push_unqualified_ref_name; extern int advice_status_hints; extern int advice_status_u_option; extern int advice_commit_before_merge; diff --git a/alias.c b/alias.c index a7e4e57..c471538 100644 --- a/alias.c +++ b/alias.c @@ -47,8 +47,8 @@ void list_aliases(struct string_list *list) #define SPLIT_CMDLINE_BAD_ENDING 1 #define SPLIT_CMDLINE_UNCLOSED_QUOTE 2 static const char *split_cmdline_errors[] = { - "cmdline ends with \\", - "unclosed quote" + N_("cmdline ends with \\"), + N_("unclosed quote") }; int split_cmdline(char *cmdline, const char ***argv) diff --git a/alloc.c b/alloc.c index e7aa81b..1c64c4d 100644 --- a/alloc.c +++ b/alloc.c @@ -99,18 +99,23 @@ void *alloc_object_node(struct repository *r) return obj; } -unsigned int alloc_commit_index(struct repository *r) +static unsigned int alloc_commit_index(struct repository *r) { return r->parsed_objects->commit_count++; } -void *alloc_commit_node(struct repository *r) +void init_commit_node(struct repository *r, struct commit *c) { - struct commit *c = alloc_node(r->parsed_objects->commit_state, sizeof(struct commit)); c->object.type = OBJ_COMMIT; c->index = alloc_commit_index(r); c->graph_pos = COMMIT_NOT_FROM_GRAPH; c->generation = GENERATION_NUMBER_INFINITY; +} + +void *alloc_commit_node(struct repository *r) +{ + struct commit *c = alloc_node(r->parsed_objects->commit_state, sizeof(struct commit)); + init_commit_node(r, c); return c; } diff --git a/alloc.h b/alloc.h index ba356ed..ed1071c 100644 --- a/alloc.h +++ b/alloc.h @@ -9,11 +9,11 @@ struct repository; void *alloc_blob_node(struct repository *r); void *alloc_tree_node(struct repository *r); +void init_commit_node(struct repository *r, struct commit *c); void *alloc_commit_node(struct repository *r); void *alloc_tag_node(struct repository *r); void *alloc_object_node(struct repository *r); void alloc_report(struct repository *r); -unsigned int alloc_commit_index(struct repository *r); struct alloc_state *allocate_alloc_state(void); void clear_alloc_state(struct alloc_state *s); diff --git a/apply.c b/apply.c index 01793d6..892ede5 100644 --- a/apply.c +++ b/apply.c @@ -467,7 +467,6 @@ static char *squash_slash(char *name) static char *find_name_gnu(struct apply_state *state, const char *line, - const char *def, int p_value) { struct strbuf name = STRBUF_INIT; @@ -714,7 +713,7 @@ static char *find_name(struct apply_state *state, int terminate) { if (*line == '"') { - char *name = find_name_gnu(state, line, def, p_value); + char *name = find_name_gnu(state, line, p_value); if (name) return name; } @@ -731,7 +730,7 @@ static char *find_name_traditional(struct apply_state *state, size_t date_len; if (*line == '"') { - char *name = find_name_gnu(state, line, def, p_value); + char *name = find_name_gnu(state, line, p_value); if (name) return name; } @@ -3183,7 +3182,7 @@ static int apply_binary(struct apply_state *state, return 0; /* deletion patch */ } - if (has_sha1_file(oid.hash)) { + if (has_object_file(&oid)) { /* We already have the postimage */ enum object_type type; unsigned long size; @@ -3352,7 +3351,8 @@ static int checkout_target(struct index_state *istate, costate.refresh_cache = 1; costate.istate = istate; - if (checkout_entry(ce, &costate, NULL) || lstat(ce->name, st)) + if (checkout_entry(ce, &costate, NULL, NULL) || + lstat(ce->name, st)) return error(_("cannot checkout %s"), ce->name); return 0; } @@ -4019,7 +4019,7 @@ static int read_apply_cache(struct apply_state *state) return read_index_from(state->repo->index, state->index_file, get_git_dir()); else - return read_index(state->repo->index); + return repo_read_index(state->repo); } /* This function tries to read the object name from the current index */ @@ -4712,7 +4712,8 @@ static int apply_patch(struct apply_state *state, state->index_file, LOCK_DIE_ON_ERROR); else - hold_locked_index(&state->lock_file, LOCK_DIE_ON_ERROR); + repo_hold_locked_index(state->repo, &state->lock_file, + LOCK_DIE_ON_ERROR); } if (state->check_index && read_apply_cache(state) < 0) { diff --git a/archive-tar.c b/archive-tar.c index a58e1a8..4aabd56 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -142,7 +142,7 @@ static int stream_blocked(const struct object_id *oid) * string and appends it to a struct strbuf. */ static void strbuf_append_ext_header(struct strbuf *sb, const char *keyword, - const char *value, unsigned int valuelen) + const char *value, unsigned int valuelen) { int len, tmp; diff --git a/archive.c b/archive.c index fd556c2..1f98324 100644 --- a/archive.c +++ b/archive.c @@ -36,8 +36,8 @@ void init_archivers(void) } static void format_subst(const struct commit *commit, - const char *src, size_t len, - struct strbuf *buf) + const char *src, size_t len, + struct strbuf *buf) { char *to_free = NULL; struct strbuf fmt = STRBUF_INIT; @@ -285,7 +285,8 @@ int write_archive_entries(struct archiver_args *args, git_attr_set_direction(GIT_ATTR_INDEX); } - err = read_tree_recursive(args->tree, "", 0, 0, &args->pathspec, + err = read_tree_recursive(args->repo, args->tree, "", + 0, 0, &args->pathspec, queue_or_write_archive_entry, &context); if (err == READ_TREE_RECURSIVE) @@ -346,7 +347,8 @@ static int path_exists(struct archiver_args *args, const char *path) ctx.args = args; parse_pathspec(&ctx.pathspec, 0, 0, "", paths); ctx.pathspec.recursive = 1; - ret = read_tree_recursive(args->tree, "", 0, 0, &ctx.pathspec, + ret = read_tree_recursive(args->repo, args->tree, "", + 0, 0, &ctx.pathspec, reject_entry, &ctx); clear_pathspec(&ctx.pathspec); return ret != 0; @@ -391,12 +393,12 @@ static void parse_treeish_arg(const char **argv, int refnamelen = colon - name; if (!dwim_ref(name, refnamelen, &oid, &ref)) - die("no such ref: %.*s", refnamelen, name); + die(_("no such ref: %.*s"), refnamelen, name); free(ref); } if (get_oid(name, &oid)) - die("Not a valid object name"); + die(_("not a valid object name: %s"), name); commit = lookup_commit_reference_gently(ar_args->repo, &oid, 1); if (commit) { @@ -409,7 +411,7 @@ static void parse_treeish_arg(const char **argv, tree = parse_tree_indirect(&oid); if (tree == NULL) - die("not a tree object"); + die(_("not a tree object: %s"), oid_to_hex(&oid)); if (prefix) { struct object_id tree_oid; @@ -419,7 +421,7 @@ static void parse_treeish_arg(const char **argv, err = get_tree_entry(&tree->object.oid, prefix, &tree_oid, &mode); if (err || !S_ISDIR(mode)) - die("current working directory is untracked"); + die(_("current working directory is untracked")); tree = parse_tree_indirect(&tree_oid); } diff --git a/attr.c b/attr.c index eaece66..fdd110b 100644 --- a/attr.c +++ b/attr.c @@ -7,7 +7,6 @@ * an insanely large number of attributes. */ -#define NO_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "config.h" #include "exec-cmd.h" @@ -366,8 +365,8 @@ static struct match_attr *parse_attr_line(const char *line, const char *src, if (strlen(ATTRIBUTE_MACRO_PREFIX) < namelen && starts_with(name, ATTRIBUTE_MACRO_PREFIX)) { if (!macro_ok) { - fprintf(stderr, "%s not allowed: %s:%d\n", - name, src, lineno); + fprintf_ln(stderr, _("%s not allowed: %s:%d"), + name, src, lineno); goto fail_return; } is_macro = 1; @@ -1092,7 +1091,7 @@ static void collect_some_attrs(const struct index_state *istate, const char *path, struct attr_check *check) { - int i, pathlen, rem, dirlen; + int pathlen, rem, dirlen; const char *cp, *last_slash = NULL; int basename_offset; @@ -1113,20 +1112,6 @@ static void collect_some_attrs(const struct index_state *istate, all_attrs_init(&g_attr_hashmap, check); determine_macros(check->all_attrs, check->stack); - if (check->nr) { - rem = 0; - for (i = 0; i < check->nr; i++) { - int n = check->items[i].attr->attr_nr; - struct all_attrs_item *item = &check->all_attrs[n]; - if (item->macro) { - item->value = ATTR__UNSET; - rem++; - } - } - if (rem == check->nr) - return; - } - rem = check->all_attrs_nr; fill(path, pathlen, basename_offset, check->stack, check->all_attrs, rem); } diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 0000000..c329b72 --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,387 @@ +resources: +- repo: self + fetchDepth: 1 + +jobs: +- job: windows_build + displayName: Windows Build + condition: succeeded() + pool: Hosted + timeoutInMinutes: 240 + steps: + - powershell: | + if ("$GITFILESHAREPWD" -ne "" -and "$GITFILESHAREPWD" -ne "`$`(gitfileshare.pwd)") { + net use s: \\gitfileshare.file.core.windows.net\test-cache "$GITFILESHAREPWD" /user:AZURE\gitfileshare /persistent:no + cmd /c mklink /d "$(Build.SourcesDirectory)\test-cache" S:\ + } + displayName: 'Mount test-cache' + env: + GITFILESHAREPWD: $(gitfileshare.pwd) + - powershell: | + $urlbase = "https://dev.azure.com/git-for-windows/git/_apis/build/builds" + $id = ((Invoke-WebRequest -UseBasicParsing "${urlbase}?definitions=22&statusFilter=completed&resultFilter=succeeded&`$top=1").content | ConvertFrom-JSON).value[0].id + $downloadUrl = ((Invoke-WebRequest -UseBasicParsing "${urlbase}/$id/artifacts").content | ConvertFrom-JSON).value[1].resource.downloadUrl + (New-Object Net.WebClient).DownloadFile($downloadUrl,"git-sdk-64-minimal.zip") + Expand-Archive git-sdk-64-minimal.zip -DestinationPath . -Force + Remove-Item git-sdk-64-minimal.zip + + # Let Git ignore the SDK and the test-cache + "/git-sdk-64-minimal/`n/test-cache/`n" | Out-File -NoNewLine -Encoding ascii -Append "$(Build.SourcesDirectory)\.git\info\exclude" + displayName: 'Download git-sdk-64-minimal' + - powershell: | + & git-sdk-64-minimal\usr\bin\bash.exe -lc @" + ci/make-test-artifacts.sh artifacts + "@ + if (!$?) { exit(1) } + displayName: Build + env: + HOME: $(Build.SourcesDirectory) + MSYSTEM: MINGW64 + DEVELOPER: 1 + NO_PERL: 1 + - task: PublishPipelineArtifact@0 + displayName: 'Publish Pipeline Artifact: test artifacts' + inputs: + artifactName: 'windows-artifacts' + targetPath: '$(Build.SourcesDirectory)\artifacts' + - task: PublishPipelineArtifact@0 + displayName: 'Publish Pipeline Artifact: git-sdk-64-minimal' + inputs: + artifactName: 'git-sdk-64-minimal' + targetPath: '$(Build.SourcesDirectory)\git-sdk-64-minimal' + - powershell: | + if ("$GITFILESHAREPWD" -ne "" -and "$GITFILESHAREPWD" -ne "`$`(gitfileshare.pwd)") { + cmd /c rmdir "$(Build.SourcesDirectory)\test-cache" + } + displayName: 'Unmount test-cache' + condition: true + env: + GITFILESHAREPWD: $(gitfileshare.pwd) + +- job: windows_test + displayName: Windows Test + dependsOn: windows_build + condition: succeeded() + pool: Hosted + timeoutInMinutes: 240 + strategy: + parallel: 10 + steps: + - powershell: | + if ("$GITFILESHAREPWD" -ne "" -and "$GITFILESHAREPWD" -ne "`$`(gitfileshare.pwd)") { + net use s: \\gitfileshare.file.core.windows.net\test-cache "$GITFILESHAREPWD" /user:AZURE\gitfileshare /persistent:no + cmd /c mklink /d "$(Build.SourcesDirectory)\test-cache" S:\ + } + displayName: 'Mount test-cache' + env: + GITFILESHAREPWD: $(gitfileshare.pwd) + - task: DownloadPipelineArtifact@0 + displayName: 'Download Pipeline Artifact: test artifacts' + inputs: + artifactName: 'windows-artifacts' + targetPath: '$(Build.SourcesDirectory)' + - task: DownloadPipelineArtifact@0 + displayName: 'Download Pipeline Artifact: git-sdk-64-minimal' + inputs: + artifactName: 'git-sdk-64-minimal' + targetPath: '$(Build.SourcesDirectory)\git-sdk-64-minimal' + - powershell: | + & git-sdk-64-minimal\usr\bin\bash.exe -lc @" + test -f artifacts.tar.gz || { + echo No test artifacts found\; skipping >&2 + exit 0 + } + tar xf artifacts.tar.gz || exit 1 + + # Let Git ignore the SDK and the test-cache + printf '%s\n' /git-sdk-64-minimal/ /test-cache/ >>.git/info/exclude + + ci/run-test-slice.sh `$SYSTEM_JOBPOSITIONINPHASE `$SYSTEM_TOTALJOBSINPHASE || { + ci/print-test-failures.sh + exit 1 + } + "@ + if (!$?) { exit(1) } + displayName: 'Test (parallel)' + env: + HOME: $(Build.SourcesDirectory) + MSYSTEM: MINGW64 + NO_SVN_TESTS: 1 + GIT_TEST_SKIP_REBASE_P: 1 + - powershell: | + if ("$GITFILESHAREPWD" -ne "" -and "$GITFILESHAREPWD" -ne "`$`(gitfileshare.pwd)") { + cmd /c rmdir "$(Build.SourcesDirectory)\test-cache" + } + displayName: 'Unmount test-cache' + condition: true + env: + GITFILESHAREPWD: $(gitfileshare.pwd) + - task: PublishTestResults@2 + displayName: 'Publish Test Results **/TEST-*.xml' + inputs: + mergeTestResults: true + testRunTitle: 'windows' + platform: Windows + publishRunAttachments: false + condition: succeededOrFailed() + - task: PublishBuildArtifacts@1 + displayName: 'Publish trash directories of failed tests' + condition: failed() + inputs: + PathtoPublish: t/failed-test-artifacts + ArtifactName: failed-test-artifacts + +- job: linux_clang + displayName: linux-clang + condition: succeeded() + pool: Hosted Ubuntu 1604 + steps: + - bash: | + test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/test-cache gitfileshare "$GITFILESHAREPWD" "$HOME/test-cache" || exit 1 + + sudo apt-get update && + sudo apt-get -y install git gcc make libssl-dev libcurl4-openssl-dev libexpat-dev tcl tk gettext git-email zlib1g-dev apache2-bin && + + export CC=clang || exit 1 + + ci/install-dependencies.sh || exit 1 + ci/run-build-and-tests.sh || { + ci/print-test-failures.sh + exit 1 + } + + test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || sudo umount "$HOME/test-cache" || exit 1 + displayName: 'ci/run-build-and-tests.sh' + env: + GITFILESHAREPWD: $(gitfileshare.pwd) + - task: PublishTestResults@2 + displayName: 'Publish Test Results **/TEST-*.xml' + inputs: + mergeTestResults: true + testRunTitle: 'linux-clang' + platform: Linux + publishRunAttachments: false + condition: succeededOrFailed() + - task: PublishBuildArtifacts@1 + displayName: 'Publish trash directories of failed tests' + condition: failed() + inputs: + PathtoPublish: t/failed-test-artifacts + ArtifactName: failed-test-artifacts + +- job: linux_gcc + displayName: linux-gcc + condition: succeeded() + pool: Hosted Ubuntu 1604 + steps: + - bash: | + test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/test-cache gitfileshare "$GITFILESHAREPWD" "$HOME/test-cache" || exit 1 + + sudo add-apt-repository ppa:ubuntu-toolchain-r/test && + sudo apt-get update && + sudo apt-get -y install git gcc make libssl-dev libcurl4-openssl-dev libexpat-dev tcl tk gettext git-email zlib1g-dev apache2 language-pack-is git-svn gcc-8 || exit 1 + + ci/install-dependencies.sh || exit 1 + ci/run-build-and-tests.sh || { + ci/print-test-failures.sh + exit 1 + } + + test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || sudo umount "$HOME/test-cache" || exit 1 + displayName: 'ci/run-build-and-tests.sh' + env: + GITFILESHAREPWD: $(gitfileshare.pwd) + - task: PublishTestResults@2 + displayName: 'Publish Test Results **/TEST-*.xml' + inputs: + mergeTestResults: true + testRunTitle: 'linux-gcc' + platform: Linux + publishRunAttachments: false + condition: succeededOrFailed() + - task: PublishBuildArtifacts@1 + displayName: 'Publish trash directories of failed tests' + condition: failed() + inputs: + PathtoPublish: t/failed-test-artifacts + ArtifactName: failed-test-artifacts + +- job: osx_clang + displayName: osx-clang + condition: succeeded() + pool: Hosted macOS + steps: + - bash: | + test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/test-cache gitfileshare "$GITFILESHAREPWD" "$HOME/test-cache" || exit 1 + + export CC=clang + + ci/install-dependencies.sh || exit 1 + ci/run-build-and-tests.sh || { + ci/print-test-failures.sh + exit 1 + } + + test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || umount "$HOME/test-cache" || exit 1 + displayName: 'ci/run-build-and-tests.sh' + env: + GITFILESHAREPWD: $(gitfileshare.pwd) + - task: PublishTestResults@2 + displayName: 'Publish Test Results **/TEST-*.xml' + inputs: + mergeTestResults: true + testRunTitle: 'osx-clang' + platform: macOS + publishRunAttachments: false + condition: succeededOrFailed() + - task: PublishBuildArtifacts@1 + displayName: 'Publish trash directories of failed tests' + condition: failed() + inputs: + PathtoPublish: t/failed-test-artifacts + ArtifactName: failed-test-artifacts + +- job: osx_gcc + displayName: osx-gcc + condition: succeeded() + pool: Hosted macOS + steps: + - bash: | + test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/test-cache gitfileshare "$GITFILESHAREPWD" "$HOME/test-cache" || exit 1 + + ci/install-dependencies.sh || exit 1 + ci/run-build-and-tests.sh || { + ci/print-test-failures.sh + exit 1 + } + + test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || umount "$HOME/test-cache" || exit 1 + displayName: 'ci/run-build-and-tests.sh' + env: + GITFILESHAREPWD: $(gitfileshare.pwd) + - task: PublishTestResults@2 + displayName: 'Publish Test Results **/TEST-*.xml' + inputs: + mergeTestResults: true + testRunTitle: 'osx-gcc' + platform: macOS + publishRunAttachments: false + condition: succeededOrFailed() + - task: PublishBuildArtifacts@1 + displayName: 'Publish trash directories of failed tests' + condition: failed() + inputs: + PathtoPublish: t/failed-test-artifacts + ArtifactName: failed-test-artifacts + +- job: gettext_poison + displayName: GETTEXT_POISON + condition: succeeded() + pool: Hosted Ubuntu 1604 + steps: + - bash: | + test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/test-cache gitfileshare "$GITFILESHAREPWD" "$HOME/test-cache" || exit 1 + + sudo apt-get update && + sudo apt-get -y install git gcc make libssl-dev libcurl4-openssl-dev libexpat-dev tcl tk gettext git-email zlib1g-dev && + + export jobname=GETTEXT_POISON || exit 1 + + ci/run-build-and-tests.sh || { + ci/print-test-failures.sh + exit 1 + } + + test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || sudo umount "$HOME/test-cache" || exit 1 + displayName: 'ci/run-build-and-tests.sh' + env: + GITFILESHAREPWD: $(gitfileshare.pwd) + - task: PublishTestResults@2 + displayName: 'Publish Test Results **/TEST-*.xml' + inputs: + mergeTestResults: true + testRunTitle: 'gettext-poison' + platform: Linux + publishRunAttachments: false + condition: succeededOrFailed() + - task: PublishBuildArtifacts@1 + displayName: 'Publish trash directories of failed tests' + condition: failed() + inputs: + PathtoPublish: t/failed-test-artifacts + ArtifactName: failed-test-artifacts + +- job: linux32 + displayName: Linux32 + condition: succeeded() + pool: Hosted Ubuntu 1604 + steps: + - bash: | + test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/test-cache gitfileshare "$GITFILESHAREPWD" "$HOME/test-cache" || exit 1 + + res=0 + sudo AGENT_OS="$AGENT_OS" BUILD_BUILDNUMBER="$BUILD_BUILDNUMBER" BUILD_REPOSITORY_URI="$BUILD_REPOSITORY_URI" BUILD_SOURCEBRANCH="$BUILD_SOURCEBRANCH" BUILD_SOURCEVERSION="$BUILD_SOURCEVERSION" SYSTEM_PHASENAME="$SYSTEM_PHASENAME" SYSTEM_TASKDEFINITIONSURI="$SYSTEM_TASKDEFINITIONSURI" SYSTEM_TEAMPROJECT="$SYSTEM_TEAMPROJECT" CC=$CC MAKEFLAGS="$MAKEFLAGS" bash -lxc ci/run-linux32-docker.sh || res=1 + + sudo chmod a+r t/out/TEST-*.xml + test ! -d t/failed-test-artifacts || sudo chmod a+r t/failed-test-artifacts + + test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || sudo umount "$HOME/test-cache" || res=1 + exit $res + displayName: 'ci/run-linux32-docker.sh' + env: + GITFILESHAREPWD: $(gitfileshare.pwd) + - task: PublishTestResults@2 + displayName: 'Publish Test Results **/TEST-*.xml' + inputs: + mergeTestResults: true + testRunTitle: 'linux32' + platform: Linux + publishRunAttachments: false + condition: succeededOrFailed() + - task: PublishBuildArtifacts@1 + displayName: 'Publish trash directories of failed tests' + condition: failed() + inputs: + PathtoPublish: t/failed-test-artifacts + ArtifactName: failed-test-artifacts + +- job: static_analysis + displayName: StaticAnalysis + condition: succeeded() + pool: Hosted Ubuntu 1604 + steps: + - bash: | + test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/test-cache gitfileshare "$GITFILESHAREPWD" "$HOME/test-cache" || exit 1 + + sudo apt-get update && + sudo apt-get install -y coccinelle && + + export jobname=StaticAnalysis && + + ci/run-static-analysis.sh || exit 1 + + test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || sudo umount "$HOME/test-cache" || exit 1 + displayName: 'ci/run-static-analysis.sh' + env: + GITFILESHAREPWD: $(gitfileshare.pwd) + +- job: documentation + displayName: Documentation + condition: succeeded() + pool: Hosted Ubuntu 1604 + steps: + - bash: | + test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/test-cache gitfileshare "$GITFILESHAREPWD" "$HOME/test-cache" || exit 1 + + sudo apt-get update && + sudo apt-get install -y asciidoc xmlto asciidoctor && + + export ALREADY_HAVE_ASCIIDOCTOR=yes. && + export jobname=Documentation && + + ci/test-documentation.sh || exit 1 + + test "$GITFILESHAREPWD" = '$(gitfileshare.pwd)' || sudo umount "$HOME/test-cache" || exit 1 + displayName: 'ci/test-documentation.sh' + env: + GITFILESHAREPWD: $(gitfileshare.pwd) diff --git a/banned.h b/banned.h index 28f5937..447af24 100644 --- a/banned.h +++ b/banned.h @@ -16,6 +16,8 @@ #define strcat(x,y) BANNED(strcat) #undef strncpy #define strncpy(x,y,n) BANNED(strncpy) +#undef strncat +#define strncat(x,y,n) BANNED(strncat) #undef sprintf #undef vsprintf diff --git a/bisect.c b/bisect.c index 487675c..3af955c 100644 --- a/bisect.c +++ b/bisect.c @@ -558,7 +558,8 @@ struct commit_list *filter_skipped(struct commit_list *list, * is increased by one between each call, but that should not matter * for this application. */ -static unsigned get_prn(unsigned count) { +static unsigned get_prn(unsigned count) +{ count = count * 1103515245 + 12345; return (count/65536) % PRN_MODULO; } @@ -626,14 +627,15 @@ static struct commit_list *managed_skipped(struct commit_list *list, return skip_away(list, count); } -static void bisect_rev_setup(struct rev_info *revs, const char *prefix, +static void bisect_rev_setup(struct repository *r, struct rev_info *revs, + const char *prefix, const char *bad_format, const char *good_format, int read_paths) { struct argv_array rev_argv = ARGV_ARRAY_INIT; int i; - repo_init_revisions(the_repository, revs, prefix); + repo_init_revisions(r, revs, prefix); revs->abbrev = 0; revs->commit_format = CMIT_FMT_UNSPECIFIED; @@ -656,7 +658,7 @@ static void bisect_common(struct rev_info *revs) if (prepare_revision_walk(revs)) die("revision walk setup failed"); if (revs->tree_objects) - mark_edges_uninteresting(revs, NULL); + mark_edges_uninteresting(revs, NULL, 0); } static void exit_if_skipped_commits(struct commit_list *tried, @@ -723,23 +725,25 @@ static int bisect_checkout(const struct object_id *bisect_rev, int no_checkout) return run_command_v_opt(argv_show_branch, RUN_GIT_CMD); } -static struct commit *get_commit_reference(const struct object_id *oid) +static struct commit *get_commit_reference(struct repository *r, + const struct object_id *oid) { - struct commit *r = lookup_commit_reference(the_repository, oid); - if (!r) + struct commit *c = lookup_commit_reference(r, oid); + if (!c) die(_("Not a valid commit name %s"), oid_to_hex(oid)); - return r; + return c; } -static struct commit **get_bad_and_good_commits(int *rev_nr) +static struct commit **get_bad_and_good_commits(struct repository *r, + int *rev_nr) { struct commit **rev; int i, n = 0; ALLOC_ARRAY(rev, 1 + good_revs.nr); - rev[n++] = get_commit_reference(current_bad_oid); + rev[n++] = get_commit_reference(r, current_bad_oid); for (i = 0; i < good_revs.nr; i++) - rev[n++] = get_commit_reference(good_revs.oid + i); + rev[n++] = get_commit_reference(r, good_revs.oid + i); *rev_nr = n; return rev; @@ -823,12 +827,13 @@ static void check_merge_bases(int rev_nr, struct commit **rev, int no_checkout) free_commit_list(result); } -static int check_ancestors(int rev_nr, struct commit **rev, const char *prefix) +static int check_ancestors(struct repository *r, int rev_nr, + struct commit **rev, const char *prefix) { struct rev_info revs; int res; - bisect_rev_setup(&revs, prefix, "^%s", "%s", 0); + bisect_rev_setup(r, &revs, prefix, "^%s", "%s", 0); bisect_common(&revs); res = (revs.commits != NULL); @@ -847,7 +852,9 @@ static int check_ancestors(int rev_nr, struct commit **rev, const char *prefix) * If a merge base must be tested by the user, its source code will be * checked out to be tested by the user and we will exit. */ -static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout) +static void check_good_are_ancestors_of_bad(struct repository *r, + const char *prefix, + int no_checkout) { char *filename = git_pathdup("BISECT_ANCESTORS_OK"); struct stat st; @@ -866,8 +873,8 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout) goto done; /* Check if all good revs are ancestor of the bad rev. */ - rev = get_bad_and_good_commits(&rev_nr); - if (check_ancestors(rev_nr, rev, prefix)) + rev = get_bad_and_good_commits(r, &rev_nr); + if (check_ancestors(r, rev_nr, rev, prefix)) check_merge_bases(rev_nr, rev, no_checkout); free(rev); @@ -885,12 +892,14 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout) /* * This does "git diff-tree --pretty COMMIT" without one fork+exec. */ -static void show_diff_tree(const char *prefix, struct commit *commit) +static void show_diff_tree(struct repository *r, + const char *prefix, + struct commit *commit) { struct rev_info opt; /* diff-tree init */ - repo_init_revisions(the_repository, &opt, prefix); + repo_init_revisions(r, &opt, prefix); git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ opt.abbrev = 0; opt.diff = 1; @@ -945,7 +954,7 @@ void read_bisect_terms(const char **read_bad, const char **read_good) * If no_checkout is non-zero, the bisection process does not * checkout the trial commit but instead simply updates BISECT_HEAD. */ -int bisect_next_all(const char *prefix, int no_checkout) +int bisect_next_all(struct repository *r, const char *prefix, int no_checkout) { struct rev_info revs; struct commit_list *tried; @@ -957,9 +966,9 @@ int bisect_next_all(const char *prefix, int no_checkout) if (read_bisect_refs()) die(_("reading bisect refs failed")); - check_good_are_ancestors_of_bad(prefix, no_checkout); + check_good_are_ancestors_of_bad(r, prefix, no_checkout); - bisect_rev_setup(&revs, prefix, "%s", "^%s", 1); + bisect_rev_setup(r, &revs, prefix, "%s", "^%s", 1); revs.limited = 1; bisect_common(&revs); @@ -993,7 +1002,7 @@ int bisect_next_all(const char *prefix, int no_checkout) exit_if_skipped_commits(tried, current_bad_oid); printf("%s is the first %s commit\n", oid_to_hex(bisect_rev), term_bad); - show_diff_tree(prefix, revs.commits->item); + show_diff_tree(r, prefix, revs.commits->item); /* This means the bisection process succeeded. */ exit(10); } diff --git a/bisect.h b/bisect.h index 34df209..821d16e 100644 --- a/bisect.h +++ b/bisect.h @@ -2,6 +2,7 @@ #define BISECT_H struct commit_list; +struct repository; /* * Find bisection. If something is found, `reaches` will be the number of @@ -30,7 +31,9 @@ struct rev_list_info { const char *header_prefix; }; -extern int bisect_next_all(const char *prefix, int no_checkout); +extern int bisect_next_all(struct repository *r, + const char *prefix, + int no_checkout); extern int estimate_bisect_steps(int all); diff --git a/blame.c b/blame.c index d84c937..da57233 100644 --- a/blame.c +++ b/blame.c @@ -116,35 +116,38 @@ static void verify_working_tree_path(struct repository *r, die("no such path '%s' in HEAD", path); } -static struct commit_list **append_parent(struct commit_list **tail, const struct object_id *oid) +static struct commit_list **append_parent(struct repository *r, + struct commit_list **tail, + const struct object_id *oid) { struct commit *parent; - parent = lookup_commit_reference(the_repository, oid); + parent = lookup_commit_reference(r, oid); if (!parent) die("no such commit %s", oid_to_hex(oid)); return &commit_list_insert(parent, tail)->next; } -static void append_merge_parents(struct commit_list **tail) +static void append_merge_parents(struct repository *r, + struct commit_list **tail) { int merge_head; struct strbuf line = STRBUF_INIT; - merge_head = open(git_path_merge_head(the_repository), O_RDONLY); + merge_head = open(git_path_merge_head(r), O_RDONLY); if (merge_head < 0) { if (errno == ENOENT) return; die("cannot open '%s' for reading", - git_path_merge_head(the_repository)); + git_path_merge_head(r)); } while (!strbuf_getwholeline_fd(&line, merge_head, '\n')) { struct object_id oid; if (line.len < GIT_SHA1_HEXSZ || get_oid_hex(line.buf, &oid)) die("unknown line in '%s': %s", - git_path_merge_head(the_repository), line.buf); - tail = append_parent(tail, &oid); + git_path_merge_head(r), line.buf); + tail = append_parent(r, tail, &oid); } close(merge_head); strbuf_release(&line); @@ -155,11 +158,13 @@ static void append_merge_parents(struct commit_list **tail) * want to transfer ownership of the buffer to the commit (so we * must use detach). */ -static void set_commit_buffer_from_strbuf(struct commit *c, struct strbuf *sb) +static void set_commit_buffer_from_strbuf(struct repository *r, + struct commit *c, + struct strbuf *sb) { size_t len; void *buf = strbuf_detach(sb, &len); - set_commit_buffer(the_repository, c, buf, len); + set_commit_buffer(r, c, buf, len); } /* @@ -183,9 +188,9 @@ static struct commit *fake_working_tree_commit(struct repository *r, unsigned mode; struct strbuf msg = STRBUF_INIT; - read_index(r->index); + repo_read_index(r); time(&now); - commit = alloc_commit_node(the_repository); + commit = alloc_commit_node(r); commit->object.parsed = 1; commit->date = now; parent_tail = &commit->parents; @@ -193,8 +198,8 @@ static struct commit *fake_working_tree_commit(struct repository *r, if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL)) die("no such ref: HEAD"); - parent_tail = append_parent(parent_tail, &head_oid); - append_merge_parents(parent_tail); + parent_tail = append_parent(r, parent_tail, &head_oid); + append_merge_parents(r, parent_tail); verify_working_tree_path(r, commit, path); origin = make_origin(commit, path); @@ -211,7 +216,7 @@ static struct commit *fake_working_tree_commit(struct repository *r, ident, ident, path, (!contents_from ? path : (!strcmp(contents_from, "-") ? "standard input" : contents_from))); - set_commit_buffer_from_strbuf(commit, &msg); + set_commit_buffer_from_strbuf(r, commit, &msg); if (!contents_from || strcmp("-", contents_from)) { struct stat st; @@ -265,7 +270,7 @@ static struct commit *fake_working_tree_commit(struct repository *r, * want to run "diff-index --cached". */ discard_index(r->index); - read_index(r->index); + repo_read_index(r); len = strlen(path); if (!mode) { @@ -1678,7 +1683,7 @@ static struct commit *find_single_final(struct rev_info *revs, struct object *obj = revs->pending.objects[i].item; if (obj->flags & UNINTERESTING) continue; - obj = deref_tag(the_repository, obj, NULL, 0); + obj = deref_tag(revs->repo, obj, NULL, 0); if (obj->type != OBJ_COMMIT) die("Non commit %s?", revs->pending.objects[i].name); if (found) @@ -1709,14 +1714,14 @@ static struct commit *dwim_reverse_initial(struct rev_info *revs, /* Is that sole rev a committish? */ obj = revs->pending.objects[0].item; - obj = deref_tag(the_repository, obj, NULL, 0); + obj = deref_tag(revs->repo, obj, NULL, 0); if (obj->type != OBJ_COMMIT) return NULL; /* Do we have HEAD? */ if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL)) return NULL; - head_commit = lookup_commit_reference_gently(the_repository, + head_commit = lookup_commit_reference_gently(revs->repo, &head_oid, 1); if (!head_commit) return NULL; @@ -1745,7 +1750,7 @@ static struct commit *find_single_initial(struct rev_info *revs, struct object *obj = revs->pending.objects[i].item; if (!(obj->flags & UNINTERESTING)) continue; - obj = deref_tag(the_repository, obj, NULL, 0); + obj = deref_tag(revs->repo, obj, NULL, 0); if (obj->type != OBJ_COMMIT) die("Non commit %s?", revs->pending.objects[i].name); if (found) diff --git a/branch.c b/branch.c index 776f55f..28b81a7 100644 --- a/branch.c +++ b/branch.c @@ -242,7 +242,8 @@ N_("\n" "will track its remote counterpart, you may want to use\n" "\"git push -u\" to set the upstream config as you push."); -void create_branch(const char *name, const char *start_name, +void create_branch(struct repository *r, + const char *name, const char *start_name, int force, int clobber_head_ok, int reflog, int quiet, enum branch_track track) { @@ -300,7 +301,7 @@ void create_branch(const char *name, const char *start_name, break; } - if ((commit = lookup_commit_reference(the_repository, &oid)) == NULL) + if ((commit = lookup_commit_reference(r, &oid)) == NULL) die(_("Not a valid branch point: '%s'."), start_name); oidcpy(&oid, &commit->object.oid); @@ -336,15 +337,15 @@ void create_branch(const char *name, const char *start_name, free(real_ref); } -void remove_branch_state(void) +void remove_branch_state(struct repository *r) { - unlink(git_path_cherry_pick_head(the_repository)); - unlink(git_path_revert_head(the_repository)); - unlink(git_path_merge_head(the_repository)); - unlink(git_path_merge_rr(the_repository)); - unlink(git_path_merge_msg(the_repository)); - unlink(git_path_merge_mode(the_repository)); - unlink(git_path_squash_msg(the_repository)); + unlink(git_path_cherry_pick_head(r)); + unlink(git_path_revert_head(r)); + unlink(git_path_merge_head(r)); + unlink(git_path_merge_rr(r)); + unlink(git_path_merge_msg(r)); + unlink(git_path_merge_mode(r)); + unlink(git_path_squash_msg(r)); } void die_if_checked_out(const char *branch, int ignore_current_worktree) diff --git a/branch.h b/branch.h index 5cace45..29c1afa 100644 --- a/branch.h +++ b/branch.h @@ -1,6 +1,7 @@ #ifndef BRANCH_H #define BRANCH_H +struct repository; struct strbuf; enum branch_track { @@ -19,6 +20,8 @@ extern enum branch_track git_branch_track; /* * Creates a new branch, where: * + * - r is the repository to add a branch to + * * - name is the new branch name * * - start_name is the name of the existing branch that the new branch should @@ -37,7 +40,8 @@ extern enum branch_track git_branch_track; * that start_name is a tracking branch for (if any). * */ -void create_branch(const char *name, const char *start_name, +void create_branch(struct repository *r, + const char *name, const char *start_name, int force, int clobber_head_ok, int reflog, int quiet, enum branch_track track); @@ -60,7 +64,7 @@ extern int validate_new_branchname(const char *name, struct strbuf *ref, int for * Remove information about the state of working on the current * branch. (E.g., MERGE_HEAD) */ -void remove_branch_state(void); +void remove_branch_state(struct repository *r); /* * Configure local branch "local" as downstream to branch "remote" diff --git a/builtin/add.c b/builtin/add.c index f65c172..db2dfa4 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -3,6 +3,7 @@ * * Copyright (C) 2006 Linus Torvalds */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "config.h" #include "builtin.h" @@ -137,7 +138,7 @@ static int renormalize_tracked_files(const struct pathspec *pathspec, int flags) continue; /* do not touch non blobs */ if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL)) continue; - retval |= add_file_to_cache(ce->name, flags | HASH_RENORMALIZE); + retval |= add_file_to_cache(ce->name, flags | ADD_CACHE_RENORMALIZE); } return retval; @@ -176,7 +177,7 @@ static void refresh(int verbose, const struct pathspec *pathspec) die(_("pathspec '%s' did not match any files"), pathspec->items[i].match); } - free(seen); + free(seen); } int run_add_interactive(const char *revision, const char *patch_mode, @@ -239,7 +240,7 @@ static int edit_patch(int argc, const char **argv, const char *prefix) rev.diffopt.output_format = DIFF_FORMAT_PATCH; rev.diffopt.use_color = 0; rev.diffopt.flags.ignore_dirty_submodules = 1; - out = open(file, O_CREAT | O_WRONLY, 0666); + out = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0666); if (out < 0) die(_("Could not open '%s' for writing."), file); rev.diffopt.file = xfdopen(out, "w"); diff --git a/builtin/am.c b/builtin/am.c index 8f27f33..58a2aef 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -3,6 +3,7 @@ * * Based on git-am.sh by Junio C Hamano. */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "config.h" #include "builtin.h" @@ -35,22 +36,6 @@ #include "repository.h" /** - * Returns 1 if the file is empty or does not exist, 0 otherwise. - */ -static int is_empty_file(const char *filename) -{ - struct stat st; - - if (stat(filename, &st) < 0) { - if (errno == ENOENT) - return 1; - die_errno(_("could not stat %s"), filename); - } - - return !st.st_size; -} - -/** * Returns the length of the first line of msg. */ static int linelen(const char *msg) @@ -527,7 +512,7 @@ static int copy_notes_for_rebase(const struct am_state *state) } finish: - finish_copy_notes_for_rewrite(c, msg); + finish_copy_notes_for_rewrite(the_repository, c, msg); fclose(fp); strbuf_release(&sb); return ret; @@ -1220,7 +1205,7 @@ static int parse_mail(struct am_state *state, const char *mail) goto finish; } - if (is_empty_file(am_path(state, "patch"))) { + if (is_empty_or_missing_file(am_path(state, "patch"))) { printf_ln(_("Patch is empty.")); die_user_resolve(state); } @@ -1545,7 +1530,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa * changes. */ - init_merge_options(&o); + init_merge_options(&o, the_repository); o.branch1 = "HEAD"; their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg); @@ -1719,7 +1704,7 @@ static void am_run(struct am_state *state, int resume) refresh_and_write_cache(); - if (index_has_changes(&the_index, NULL, &sb)) { + if (repo_index_has_changes(the_repository, NULL, &sb)) { write_state_bool(state, "dirtyindex", 1); die(_("Dirty index: cannot apply patches (dirty: %s)"), sb.buf); } @@ -1777,7 +1762,7 @@ static void am_run(struct am_state *state, int resume) * the result may have produced the same tree as ours. */ if (!apply_status && - !index_has_changes(&the_index, NULL, NULL)) { + !repo_index_has_changes(the_repository, NULL, NULL)) { say(state, stdout, _("No changes -- Patch already applied.")); goto next; } @@ -1803,7 +1788,7 @@ next: resume = 0; } - if (!is_empty_file(am_path(state, "rewritten"))) { + if (!is_empty_or_missing_file(am_path(state, "rewritten"))) { assert(state->rebasing); copy_notes_for_rebase(state); run_post_rewrite_hook(state); @@ -1831,7 +1816,7 @@ static void am_resolve(struct am_state *state) say(state, stdout, _("Applying: %.*s"), linelen(state->msg), state->msg); - if (!index_has_changes(&the_index, NULL, NULL)) { + if (!repo_index_has_changes(the_repository, NULL, NULL)) { printf_ln(_("No changes - did you forget to use 'git add'?\n" "If there is nothing left to stage, chances are that something else\n" "already introduced the same changes; you might want to skip this patch.")); @@ -1970,7 +1955,7 @@ static int clean_index(const struct object_id *head, const struct object_id *rem if (merge_tree(remote_tree)) return -1; - remove_branch_state(); + remove_branch_state(the_repository); return 0; } @@ -1981,7 +1966,7 @@ static int clean_index(const struct object_id *head, const struct object_id *rem static void am_rerere_clear(void) { struct string_list merge_rr = STRING_LIST_INIT_DUP; - rerere_clear(&merge_rr); + rerere_clear(the_repository, &merge_rr); string_list_clear(&merge_rr, 1); } @@ -2000,6 +1985,15 @@ static void am_skip(struct am_state *state) if (clean_index(&head, &head)) die(_("failed to clean index")); + if (state->rebasing) { + FILE *fp = xfopen(am_path(state, "rewritten"), "a"); + + assert(!is_null_oid(&state->orig_commit)); + fprintf(fp, "%s ", oid_to_hex(&state->orig_commit)); + fprintf(fp, "%s\n", oid_to_hex(&head)); + fclose(fp); + } + am_next(state); am_load(state); am_run(state, 0); @@ -2278,7 +2272,7 @@ int cmd_am(int argc, const char **argv, const char *prefix) /* Ensure a valid committer ident can be constructed */ git_committer_info(IDENT_STRICT); - if (read_index_preload(&the_index, NULL, 0) < 0) + if (repo_read_index_preload(the_repository, NULL, 0) < 0) die(_("failed to read the index")); if (in_progress) { diff --git a/builtin/archive.c b/builtin/archive.c index d245523..45d1166 100644 --- a/builtin/archive.c +++ b/builtin/archive.c @@ -27,10 +27,10 @@ static int run_remote_archiver(int argc, const char **argv, const char *remote, const char *exec, const char *name_hint) { - char *buf; int fd[2], i, rv; struct transport *transport; struct remote *_remote; + struct packet_reader reader; _remote = remote_get(remote); if (!_remote->url[0]) @@ -53,18 +53,19 @@ static int run_remote_archiver(int argc, const char **argv, packet_write_fmt(fd[1], "argument %s\n", argv[i]); packet_flush(fd[1]); - buf = packet_read_line(fd[0], NULL); - if (!buf) + packet_reader_init(&reader, fd[0], NULL, 0, + PACKET_READ_CHOMP_NEWLINE | + PACKET_READ_DIE_ON_ERR_PACKET); + + if (packet_reader_read(&reader) != PACKET_READ_NORMAL) die(_("git archive: expected ACK/NAK, got a flush packet")); - if (strcmp(buf, "ACK")) { - if (starts_with(buf, "NACK ")) - die(_("git archive: NACK %s"), buf + 5); - if (starts_with(buf, "ERR ")) - die(_("remote error: %s"), buf + 4); + if (strcmp(reader.line, "ACK")) { + if (starts_with(reader.line, "NACK ")) + die(_("git archive: NACK %s"), reader.line + 5); die(_("git archive: protocol error")); } - if (packet_read_line(fd[0], NULL)) + if (packet_reader_read(&reader) != PACKET_READ_FLUSH) die(_("git archive: expected a flush")); /* Now, start reading from fd[0] and spit it out to stdout */ diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c index 4b5fadc..e7325fe 100644 --- a/builtin/bisect--helper.c +++ b/builtin/bisect--helper.c @@ -3,18 +3,58 @@ #include "parse-options.h" #include "bisect.h" #include "refs.h" +#include "dir.h" +#include "argv-array.h" +#include "run-command.h" +#include "prompt.h" +#include "quote.h" static GIT_PATH_FUNC(git_path_bisect_terms, "BISECT_TERMS") static GIT_PATH_FUNC(git_path_bisect_expected_rev, "BISECT_EXPECTED_REV") static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, "BISECT_ANCESTORS_OK") +static GIT_PATH_FUNC(git_path_bisect_start, "BISECT_START") +static GIT_PATH_FUNC(git_path_bisect_head, "BISECT_HEAD") +static GIT_PATH_FUNC(git_path_bisect_log, "BISECT_LOG") +static GIT_PATH_FUNC(git_path_head_name, "head-name") +static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES") static const char * const git_bisect_helper_usage[] = { N_("git bisect--helper --next-all [--no-checkout]"), N_("git bisect--helper --write-terms "), N_("git bisect--helper --bisect-clean-state"), + N_("git bisect--helper --bisect-reset []"), + N_("git bisect--helper --bisect-write [--no-log] "), + N_("git bisect--helper --bisect-check-and-set-terms "), + N_("git bisect--helper --bisect-next-check []"), + N_("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]"), + N_("git bisect--helper --bisect-start [--term-{old,good}= --term-{new,bad}=]" + "[--no-checkout] [ [...]] [--] [...]"), NULL }; +struct bisect_terms { + char *term_good; + char *term_bad; +}; + +static void free_terms(struct bisect_terms *terms) +{ + FREE_AND_NULL(terms->term_good); + FREE_AND_NULL(terms->term_bad); +} + +static void set_terms(struct bisect_terms *terms, const char *bad, + const char *good) +{ + free((void *)terms->term_good); + terms->term_good = xstrdup(good); + free((void *)terms->term_bad); + terms->term_bad = xstrdup(bad); +} + +static const char *vocab_bad = "bad|new"; +static const char *vocab_good = "good|old"; + /* * Check whether the string `term` belongs to the set of strings * included in the variable arguments. @@ -106,15 +146,482 @@ static void check_expected_revs(const char **revs, int rev_nr) } } +static int bisect_reset(const char *commit) +{ + struct strbuf branch = STRBUF_INIT; + + if (!commit) { + if (strbuf_read_file(&branch, git_path_bisect_start(), 0) < 1) { + printf(_("We are not bisecting.\n")); + return 0; + } + strbuf_rtrim(&branch); + } else { + struct object_id oid; + + if (get_oid_commit(commit, &oid)) + return error(_("'%s' is not a valid commit"), commit); + strbuf_addstr(&branch, commit); + } + + if (!file_exists(git_path_bisect_head())) { + struct argv_array argv = ARGV_ARRAY_INIT; + + argv_array_pushl(&argv, "checkout", branch.buf, "--", NULL); + if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) { + strbuf_release(&branch); + argv_array_clear(&argv); + return error(_("could not check out original" + " HEAD '%s'. Try 'git bisect" + " reset '."), branch.buf); + } + argv_array_clear(&argv); + } + + strbuf_release(&branch); + return bisect_clean_state(); +} + +static void log_commit(FILE *fp, char *fmt, const char *state, + struct commit *commit) +{ + struct pretty_print_context pp = {0}; + struct strbuf commit_msg = STRBUF_INIT; + char *label = xstrfmt(fmt, state); + + format_commit_message(commit, "%s", &commit_msg, &pp); + + fprintf(fp, "# %s: [%s] %s\n", label, oid_to_hex(&commit->object.oid), + commit_msg.buf); + + strbuf_release(&commit_msg); + free(label); +} + +static int bisect_write(const char *state, const char *rev, + const struct bisect_terms *terms, int nolog) +{ + struct strbuf tag = STRBUF_INIT; + struct object_id oid; + struct commit *commit; + FILE *fp = NULL; + int retval = 0; + + if (!strcmp(state, terms->term_bad)) { + strbuf_addf(&tag, "refs/bisect/%s", state); + } else if (one_of(state, terms->term_good, "skip", NULL)) { + strbuf_addf(&tag, "refs/bisect/%s-%s", state, rev); + } else { + retval = error(_("Bad bisect_write argument: %s"), state); + goto finish; + } + + if (get_oid(rev, &oid)) { + retval = error(_("couldn't get the oid of the rev '%s'"), rev); + goto finish; + } + + if (update_ref(NULL, tag.buf, &oid, NULL, 0, + UPDATE_REFS_MSG_ON_ERR)) { + retval = -1; + goto finish; + } + + fp = fopen(git_path_bisect_log(), "a"); + if (!fp) { + retval = error_errno(_("couldn't open the file '%s'"), git_path_bisect_log()); + goto finish; + } + + commit = lookup_commit_reference(the_repository, &oid); + log_commit(fp, "%s", state, commit); + + if (!nolog) + fprintf(fp, "git bisect %s %s\n", state, rev); + +finish: + if (fp) + fclose(fp); + strbuf_release(&tag); + return retval; +} + +static int check_and_set_terms(struct bisect_terms *terms, const char *cmd) +{ + int has_term_file = !is_empty_or_missing_file(git_path_bisect_terms()); + + if (one_of(cmd, "skip", "start", "terms", NULL)) + return 0; + + if (has_term_file && strcmp(cmd, terms->term_bad) && + strcmp(cmd, terms->term_good)) + return error(_("Invalid command: you're currently in a " + "%s/%s bisect"), terms->term_bad, + terms->term_good); + + if (!has_term_file) { + if (one_of(cmd, "bad", "good", NULL)) { + set_terms(terms, "bad", "good"); + return write_terms(terms->term_bad, terms->term_good); + } + if (one_of(cmd, "new", "old", NULL)) { + set_terms(terms, "new", "old"); + return write_terms(terms->term_bad, terms->term_good); + } + } + + return 0; +} + +static int mark_good(const char *refname, const struct object_id *oid, + int flag, void *cb_data) +{ + int *m_good = (int *)cb_data; + *m_good = 0; + return 1; +} + +static const char *need_bad_and_good_revision_warning = + N_("You need to give me at least one %s and %s revision.\n" + "You can use \"git bisect %s\" and \"git bisect %s\" for that."); + +static const char *need_bisect_start_warning = + N_("You need to start by \"git bisect start\".\n" + "You then need to give me at least one %s and %s revision.\n" + "You can use \"git bisect %s\" and \"git bisect %s\" for that."); + +static int bisect_next_check(const struct bisect_terms *terms, + const char *current_term) +{ + int missing_good = 1, missing_bad = 1, retval = 0; + const char *bad_ref = xstrfmt("refs/bisect/%s", terms->term_bad); + const char *good_glob = xstrfmt("%s-*", terms->term_good); + + if (ref_exists(bad_ref)) + missing_bad = 0; + + for_each_glob_ref_in(mark_good, good_glob, "refs/bisect/", + (void *) &missing_good); + + if (!missing_good && !missing_bad) + goto finish; + + if (!current_term) { + retval = -1; + goto finish; + } + + if (missing_good && !missing_bad && + !strcmp(current_term, terms->term_good)) { + char *yesno; + /* + * have bad (or new) but not good (or old). We could bisect + * although this is less optimum. + */ + warning(_("bisecting only with a %s commit"), terms->term_bad); + if (!isatty(0)) + goto finish; + /* + * TRANSLATORS: Make sure to include [Y] and [n] in your + * translation. The program will only accept English input + * at this point. + */ + yesno = git_prompt(_("Are you sure [Y/n]? "), PROMPT_ECHO); + if (starts_with(yesno, "N") || starts_with(yesno, "n")) + retval = -1; + goto finish; + } + if (!is_empty_or_missing_file(git_path_bisect_start())) { + retval = error(_(need_bad_and_good_revision_warning), + vocab_bad, vocab_good, vocab_bad, vocab_good); + } else { + retval = error(_(need_bisect_start_warning), + vocab_good, vocab_bad, vocab_good, vocab_bad); + } + +finish: + free((void *) good_glob); + free((void *) bad_ref); + return retval; +} + +static int get_terms(struct bisect_terms *terms) +{ + struct strbuf str = STRBUF_INIT; + FILE *fp = NULL; + int res = 0; + + fp = fopen(git_path_bisect_terms(), "r"); + if (!fp) { + res = -1; + goto finish; + } + + free_terms(terms); + strbuf_getline_lf(&str, fp); + terms->term_bad = strbuf_detach(&str, NULL); + strbuf_getline_lf(&str, fp); + terms->term_good = strbuf_detach(&str, NULL); + +finish: + if (fp) + fclose(fp); + strbuf_release(&str); + return res; +} + +static int bisect_terms(struct bisect_terms *terms, const char *option) +{ + if (get_terms(terms)) + return error(_("no terms defined")); + + if (option == NULL) { + printf(_("Your current terms are %s for the old state\n" + "and %s for the new state.\n"), + terms->term_good, terms->term_bad); + return 0; + } + if (one_of(option, "--term-good", "--term-old", NULL)) + printf("%s\n", terms->term_good); + else if (one_of(option, "--term-bad", "--term-new", NULL)) + printf("%s\n", terms->term_bad); + else + return error(_("invalid argument %s for 'git bisect terms'.\n" + "Supported options are: " + "--term-good|--term-old and " + "--term-bad|--term-new."), option); + + return 0; +} + +static int bisect_append_log_quoted(const char **argv) +{ + int retval = 0; + FILE *fp = fopen(git_path_bisect_log(), "a"); + struct strbuf orig_args = STRBUF_INIT; + + if (!fp) + return -1; + + if (fprintf(fp, "git bisect start") < 1) { + retval = -1; + goto finish; + } + + sq_quote_argv(&orig_args, argv); + if (fprintf(fp, "%s\n", orig_args.buf) < 1) + retval = -1; + +finish: + fclose(fp); + strbuf_release(&orig_args); + return retval; +} + +static int bisect_start(struct bisect_terms *terms, int no_checkout, + const char **argv, int argc) +{ + int i, has_double_dash = 0, must_write_terms = 0, bad_seen = 0; + int flags, pathspec_pos, retval = 0; + struct string_list revs = STRING_LIST_INIT_DUP; + struct string_list states = STRING_LIST_INIT_DUP; + struct strbuf start_head = STRBUF_INIT; + struct strbuf bisect_names = STRBUF_INIT; + struct object_id head_oid; + struct object_id oid; + const char *head; + + if (is_bare_repository()) + no_checkout = 1; + + /* + * Check for one bad and then some good revisions + */ + for (i = 0; i < argc; i++) { + if (!strcmp(argv[i], "--")) { + has_double_dash = 1; + break; + } + } + + for (i = 0; i < argc; i++) { + const char *arg = argv[i]; + if (!strcmp(argv[i], "--")) { + break; + } else if (!strcmp(arg, "--no-checkout")) { + no_checkout = 1; + } else if (!strcmp(arg, "--term-good") || + !strcmp(arg, "--term-old")) { + must_write_terms = 1; + free((void *) terms->term_good); + terms->term_good = xstrdup(argv[++i]); + } else if (skip_prefix(arg, "--term-good=", &arg) || + skip_prefix(arg, "--term-old=", &arg)) { + must_write_terms = 1; + free((void *) terms->term_good); + terms->term_good = xstrdup(arg); + } else if (!strcmp(arg, "--term-bad") || + !strcmp(arg, "--term-new")) { + must_write_terms = 1; + free((void *) terms->term_bad); + terms->term_bad = xstrdup(argv[++i]); + } else if (skip_prefix(arg, "--term-bad=", &arg) || + skip_prefix(arg, "--term-new=", &arg)) { + must_write_terms = 1; + free((void *) terms->term_bad); + terms->term_bad = xstrdup(arg); + } else if (starts_with(arg, "--") && + !one_of(arg, "--term-good", "--term-bad", NULL)) { + return error(_("unrecognized option: '%s'"), arg); + } else { + char *commit_id = xstrfmt("%s^{commit}", arg); + if (get_oid(commit_id, &oid) && has_double_dash) + die(_("'%s' does not appear to be a valid " + "revision"), arg); + + string_list_append(&revs, oid_to_hex(&oid)); + free(commit_id); + } + } + pathspec_pos = i; + + /* + * The user ran "git bisect start ", hence did not + * explicitly specify the terms, but we are already starting to + * set references named with the default terms, and won't be able + * to change afterwards. + */ + if (revs.nr) + must_write_terms = 1; + for (i = 0; i < revs.nr; i++) { + if (bad_seen) { + string_list_append(&states, terms->term_good); + } else { + bad_seen = 1; + string_list_append(&states, terms->term_bad); + } + } + + /* + * Verify HEAD + */ + head = resolve_ref_unsafe("HEAD", 0, &head_oid, &flags); + if (!head) + if (get_oid("HEAD", &head_oid)) + return error(_("bad HEAD - I need a HEAD")); + + /* + * Check if we are bisecting + */ + if (!is_empty_or_missing_file(git_path_bisect_start())) { + /* Reset to the rev from where we started */ + strbuf_read_file(&start_head, git_path_bisect_start(), 0); + strbuf_trim(&start_head); + if (!no_checkout) { + struct argv_array argv = ARGV_ARRAY_INIT; + + argv_array_pushl(&argv, "checkout", start_head.buf, + "--", NULL); + if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) { + retval = error(_("checking out '%s' failed." + " Try 'git bisect start " + "'."), + start_head.buf); + goto finish; + } + } + } else { + /* Get the rev from where we start. */ + if (!get_oid(head, &head_oid) && + !starts_with(head, "refs/heads/")) { + strbuf_reset(&start_head); + strbuf_addstr(&start_head, oid_to_hex(&head_oid)); + } else if (!get_oid(head, &head_oid) && + skip_prefix(head, "refs/heads/", &head)) { + /* + * This error message should only be triggered by + * cogito usage, and cogito users should understand + * it relates to cg-seek. + */ + if (!is_empty_or_missing_file(git_path_head_name())) + return error(_("won't bisect on cg-seek'ed tree")); + strbuf_addstr(&start_head, head); + } else { + return error(_("bad HEAD - strange symbolic ref")); + } + } + + /* + * Get rid of any old bisect state. + */ + if (bisect_clean_state()) + return -1; + + /* + * In case of mistaken revs or checkout error, or signals received, + * "bisect_auto_next" below may exit or misbehave. + * We have to trap this to be able to clean up using + * "bisect_clean_state". + */ + + /* + * Write new start state + */ + write_file(git_path_bisect_start(), "%s\n", start_head.buf); + + if (no_checkout) { + get_oid(start_head.buf, &oid); + if (update_ref(NULL, "BISECT_HEAD", &oid, NULL, 0, + UPDATE_REFS_MSG_ON_ERR)) { + retval = -1; + goto finish; + } + } + + if (pathspec_pos < argc - 1) + sq_quote_argv(&bisect_names, argv + pathspec_pos); + write_file(git_path_bisect_names(), "%s\n", bisect_names.buf); + + for (i = 0; i < states.nr; i++) + if (bisect_write(states.items[i].string, + revs.items[i].string, terms, 1)) { + retval = -1; + goto finish; + } + + if (must_write_terms && write_terms(terms->term_bad, + terms->term_good)) { + retval = -1; + goto finish; + } + + retval = bisect_append_log_quoted(argv); + if (retval) + retval = -1; + +finish: + string_list_clear(&revs, 0); + string_list_clear(&states, 0); + strbuf_release(&start_head); + strbuf_release(&bisect_names); + return retval; +} + int cmd_bisect__helper(int argc, const char **argv, const char *prefix) { enum { NEXT_ALL = 1, WRITE_TERMS, BISECT_CLEAN_STATE, - CHECK_EXPECTED_REVS + CHECK_EXPECTED_REVS, + BISECT_RESET, + BISECT_WRITE, + CHECK_AND_SET_TERMS, + BISECT_NEXT_CHECK, + BISECT_TERMS, + BISECT_START } cmdmode = 0; - int no_checkout = 0; + int no_checkout = 0, res = 0, nolog = 0; struct option options[] = { OPT_CMDMODE(0, "next-all", &cmdmode, N_("perform 'git bisect next'"), NEXT_ALL), @@ -124,20 +631,36 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) N_("cleanup the bisection state"), BISECT_CLEAN_STATE), OPT_CMDMODE(0, "check-expected-revs", &cmdmode, N_("check for expected revs"), CHECK_EXPECTED_REVS), + OPT_CMDMODE(0, "bisect-reset", &cmdmode, + N_("reset the bisection state"), BISECT_RESET), + OPT_CMDMODE(0, "bisect-write", &cmdmode, + N_("write out the bisection state in BISECT_LOG"), BISECT_WRITE), + OPT_CMDMODE(0, "check-and-set-terms", &cmdmode, + N_("check and set terms in a bisection state"), CHECK_AND_SET_TERMS), + OPT_CMDMODE(0, "bisect-next-check", &cmdmode, + N_("check whether bad or good terms exist"), BISECT_NEXT_CHECK), + OPT_CMDMODE(0, "bisect-terms", &cmdmode, + N_("print out the bisect terms"), BISECT_TERMS), + OPT_CMDMODE(0, "bisect-start", &cmdmode, + N_("start the bisect session"), BISECT_START), OPT_BOOL(0, "no-checkout", &no_checkout, N_("update BISECT_HEAD instead of checking out the current commit")), + OPT_BOOL(0, "no-log", &nolog, + N_("no log for BISECT_WRITE")), OPT_END() }; + struct bisect_terms terms = { .term_good = NULL, .term_bad = NULL }; argc = parse_options(argc, argv, prefix, options, - git_bisect_helper_usage, 0); + git_bisect_helper_usage, + PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_UNKNOWN); if (!cmdmode) usage_with_options(git_bisect_helper_usage, options); switch (cmdmode) { case NEXT_ALL: - return bisect_next_all(prefix, no_checkout); + return bisect_next_all(the_repository, prefix, no_checkout); case WRITE_TERMS: if (argc != 2) return error(_("--write-terms requires two arguments")); @@ -149,8 +672,40 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) case CHECK_EXPECTED_REVS: check_expected_revs(argv, argc); return 0; + case BISECT_RESET: + if (argc > 1) + return error(_("--bisect-reset requires either no argument or a commit")); + return !!bisect_reset(argc ? argv[0] : NULL); + case BISECT_WRITE: + if (argc != 4 && argc != 5) + return error(_("--bisect-write requires either 4 or 5 arguments")); + set_terms(&terms, argv[3], argv[2]); + res = bisect_write(argv[0], argv[1], &terms, nolog); + break; + case CHECK_AND_SET_TERMS: + if (argc != 3) + return error(_("--check-and-set-terms requires 3 arguments")); + set_terms(&terms, argv[2], argv[1]); + res = check_and_set_terms(&terms, argv[0]); + break; + case BISECT_NEXT_CHECK: + if (argc != 2 && argc != 3) + return error(_("--bisect-next-check requires 2 or 3 arguments")); + set_terms(&terms, argv[1], argv[0]); + res = bisect_next_check(&terms, argc == 3 ? argv[2] : NULL); + break; + case BISECT_TERMS: + if (argc > 1) + return error(_("--bisect-terms requires 0 or 1 argument")); + res = bisect_terms(&terms, argc == 1 ? argv[0] : NULL); + break; + case BISECT_START: + set_terms(&terms, "bad", "good"); + res = bisect_start(&terms, no_checkout, argv, argc); + break; default: return error("BUG: unknown subcommand '%d'", cmdmode); } - return 0; + free_terms(&terms); + return !!res; } diff --git a/builtin/blame.c b/builtin/blame.c index 6d798f9..581de0d 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -925,6 +925,10 @@ parse_done: */ blame_date_width = utf8_strwidth(_("4 years, 11 months ago")) + 1; /* add the null */ break; + case DATE_HUMAN: + /* If the year is shown, no time is shown */ + blame_date_width = sizeof("Thu Oct 19 16:00"); + break; case DATE_NORMAL: blame_date_width = sizeof("Thu Oct 19 16:00:04 2006 -0700"); break; @@ -1007,7 +1011,8 @@ parse_done: long bottom, top; if (parse_range_arg(range_list.items[range_i].string, nth_line_cb, &sb, lno, anchor, - &bottom, &top, sb.path, &the_index)) + &bottom, &top, sb.path, + the_repository->index)) usage(blame_usage); if ((!lno && (top || bottom)) || lno < bottom) die(Q_("file %s has only %lu line", diff --git a/builtin/branch.c b/builtin/branch.c index 0c55f7f..1be7272 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -783,7 +783,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix) * create_branch takes care of setting up the tracking * info and making sure new_upstream is correct */ - create_branch(branch->name, new_upstream, 0, 0, 0, quiet, BRANCH_TRACK_OVERRIDE); + create_branch(the_repository, branch->name, new_upstream, + 0, 0, 0, quiet, BRANCH_TRACK_OVERRIDE); } else if (unset_upstream) { struct branch *branch = branch_get(argv[0]); struct strbuf buf = STRBUF_INIT; @@ -814,7 +815,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix) if (track == BRANCH_TRACK_OVERRIDE) die(_("the '--set-upstream' option is no longer supported. Please use '--track' or '--set-upstream-to' instead.")); - create_branch(argv[0], (argc == 2) ? argv[1] : head, + create_branch(the_repository, + argv[0], (argc == 2) ? argv[1] : head, force, 0, reflog, quiet, track); } else diff --git a/builtin/bundle.c b/builtin/bundle.c index d0de59b..1ea4bfd 100644 --- a/builtin/bundle.c +++ b/builtin/bundle.c @@ -40,7 +40,7 @@ int cmd_bundle(int argc, const char **argv, const char *prefix) usage(builtin_bundle_usage); return 1; } - if (verify_bundle(&header, 1)) + if (verify_bundle(the_repository, &header, 1)) return 1; fprintf(stderr, _("%s is okay\n"), bundle_file); return 0; @@ -56,11 +56,11 @@ int cmd_bundle(int argc, const char **argv, const char *prefix) } if (!startup_info->have_repository) die(_("Need a repository to create a bundle.")); - return !!create_bundle(&header, bundle_file, argc, argv); + return !!create_bundle(the_repository, bundle_file, argc, argv); } else if (!strcmp(cmd, "unbundle")) { if (!startup_info->have_repository) die(_("Need a repository to unbundle.")); - return !!unbundle(&header, bundle_fd, 0) || + return !!unbundle(the_repository, &header, bundle_fd, 0) || list_bundle_refs(&header, argc, argv); } else usage(builtin_bundle_usage); diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 2ca56fd..0f09238 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -3,6 +3,7 @@ * * Copyright (C) Linus Torvalds, 2005 */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "config.h" #include "builtin.h" @@ -73,7 +74,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, if (unknown_type) flags |= OBJECT_INFO_ALLOW_UNKNOWN_TYPE; - if (get_oid_with_context(obj_name, GET_OID_RECORD_PATH, + if (get_oid_with_context(the_repository, obj_name, + GET_OID_RECORD_PATH, &oid, &obj_context)) die("Not a valid object name %s", obj_name); @@ -209,14 +211,14 @@ struct expand_data { /* * After a mark_query run, this object_info is set up to be - * passed to sha1_object_info_extended. It will point to the data + * passed to oid_object_info_extended. It will point to the data * elements above, so you can retrieve the response from there. */ struct object_info info; /* * This flag will be true if the requested batch format and options - * don't require us to call sha1_object_info, which can then be + * don't require us to call oid_object_info, which can then be * optimized out. */ unsigned skip_object_info : 1; @@ -380,14 +382,18 @@ static void batch_one_object(const char *obj_name, { struct object_context ctx; int flags = opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0; - enum follow_symlinks_result result; + enum get_oid_result result; - result = get_oid_with_context(obj_name, flags, &data->oid, &ctx); + result = get_oid_with_context(the_repository, obj_name, + flags, &data->oid, &ctx); if (result != FOUND) { switch (result) { case MISSING_OBJECT: printf("%s missing\n", obj_name); break; + case SHORT_NAME_AMBIGUOUS: + printf("%s ambiguous\n", obj_name); + break; case DANGLING_SYMLINK: printf("dangling %"PRIuMAX"\n%s\n", (uintmax_t)strlen(obj_name), obj_name); @@ -490,7 +496,7 @@ static int batch_objects(struct batch_options *opt) /* * Expand once with our special mark_query flag, which will prime the - * object_info to be handed to sha1_object_info_extended for each + * object_info to be handed to oid_object_info_extended for each * object. */ memset(&data, 0, sizeof(data)); diff --git a/builtin/check-attr.c b/builtin/check-attr.c index 30a2f84..dd83397 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -1,3 +1,4 @@ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "builtin.h" #include "cache.h" #include "config.h" diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c index ec9a959..5990973 100644 --- a/builtin/check-ignore.c +++ b/builtin/check-ignore.c @@ -1,3 +1,4 @@ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "builtin.h" #include "cache.h" #include "config.h" diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c index eb74774..1ac1cc2 100644 --- a/builtin/checkout-index.c +++ b/builtin/checkout-index.c @@ -4,6 +4,7 @@ * Copyright (C) 2005 Linus Torvalds * */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "builtin.h" #include "config.h" #include "lockfile.h" @@ -67,7 +68,8 @@ static int checkout_file(const char *name, const char *prefix) continue; did_checkout = 1; if (checkout_entry(ce, &state, - to_tempfile ? topath[ce_stage(ce)] : NULL) < 0) + to_tempfile ? topath[ce_stage(ce)] : NULL, + NULL) < 0) errs++; } @@ -111,7 +113,8 @@ static void checkout_all(const char *prefix, int prefix_length) write_tempfile_record(last_ce->name, prefix); } if (checkout_entry(ce, &state, - to_tempfile ? topath[ce_stage(ce)] : NULL) < 0) + to_tempfile ? topath[ce_stage(ce)] : NULL, + NULL) < 0) errs++; last_ce = ce; } diff --git a/builtin/checkout.c b/builtin/checkout.c index acdafc6..24b8593 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -1,3 +1,4 @@ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "builtin.h" #include "config.h" #include "checkout.h" @@ -44,6 +45,7 @@ struct checkout_opts { int ignore_skipworktree; int ignore_other_worktrees; int show_progress; + int count_checkout_paths; /* * If new checkout options are added, skip_merge_working_tree * should be updated accordingly. @@ -115,7 +117,8 @@ static int update_some(const struct object_id *oid, struct strbuf *base, static int read_tree_some(struct tree *tree, const struct pathspec *pathspec) { - read_tree_recursive(tree, "", 0, 0, pathspec, update_some, NULL); + read_tree_recursive(the_repository, tree, "", 0, 0, + pathspec, update_some, NULL); /* update the index with the given tree's info * for all args, expanding wildcards, and exit @@ -165,12 +168,13 @@ static int check_stages(unsigned stages, const struct cache_entry *ce, int pos) } static int checkout_stage(int stage, const struct cache_entry *ce, int pos, - const struct checkout *state) + const struct checkout *state, int *nr_checkouts) { while (pos < active_nr && !strcmp(active_cache[pos]->name, ce->name)) { if (ce_stage(active_cache[pos]) == stage) - return checkout_entry(active_cache[pos], state, NULL); + return checkout_entry(active_cache[pos], state, + NULL, nr_checkouts); pos++; } if (stage == 2) @@ -179,7 +183,7 @@ static int checkout_stage(int stage, const struct cache_entry *ce, int pos, return error(_("path '%s' does not have their version"), ce->name); } -static int checkout_merged(int pos, const struct checkout *state) +static int checkout_merged(int pos, const struct checkout *state, int *nr_checkouts) { struct cache_entry *ce = active_cache[pos]; const char *path = ce->name; @@ -242,7 +246,7 @@ static int checkout_merged(int pos, const struct checkout *state) ce = make_transient_cache_entry(mode, &oid, path, 2); if (!ce) die(_("make_cache_entry failed for path '%s'"), path); - status = checkout_entry(ce, state, NULL); + status = checkout_entry(ce, state, NULL, nr_checkouts); discard_cache_entry(ce); return status; } @@ -257,6 +261,7 @@ static int checkout_paths(const struct checkout_opts *opts, struct commit *head; int errs = 0; struct lock_file lock_file = LOCK_INIT; + int nr_checkouts = 0, nr_unmerged = 0; if (opts->track != BRANCH_TRACK_UNSPECIFIED) die(_("'%s' cannot be used with updating paths"), "--track"); @@ -284,7 +289,7 @@ static int checkout_paths(const struct checkout_opts *opts, return run_add_interactive(revision, "--patch=checkout", &opts->pathspec); - hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR); + repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR); if (read_cache_preload(&opts->pathspec) < 0) return error(_("index file corrupt")); @@ -371,17 +376,41 @@ static int checkout_paths(const struct checkout_opts *opts, struct cache_entry *ce = active_cache[pos]; if (ce->ce_flags & CE_MATCHED) { if (!ce_stage(ce)) { - errs |= checkout_entry(ce, &state, NULL); + errs |= checkout_entry(ce, &state, + NULL, &nr_checkouts); continue; } if (opts->writeout_stage) - errs |= checkout_stage(opts->writeout_stage, ce, pos, &state); + errs |= checkout_stage(opts->writeout_stage, + ce, pos, + &state, &nr_checkouts); else if (opts->merge) - errs |= checkout_merged(pos, &state); + errs |= checkout_merged(pos, &state, + &nr_unmerged); pos = skip_same_name(ce, pos) - 1; } } - errs |= finish_delayed_checkout(&state); + errs |= finish_delayed_checkout(&state, &nr_checkouts); + + if (opts->count_checkout_paths) { + if (nr_unmerged) + fprintf_ln(stderr, Q_("Recreated %d merge conflict", + "Recreated %d merge conflicts", + nr_unmerged), + nr_unmerged); + if (opts->source_tree) + fprintf_ln(stderr, Q_("Updated %d path from %s", + "Updated %d paths from %s", + nr_checkouts), + nr_checkouts, + find_unique_abbrev(&opts->source_tree->object.oid, + DEFAULT_ABBREV)); + else if (!nr_unmerged || nr_checkouts) + fprintf_ln(stderr, Q_("Updated %d path from the index", + "Updated %d paths from the index", + nr_checkouts), + nr_checkouts); + } if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK)) die(_("unable to write new index file")); @@ -569,6 +598,14 @@ static int skip_merge_working_tree(const struct checkout_opts *opts, * Remaining variables are not checkout options but used to track state */ + /* + * Do the merge if this is the initial checkout. We cannot use + * is_cache_unborn() here because the index hasn't been loaded yet + * so cache_nr and timestamp.sec are always zero. + */ + if (!file_exists(get_index_file())) + return 0; + return 1; } @@ -670,7 +707,7 @@ static int merge_working_tree(const struct checkout_opts *opts, * a pain; plumb in an option to set * o.renormalize? */ - init_merge_options(&o); + init_merge_options(&o, the_repository); o.verbosity = 0; work = write_tree_from_memory(&o); @@ -753,7 +790,8 @@ static void update_refs_for_switch(const struct checkout_opts *opts, free(refname); } else - create_branch(opts->new_branch, new_branch_info->name, + create_branch(the_repository, + opts->new_branch, new_branch_info->name, opts->new_branch_force ? 1 : 0, opts->new_branch_force ? 1 : 0, opts->new_branch_log, @@ -811,7 +849,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts, delete_reflog(old_branch_info->path); } } - remove_branch_state(); + remove_branch_state(the_repository); strbuf_release(&msg); if (!opts->quiet && (new_branch_info->path || (!opts->force_detach && !strcmp(new_branch_info->name, "HEAD")))) @@ -1064,6 +1102,7 @@ static int parse_branchname_arg(int argc, const char **argv, has_dash_dash = 1; /* case (3) or (1) */ else if (dash_dash_pos >= 2) die(_("only one reference expected, %d given."), dash_dash_pos); + opts->count_checkout_paths = !opts->quiet && !has_dash_dash; if (!strcmp(arg, "-")) arg = "@{-1}"; @@ -1079,9 +1118,12 @@ static int parse_branchname_arg(int argc, const char **argv, */ int recover_with_dwim = dwim_new_local_branch_ok; - if (!has_dash_dash && - (check_filename(opts->prefix, arg) || !no_wildcard(arg))) + int could_be_checkout_paths = !has_dash_dash && + check_filename(opts->prefix, arg); + + if (!has_dash_dash && !no_wildcard(arg)) recover_with_dwim = 0; + /* * Accept "git checkout foo" and "git checkout foo --" * as candidates for dwim. @@ -1094,6 +1136,10 @@ static int parse_branchname_arg(int argc, const char **argv, const char *remote = unique_tracking_name(arg, rev, dwim_remotes_matched); if (remote) { + if (could_be_checkout_paths) + die(_("'%s' could be both a local file and a tracking branch.\n" + "Please use -- (and optionally --no-guess) to disambiguate"), + arg); *new_branch = arg; arg = remote; /* DWIMmed to create local branch, case (3).(b) */ @@ -1228,7 +1274,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) struct checkout_opts opts; struct branch_info new_branch_info; char *conflict_style = NULL; - int dwim_new_local_branch = 1; + int dwim_new_local_branch, no_dwim_new_local_branch = 0; int dwim_remotes_matched = 0; struct option options[] = { OPT__QUIET(&opts.quiet, N_("suppress progress reporting")), @@ -1258,8 +1304,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) OPT_BOOL('p', "patch", &opts.patch_mode, N_("select hunks interactively")), OPT_BOOL(0, "ignore-skip-worktree-bits", &opts.ignore_skipworktree, N_("do not limit pathspecs to sparse entries only")), - OPT_HIDDEN_BOOL(0, "guess", &dwim_new_local_branch, - N_("second guess 'git checkout '")), + OPT_BOOL(0, "no-guess", &no_dwim_new_local_branch, + N_("do not second guess 'git checkout '")), OPT_BOOL(0, "ignore-other-worktrees", &opts.ignore_other_worktrees, N_("do not check if another worktree is holding the given ref")), { OPTION_CALLBACK, 0, "recurse-submodules", NULL, @@ -1282,6 +1328,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, checkout_usage, PARSE_OPT_KEEP_DASHDASH); + dwim_new_local_branch = !no_dwim_new_local_branch; if (opts.show_progress < 0) { if (opts.quiet) opts.show_progress = 0; diff --git a/builtin/clean.c b/builtin/clean.c index bbcdeb2..aaba4af 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -6,6 +6,7 @@ * Based on git-clean.sh by Pavel Roskin */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "builtin.h" #include "cache.h" #include "config.h" diff --git a/builtin/clone.c b/builtin/clone.c index 5d31bea..50bde99 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -8,6 +8,7 @@ * Clone a repository into a different directory that does not yet exist. */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "builtin.h" #include "config.h" #include "lockfile.h" @@ -548,7 +549,7 @@ static struct ref *find_remote_branch(const struct ref *refs, const char *branch } static struct ref *wanted_peer_refs(const struct ref *refs, - struct refspec_item *refspec) + struct refspec *refspec) { struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD")); struct ref *local_refs = head; @@ -569,13 +570,19 @@ static struct ref *wanted_peer_refs(const struct ref *refs, warning(_("Could not find remote branch %s to clone."), option_branch); else { - get_fetch_map(remote_head, refspec, &tail, 0); + int i; + for (i = 0; i < refspec->nr; i++) + get_fetch_map(remote_head, &refspec->items[i], + &tail, 0); /* if --branch=tag, pull the requested tag explicitly */ get_fetch_map(remote_head, tag_refspec, &tail, 0); } - } else - get_fetch_map(refs, refspec, &tail, 0); + } else { + int i; + for (i = 0; i < refspec->nr; i++) + get_fetch_map(refs, &refspec->items[i], &tail, 0); + } if (!option_mirror && !option_single_branch && !option_no_tags) get_fetch_map(refs, tag_refspec, &tail, 0); @@ -768,7 +775,7 @@ static int checkout(int submodule_progress) if (!err && (option_recurse_submodules.nr > 0)) { struct argv_array args = ARGV_ARRAY_INIT; - argv_array_pushl(&args, "submodule", "update", "--require-init", "--recursive", NULL); + argv_array_pushl(&args, "submodule", "update", "--init", "--recursive", NULL); if (option_shallow_submodules == 1) argv_array_push(&args, "--depth=1"); @@ -890,7 +897,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix) const struct ref *our_head_points_at; struct ref *mapped_refs; const struct ref *ref; - struct strbuf key = STRBUF_INIT, value = STRBUF_INIT; + struct strbuf key = STRBUF_INIT; + struct strbuf default_refspec = STRBUF_INIT; struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT; struct transport *transport = NULL; const char *src_ref_prefix = "refs/heads/"; @@ -898,7 +906,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix) int err = 0, complete_refs_before_fetch = 1; int submodule_progress; - struct refspec rs = REFSPEC_INIT_FETCH; struct argv_array ref_prefixes = ARGV_ARRAY_INIT; fetch_if_missing = 0; @@ -1067,7 +1074,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix) strbuf_addf(&branch_top, "refs/remotes/%s/", option_origin); } - strbuf_addf(&value, "+%s*:%s*", src_ref_prefix, branch_top.buf); strbuf_addf(&key, "remote.%s.url", option_origin); git_config_set(key.buf, repo); strbuf_reset(&key); @@ -1081,11 +1087,12 @@ int cmd_clone(int argc, const char **argv, const char *prefix) if (option_required_reference.nr || option_optional_reference.nr) setup_reference(); - refspec_append(&rs, value.buf); + remote = remote_get(option_origin); - strbuf_reset(&value); + strbuf_addf(&default_refspec, "+%s*:%s*", src_ref_prefix, + branch_top.buf); + refspec_append(&remote->fetch, default_refspec.buf); - remote = remote_get(option_origin); transport = transport_get(remote, remote->url[0]); transport_set_verbosity(transport, option_verbosity, option_progress); transport->family = family; @@ -1130,9 +1137,13 @@ int cmd_clone(int argc, const char **argv, const char *prefix) option_upload_pack); if (filter_options.choice) { + struct strbuf expanded_filter_spec = STRBUF_INIT; + expand_list_objects_filter_spec(&filter_options, + &expanded_filter_spec); transport_set_option(transport, TRANS_OPT_LIST_OBJECTS_FILTER, - filter_options.filter_spec); + expanded_filter_spec.buf); transport_set_option(transport, TRANS_OPT_FROM_PROMISOR, "1"); + strbuf_release(&expanded_filter_spec); } if (transport->smart_options && !deepen && !filter_options.choice) @@ -1140,7 +1151,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) argv_array_push(&ref_prefixes, "HEAD"); - refspec_ref_prefixes(&rs, &ref_prefixes); + refspec_ref_prefixes(&remote->fetch, &ref_prefixes); if (option_branch) expand_ref_prefix(&ref_prefixes, option_branch); if (!option_no_tags) @@ -1149,7 +1160,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) refs = transport_get_remote_refs(transport, &ref_prefixes); if (refs) { - mapped_refs = wanted_peer_refs(refs, &rs.items[0]); + mapped_refs = wanted_peer_refs(refs, &remote->fetch); /* * transport_get_remote_refs() may return refs with null sha-1 * in mapped_refs (see struct transport->get_refs_list @@ -1240,10 +1251,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix) strbuf_release(&reflog_msg); strbuf_release(&branch_top); strbuf_release(&key); - strbuf_release(&value); + strbuf_release(&default_refspec); junk_mode = JUNK_LEAVE_ALL; - refspec_clear(&rs); argv_array_clear(&ref_prefixes); return err; } diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index c02a3f1..4ae5027 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -110,8 +110,8 @@ static int graph_read(int argc, const char **argv) printf(" oid_lookup"); if (graph->chunk_commit_data) printf(" commit_metadata"); - if (graph->chunk_large_edges) - printf(" large_edges"); + if (graph->chunk_extra_edges) + printf(" extra_edges"); printf("\n"); UNLEAK(graph); diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c index 9ec36a8..12cc403 100644 --- a/builtin/commit-tree.c +++ b/builtin/commit-tree.c @@ -66,7 +66,13 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix) continue; } - if (skip_prefix(arg, "-S", &sign_commit)) + if (!strcmp(arg, "--gpg-sign")) { + sign_commit = ""; + continue; + } + + if (skip_prefix(arg, "-S", &sign_commit) || + skip_prefix(arg, "--gpg-sign=", &sign_commit)) continue; if (!strcmp(arg, "--no-gpg-sign")) { diff --git a/builtin/commit.c b/builtin/commit.c index c021b11..2986553 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -5,6 +5,7 @@ * Based on git-commit.sh by Junio C Hamano and Linus Torvalds */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "config.h" #include "lockfile.h" @@ -188,7 +189,7 @@ static void determine_whence(struct wt_status *s) static void status_init_config(struct wt_status *s, config_fn_t fn) { - wt_status_prepare(s); + wt_status_prepare(the_repository, s); init_diff_ui_defaults(); git_config(fn, s); determine_whence(s); @@ -351,7 +352,7 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix if (write_locked_index(&the_index, &index_lock, 0)) die(_("unable to create temporary index")); - old_index_env = getenv(INDEX_ENVIRONMENT); + old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT)); setenv(INDEX_ENVIRONMENT, get_lock_file_path(&index_lock), 1); if (interactive_add(argc, argv, prefix, patch_interactive) != 0) @@ -361,6 +362,7 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix setenv(INDEX_ENVIRONMENT, old_index_env, 1); else unsetenv(INDEX_ENVIRONMENT); + FREE_AND_NULL(old_index_env); discard_cache(); read_cache_from(get_lock_file_path(&index_lock)); @@ -911,7 +913,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix, if (ignore_submodule_arg && !strcmp(ignore_submodule_arg, "all")) flags.ignore_submodules = 1; - committable = index_differs_from(parent, &flags, 1); + committable = index_differs_from(the_repository, + parent, &flags, 1); } } strbuf_release(&committer_ident); @@ -1366,7 +1369,7 @@ int cmd_status(int argc, const char **argv, const char *prefix) if (status_format != STATUS_FORMAT_PORCELAIN && status_format != STATUS_FORMAT_PORCELAIN_V2) progress_flag = REFRESH_PROGRESS; - read_index(&the_index); + repo_read_index(the_repository); refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED|progress_flag, &s.pathspec, NULL, NULL); @@ -1395,7 +1398,7 @@ int cmd_status(int argc, const char **argv, const char *prefix) wt_status_collect(&s); if (0 <= fd) - update_index_if_able(&the_index, &index_lock); + repo_update_index_if_able(the_repository, &index_lock); if (s.relative_paths) s.prefix = prefix; @@ -1673,7 +1676,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) run_command_v_opt(argv_gc_auto, RUN_GIT_CMD); run_commit_hook(use_editor, get_index_file(), "post-commit", NULL); if (amend && !no_post_rewrite) { - commit_post_rewrite(current_head, &oid); + commit_post_rewrite(the_repository, current_head, &oid); } if (!quiet) { unsigned int flags = 0; @@ -1682,7 +1685,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix) flags |= SUMMARY_INITIAL_COMMIT; if (author_date_is_interesting()) flags |= SUMMARY_SHOW_AUTHOR_DATE; - print_commit_summary(prefix, &oid, flags); + print_commit_summary(the_repository, prefix, + &oid, flags); } UNLEAK(err); diff --git a/builtin/config.c b/builtin/config.c index 84385ef..98d65bc 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -164,7 +164,8 @@ static NORETURN void usage_builtin_config(void) usage_with_options(builtin_config_usage, builtin_config_options); } -static void check_argc(int argc, int min, int max) { +static void check_argc(int argc, int min, int max) +{ if (argc >= min && argc <= max) return; if (min == max) @@ -598,7 +599,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) int nongit = !startup_info->have_repository; char *value; - given_config_source.file = getenv(CONFIG_ENVIRONMENT); + given_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT)); argc = parse_options(argc, argv, prefix, builtin_config_options, builtin_config_usage, diff --git a/builtin/count-objects.c b/builtin/count-objects.c index a7cad05..3fae474 100644 --- a/builtin/count-objects.c +++ b/builtin/count-objects.c @@ -78,10 +78,10 @@ static int count_cruft(const char *basename, const char *path, void *data) return 0; } -static int print_alternate(struct alternate_object_database *alt, void *data) +static int print_alternate(struct object_directory *odb, void *data) { printf("alternate: "); - quote_c_style(alt->path, NULL, stdout, 0); + quote_c_style(odb->path, NULL, stdout, 0); putchar('\n'); return 0; } diff --git a/builtin/describe.c b/builtin/describe.c index cc11844..1409ced 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -1,3 +1,4 @@ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "config.h" #include "lockfile.h" @@ -629,12 +630,13 @@ int cmd_describe(int argc, const char **argv, const char *prefix) struct argv_array args = ARGV_ARRAY_INIT; int fd, result; + setup_work_tree(); read_cache(); refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, NULL, NULL, NULL); fd = hold_locked_index(&index_lock, 0); if (0 <= fd) - update_index_if_able(&the_index, &index_lock); + repo_update_index_if_able(the_repository, &index_lock); repo_init_revisions(the_repository, &revs, prefix); argv_array_pushv(&args, diff_index_args); diff --git a/builtin/diff-files.c b/builtin/diff-files.c index 48cfcb9..86ae474 100644 --- a/builtin/diff-files.c +++ b/builtin/diff-files.c @@ -3,6 +3,7 @@ * * Copyright (C) Linus Torvalds, 2005 */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "config.h" #include "diff.h" diff --git a/builtin/diff-index.c b/builtin/diff-index.c index fcccd1f..93ec642 100644 --- a/builtin/diff-index.c +++ b/builtin/diff-index.c @@ -1,3 +1,4 @@ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "config.h" #include "diff.h" diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c index ef99612..a90681b 100644 --- a/builtin/diff-tree.c +++ b/builtin/diff-tree.c @@ -1,3 +1,4 @@ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "config.h" #include "diff.h" @@ -165,7 +166,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) if (opt->diffopt.detect_rename) { if (!the_index.cache) - read_index(&the_index); + repo_read_index(the_repository); opt->diffopt.setup |= DIFF_SETUP_USE_SIZE_CACHE; } while (fgets(line, sizeof(line), stdin)) { diff --git a/builtin/diff.c b/builtin/diff.c index f0393bb..9f61092 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -3,6 +3,7 @@ * * Copyright (c) 2006 Junio C Hamano */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "config.h" #include "lockfile.h" @@ -102,7 +103,7 @@ static int builtin_diff_blobs(struct rev_info *revs, int argc, const char **argv, struct object_array_entry **blob) { - unsigned mode = canon_mode(S_IFREG | 0644); + const unsigned mode = canon_mode(S_IFREG | 0644); if (argc > 1) usage(builtin_diff_usage); @@ -212,7 +213,7 @@ static void refresh_index_quietly(void) discard_cache(); read_cache(); refresh_cache(REFRESH_QUIET|REFRESH_UNMERGED); - update_index_if_able(&the_index, &lock_file); + repo_update_index_if_able(the_repository, &lock_file); } static int builtin_diff_files(struct rev_info *revs, int argc, const char **argv) diff --git a/builtin/difftool.c b/builtin/difftool.c index 544b0e8..a3ea60e 100644 --- a/builtin/difftool.c +++ b/builtin/difftool.c @@ -11,6 +11,7 @@ * * Copyright (C) 2016 Johannes Schindelin */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "config.h" #include "builtin.h" @@ -323,7 +324,7 @@ static int checkout_path(unsigned mode, struct object_id *oid, int ret; ce = make_transient_cache_entry(mode, oid, path, 0); - ret = checkout_entry(ce, state, NULL); + ret = checkout_entry(ce, state, NULL, NULL); discard_cache_entry(ce); return ret; diff --git a/builtin/fast-export.c b/builtin/fast-export.c index 5790f0d..9e28348 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -31,13 +31,16 @@ static const char *fast_export_usage[] = { }; static int progress; -static enum { ABORT, VERBATIM, WARN, WARN_STRIP, STRIP } signed_tag_mode = ABORT; -static enum { ERROR, DROP, REWRITE } tag_of_filtered_mode = ERROR; +static enum { SIGNED_TAG_ABORT, VERBATIM, WARN, WARN_STRIP, STRIP } signed_tag_mode = SIGNED_TAG_ABORT; +static enum { TAG_FILTERING_ABORT, DROP, REWRITE } tag_of_filtered_mode = TAG_FILTERING_ABORT; static int fake_missing_tagger; static int use_done_feature; static int no_data; static int full_tree; +static int reference_excluded_commits; +static int show_original_ids; static struct string_list extra_refs = STRING_LIST_INIT_NODUP; +static struct string_list tag_refs = STRING_LIST_INIT_NODUP; static struct refspec refspecs = REFSPEC_INIT_FETCH; static int anonymize; static struct revision_sources revision_sources; @@ -46,7 +49,7 @@ static int parse_opt_signed_tag_mode(const struct option *opt, const char *arg, int unset) { if (unset || !strcmp(arg, "abort")) - signed_tag_mode = ABORT; + signed_tag_mode = SIGNED_TAG_ABORT; else if (!strcmp(arg, "verbatim") || !strcmp(arg, "ignore")) signed_tag_mode = VERBATIM; else if (!strcmp(arg, "warn")) @@ -64,7 +67,7 @@ static int parse_opt_tag_of_filtered_mode(const struct option *opt, const char *arg, int unset) { if (unset || !strcmp(arg, "abort")) - tag_of_filtered_mode = ERROR; + tag_of_filtered_mode = TAG_FILTERING_ABORT; else if (!strcmp(arg, "drop")) tag_of_filtered_mode = DROP; else if (!strcmp(arg, "rewrite")) @@ -187,6 +190,22 @@ static int get_object_mark(struct object *object) return ptr_to_mark(decoration); } +static struct commit *rewrite_commit(struct commit *p) +{ + for (;;) { + if (p->parents && p->parents->next) + break; + if (p->object.flags & UNINTERESTING) + break; + if (!(p->object.flags & TREESAME)) + break; + if (!p->parents) + return NULL; + p = p->parents->item; + } + return p; +} + static void show_progress(void) { static int counter = 0; @@ -243,7 +262,7 @@ static void export_blob(const struct object_id *oid) if (!buf) die("could not read blob %s", oid_to_hex(oid)); if (check_object_signature(oid, buf, size, type_name(type)) < 0) - die("sha1 mismatch in blob %s", oid_to_hex(oid)); + die("oid mismatch in blob %s", oid_to_hex(oid)); object = parse_object_buffer(the_repository, oid, type, size, buf, &eaten); } @@ -253,7 +272,10 @@ static void export_blob(const struct object_id *oid) mark_next_object(object); - printf("blob\nmark :%"PRIu32"\ndata %"PRIuMAX"\n", last_idnum, (uintmax_t)size); + printf("blob\nmark :%"PRIu32"\n", last_idnum); + if (show_original_ids) + printf("original-oid %s\n", oid_to_hex(oid)); + printf("data %"PRIuMAX"\n", (uintmax_t)size); if (size && fwrite(buf, size, 1, stdout) != 1) die_errno("could not write blob '%s'", oid_to_hex(oid)); printf("\n"); @@ -330,17 +352,18 @@ static void print_path(const char *path) static void *generate_fake_oid(const void *old, size_t *len) { - static uint32_t counter = 1; /* avoid null sha1 */ - unsigned char *out = xcalloc(GIT_SHA1_RAWSZ, 1); - put_be32(out + GIT_SHA1_RAWSZ - 4, counter++); + static uint32_t counter = 1; /* avoid null oid */ + const unsigned hashsz = the_hash_algo->rawsz; + unsigned char *out = xcalloc(hashsz, 1); + put_be32(out + hashsz - 4, counter++); return out; } -static const unsigned char *anonymize_sha1(const struct object_id *oid) +static const struct object_id *anonymize_oid(const struct object_id *oid) { - static struct hashmap sha1s; - size_t len = GIT_SHA1_RAWSZ; - return anonymize_mem(&sha1s, generate_fake_oid, oid, &len); + static struct hashmap objs; + size_t len = the_hash_algo->rawsz; + return anonymize_mem(&objs, generate_fake_oid, oid, &len); } static void show_filemodify(struct diff_queue_struct *q, @@ -399,9 +422,9 @@ static void show_filemodify(struct diff_queue_struct *q, */ if (no_data || S_ISGITLINK(spec->mode)) printf("M %06o %s ", spec->mode, - sha1_to_hex(anonymize ? - anonymize_sha1(&spec->oid) : - spec->oid.hash)); + oid_to_hex(anonymize ? + anonymize_oid(&spec->oid) : + &spec->oid)); else { struct object *object = lookup_object(the_repository, spec->oid.hash); @@ -579,7 +602,8 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, message += 2; if (commit->parents && - get_object_mark(&commit->parents->item->object) != 0 && + (get_object_mark(&commit->parents->item->object) != 0 || + reference_excluded_commits) && !full_tree) { parse_commit_or_die(commit->parents->item); diff_tree_oid(get_commit_tree_oid(commit->parents->item), @@ -595,6 +619,13 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, export_blob(&diff_queued_diff.queue[i]->two->oid); refname = *revision_sources_at(&revision_sources, commit); + /* + * FIXME: string_list_remove() below for each ref is overall + * O(N^2). Compared to a history walk and diffing trees, this is + * just lost in the noise in practice. However, theoretically a + * repo may have enough refs for this to become slow. + */ + string_list_remove(&extra_refs, refname, 0); if (anonymize) { refname = anonymize_refname(refname); anonymize_ident_line(&committer, &committer_end); @@ -608,8 +639,10 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, reencoded = reencode_string(message, "UTF-8", encoding); if (!commit->parents) printf("reset %s\n", refname); - printf("commit %s\nmark :%"PRIu32"\n%.*s\n%.*s\ndata %u\n%s", - refname, last_idnum, + printf("commit %s\nmark :%"PRIu32"\n", refname, last_idnum); + if (show_original_ids) + printf("original-oid %s\n", oid_to_hex(&commit->object.oid)); + printf("%.*s\n%.*s\ndata %u\n%s", (int)(author_end - author), author, (int)(committer_end - committer), committer, (unsigned)(reencoded @@ -620,13 +653,21 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, unuse_commit_buffer(commit, commit_buffer); for (i = 0, p = commit->parents; p; p = p->next) { - int mark = get_object_mark(&p->item->object); - if (!mark) + struct object *obj = &p->item->object; + int mark = get_object_mark(obj); + + if (!mark && !reference_excluded_commits) continue; if (i == 0) - printf("from :%d\n", mark); + printf("from "); + else + printf("merge "); + if (mark) + printf(":%d\n", mark); else - printf("merge :%d\n", mark); + printf("%s\n", oid_to_hex(anonymize ? + anonymize_oid(&obj->oid) : + &obj->oid)); i++; } @@ -727,7 +768,7 @@ static void handle_tag(const char *name, struct tag *tag) "\n-----BEGIN PGP SIGNATURE-----\n"); if (signature) switch(signed_tag_mode) { - case ABORT: + case SIGNED_TAG_ABORT: die("encountered signed tag %s; use " "--signed-tags= to handle it", oid_to_hex(&tag->object.oid)); @@ -752,7 +793,7 @@ static void handle_tag(const char *name, struct tag *tag) tagged_mark = get_object_mark(tagged); if (!tagged_mark) { switch(tag_of_filtered_mode) { - case ABORT: + case TAG_FILTERING_ABORT: die("tag %s tags unexported object; use " "--tag-of-filtered-object= to handle it", oid_to_hex(&tag->object.oid)); @@ -766,18 +807,12 @@ static void handle_tag(const char *name, struct tag *tag) oid_to_hex(&tag->object.oid), type_name(tagged->type)); } - p = (struct commit *)tagged; - for (;;) { - if (p->parents && p->parents->next) - break; - if (p->object.flags & UNINTERESTING) - break; - if (!(p->object.flags & TREESAME)) - break; - if (!p->parents) - die("can't find replacement commit for tag %s", - oid_to_hex(&tag->object.oid)); - p = p->parents->item; + p = rewrite_commit((struct commit *)tagged); + if (!p) { + printf("reset %s\nfrom %s\n\n", + name, oid_to_hex(&null_oid)); + free(buf); + return; } tagged_mark = get_object_mark(&p->object); } @@ -785,8 +820,10 @@ static void handle_tag(const char *name, struct tag *tag) if (starts_with(name, "refs/tags/")) name += 10; - printf("tag %s\nfrom :%d\n%.*s%sdata %d\n%.*s\n", - name, tagged_mark, + printf("tag %s\nfrom :%d\n", name, tagged_mark); + if (show_original_ids) + printf("original-oid %s\n", oid_to_hex(&tag->object.oid)); + printf("%.*s%sdata %d\n%.*s\n", (int)(tagger_end - tagger), tagger, tagger == tagger_end ? "" : "\n", (int)message_size, (int)message_size, message ? message : ""); @@ -804,7 +841,7 @@ static struct commit *get_commit(struct rev_cmdline_entry *e, char *full_name) /* handle nested tags */ while (tag && tag->object.type == OBJ_TAG) { parse_object(the_repository, &tag->object.oid); - string_list_append(&extra_refs, full_name)->util = tag; + string_list_append(&tag_refs, full_name)->util = tag; tag = (struct tag *)tag->tagged; } if (!tag) @@ -863,25 +900,30 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info) } /* - * This ref will not be updated through a commit, lets make - * sure it gets properly updated eventually. + * Make sure this ref gets properly updated eventually, whether + * through a commit or manually at the end. */ - if (*revision_sources_at(&revision_sources, commit) || - commit->object.flags & SHOWN) + if (e->item->type != OBJ_TAG) string_list_append(&extra_refs, full_name)->util = commit; + if (!*revision_sources_at(&revision_sources, commit)) *revision_sources_at(&revision_sources, commit) = full_name; } + + string_list_sort(&extra_refs); + string_list_remove_duplicates(&extra_refs, 0); } -static void handle_tags_and_duplicates(void) +static void handle_tags_and_duplicates(struct string_list *extras) { struct commit *commit; int i; - for (i = extra_refs.nr - 1; i >= 0; i--) { - const char *name = extra_refs.items[i].string; - struct object *object = extra_refs.items[i].util; + for (i = extras->nr - 1; i >= 0; i--) { + const char *name = extras->items[i].string; + struct object *object = extras->items[i].util; + int mark; + switch (object->type) { case OBJ_TAG: handle_tag(name, (struct tag *)object); @@ -890,9 +932,45 @@ static void handle_tags_and_duplicates(void) if (anonymize) name = anonymize_refname(name); /* create refs pointing to already seen commits */ - commit = (struct commit *)object; - printf("reset %s\nfrom :%d\n\n", name, - get_object_mark(&commit->object)); + commit = rewrite_commit((struct commit *)object); + if (!commit) { + /* + * Neither this object nor any of its + * ancestors touch any relevant paths, so + * it has been filtered to nothing. Delete + * it. + */ + printf("reset %s\nfrom %s\n\n", + name, oid_to_hex(&null_oid)); + continue; + } + + mark = get_object_mark(&commit->object); + if (!mark) { + /* + * Getting here means we have a commit which + * was excluded by a negative refspec (e.g. + * fast-export ^master master). If we are + * referencing excluded commits, set the ref + * to the exact commit. Otherwise, the user + * wants the branch exported but every commit + * in its history to be deleted, which basically + * just means deletion of the ref. + */ + if (!reference_excluded_commits) { + /* delete the ref */ + printf("reset %s\nfrom %s\n\n", + name, oid_to_hex(&null_oid)); + continue; + } + /* set ref to commit using oid, not mark */ + printf("reset %s\nfrom %s\n\n", name, + oid_to_hex(&commit->object.oid)); + continue; + } + + printf("reset %s\nfrom :%d\n\n", name, mark + ); show_progress(); break; } @@ -988,7 +1066,7 @@ static void handle_deletes(void) continue; printf("reset %s\nfrom %s\n\n", - refspec->dst, sha1_to_hex(null_sha1)); + refspec->dst, oid_to_hex(&null_oid)); } } @@ -1024,6 +1102,11 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) OPT_STRING_LIST(0, "refspec", &refspecs_list, N_("refspec"), N_("Apply refspec to exported refs")), OPT_BOOL(0, "anonymize", &anonymize, N_("anonymize output")), + OPT_BOOL(0, "reference-excluded-parents", + &reference_excluded_commits, N_("Reference parents which are not in fast-export stream by object id")), + OPT_BOOL(0, "show-original-ids", &show_original_ids, + N_("Show original object ids of blobs/commits")), + OPT_END() }; @@ -1080,7 +1163,8 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) } } - handle_tags_and_duplicates(); + handle_tags_and_duplicates(&extra_refs); + handle_tags_and_duplicates(&tag_refs); handle_deletes(); if (export_filename && lastimportid != last_idnum) diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index 63e69a5..153a2bd 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -55,6 +55,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) struct oid_array shallow = OID_ARRAY_INIT; struct string_list deepen_not = STRING_LIST_INIT_DUP; struct packet_reader reader; + enum protocol_version version; fetch_if_missing = 0; @@ -217,11 +218,14 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) packet_reader_init(&reader, fd[0], NULL, 0, PACKET_READ_CHOMP_NEWLINE | - PACKET_READ_GENTLE_ON_EOF); + PACKET_READ_GENTLE_ON_EOF | + PACKET_READ_DIE_ON_ERR_PACKET); - switch (discover_version(&reader)) { + version = discover_version(&reader); + switch (version) { case protocol_v2: - die("support for protocol v2 not implemented yet"); + get_remote_refs(fd[1], &reader, &ref, 0, NULL, NULL); + break; case protocol_v1: case protocol_v0: get_remote_heads(&reader, &ref, 0, NULL, &shallow); @@ -231,7 +235,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) } ref = fetch_pack(&args, fd, conn, ref, dest, sought, nr_sought, - &shallow, pack_lockfile_ptr, protocol_v0); + &shallow, pack_lockfile_ptr, version); if (pack_lockfile) { printf("lock %s\n", pack_lockfile); fflush(stdout); diff --git a/builtin/fetch.c b/builtin/fetch.c index e014032..b620fd5 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -317,8 +317,7 @@ static void find_non_local_tags(const struct ref *refs, !has_object_file_with_flags(&ref->old_oid, OBJECT_INFO_QUICK) && !will_fetch(head, ref->old_oid.hash) && - !has_sha1_file_with_flags(item->oid.hash, - OBJECT_INFO_QUICK) && + !has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) && !will_fetch(head, item->oid.hash)) oidclr(&item->oid); item = NULL; @@ -332,7 +331,7 @@ static void find_non_local_tags(const struct ref *refs, * fetch. */ if (item && - !has_sha1_file_with_flags(item->oid.hash, OBJECT_INFO_QUICK) && + !has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) && !will_fetch(head, item->oid.hash)) oidclr(&item->oid); @@ -353,7 +352,7 @@ static void find_non_local_tags(const struct ref *refs, * checked to see if it needs fetching. */ if (item && - !has_sha1_file_with_flags(item->oid.hash, OBJECT_INFO_QUICK) && + !has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) && !will_fetch(head, item->oid.hash)) oidclr(&item->oid); @@ -629,9 +628,14 @@ static int find_and_replace(struct strbuf *haystack, const char *needle, const char *placeholder) { - const char *p = strstr(haystack->buf, needle); + const char *p = NULL; int plen, nlen; + nlen = strlen(needle); + if (ends_with(haystack->buf, needle)) + p = haystack->buf + haystack->len - nlen; + else + p = strstr(haystack->buf, needle); if (!p) return 0; @@ -639,7 +643,6 @@ static int find_and_replace(struct strbuf *haystack, return 0; plen = strlen(p); - nlen = strlen(needle); if (plen > nlen && p[nlen] != '/') return 0; @@ -763,9 +766,6 @@ static int update_local_ref(struct ref *ref, what = _("[new ref]"); } - if ((recurse_submodules != RECURSE_SUBMODULES_OFF) && - (recurse_submodules != RECURSE_SUBMODULES_ON)) - check_for_new_submodule_commits(&ref->new_oid); r = s_update_ref(msg, ref, 0); format_display(display, r ? '!' : '*', what, r ? _("unable to update local ref") : NULL, @@ -779,9 +779,6 @@ static int update_local_ref(struct ref *ref, strbuf_add_unique_abbrev(&quickref, ¤t->object.oid, DEFAULT_ABBREV); strbuf_addstr(&quickref, ".."); strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV); - if ((recurse_submodules != RECURSE_SUBMODULES_OFF) && - (recurse_submodules != RECURSE_SUBMODULES_ON)) - check_for_new_submodule_commits(&ref->new_oid); r = s_update_ref("fast-forward", ref, 1); format_display(display, r ? '!' : ' ', quickref.buf, r ? _("unable to update local ref") : NULL, @@ -794,9 +791,6 @@ static int update_local_ref(struct ref *ref, strbuf_add_unique_abbrev(&quickref, ¤t->object.oid, DEFAULT_ABBREV); strbuf_addstr(&quickref, "..."); strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV); - if ((recurse_submodules != RECURSE_SUBMODULES_OFF) && - (recurse_submodules != RECURSE_SUBMODULES_ON)) - check_for_new_submodule_commits(&ref->new_oid); r = s_update_ref("forced-update", ref, 1); format_display(display, r ? '!' : '+', quickref.buf, r ? _("unable to update local ref") : _("forced update"), @@ -892,6 +886,8 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, ref->force = rm->peer_ref->force; } + if (recurse_submodules != RECURSE_SUBMODULES_OFF) + check_for_new_submodule_commits(&rm->old_oid); if (!strcmp(rm->name, "HEAD")) { kind = ""; @@ -1172,6 +1168,7 @@ static void add_negotiation_tips(struct git_transport_options *smart_options) static struct transport *prepare_transport(struct remote *remote, int deepen) { struct transport *transport; + transport = transport_get(remote, NULL); transport_set_verbosity(transport, verbosity, progress); transport->family = family; @@ -1191,9 +1188,13 @@ static struct transport *prepare_transport(struct remote *remote, int deepen) if (update_shallow) set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes"); if (filter_options.choice) { + struct strbuf expanded_filter_spec = STRBUF_INIT; + expand_list_objects_filter_spec(&filter_options, + &expanded_filter_spec); set_option(transport, TRANS_OPT_LIST_OBJECTS_FILTER, - filter_options.filter_spec); + expanded_filter_spec.buf); set_option(transport, TRANS_OPT_FROM_PROMISOR, "1"); + strbuf_release(&expanded_filter_spec); } if (negotiation_tip.nr) { if (transport->smart_options) @@ -1478,7 +1479,8 @@ static inline void fetch_one_setup_partial(struct remote *remote) */ if (strcmp(remote->name, repository_format_partial_clone)) { if (filter_options.choice) - die(_("--filter can only be used with the remote configured in core.partialClone")); + die(_("--filter can only be used with the remote " + "configured in extensions.partialClone")); return; } @@ -1646,7 +1648,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) result = fetch_one(remote, argc, argv, prune_tags_ok); } else { if (filter_options.choice) - die(_("--filter can only be used with the remote configured in core.partialClone")); + die(_("--filter can only be used with the remote " + "configured in extensions.partialclone")); /* TODO should this also die if we have a previous partial-clone? */ result = fetch_multiple(&list); } diff --git a/builtin/fsck.c b/builtin/fsck.c index 3c3e0f0..bb4227b 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -1,3 +1,4 @@ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "builtin.h" #include "cache.h" #include "repository.h" @@ -51,16 +52,24 @@ static int name_objects; static const char *describe_object(struct object *obj) { - static struct strbuf buf = STRBUF_INIT; - char *name = name_objects ? - lookup_decoration(fsck_walk_options.object_names, obj) : NULL; + static struct strbuf bufs[] = { + STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT + }; + static int b = 0; + struct strbuf *buf; + char *name = NULL; - strbuf_reset(&buf); - strbuf_addstr(&buf, oid_to_hex(&obj->oid)); + if (name_objects) + name = lookup_decoration(fsck_walk_options.object_names, obj); + + buf = bufs + b; + b = (b + 1) % ARRAY_SIZE(bufs); + strbuf_reset(buf); + strbuf_addstr(buf, oid_to_hex(&obj->oid)); if (name) - strbuf_addf(&buf, " (%s)", name); + strbuf_addf(buf, " (%s)", name); - return buf.buf; + return buf->buf; } static const char *printable_type(struct object *obj) @@ -76,7 +85,7 @@ static const char *printable_type(struct object *obj) ret = type_name(obj->type); if (!ret) - ret = "unknown"; + ret = _("unknown"); return ret; } @@ -104,25 +113,32 @@ static int fsck_config(const char *var, const char *value, void *cb) return git_default_config(var, value, cb); } -static void objreport(struct object *obj, const char *msg_type, - const char *err) -{ - fprintf(stderr, "%s in %s %s: %s\n", - msg_type, printable_type(obj), describe_object(obj), err); -} - static int objerror(struct object *obj, const char *err) { errors_found |= ERROR_OBJECT; - objreport(obj, "error", err); + /* TRANSLATORS: e.g. error in tree 01bfda: */ + fprintf_ln(stderr, _("error in %s %s: %s"), + printable_type(obj), describe_object(obj), err); return -1; } static int fsck_error_func(struct fsck_options *o, struct object *obj, int type, const char *message) { - objreport(obj, (type == FSCK_WARN) ? "warning" : "error", message); - return (type == FSCK_WARN) ? 0 : 1; + switch (type) { + case FSCK_WARN: + /* TRANSLATORS: e.g. warning in tree 01bfda: */ + fprintf_ln(stderr, _("warning in %s %s: %s"), + printable_type(obj), describe_object(obj), message); + return 0; + case FSCK_ERROR: + /* TRANSLATORS: e.g. error in tree 01bfda: */ + fprintf_ln(stderr, _("error in %s %s: %s"), + printable_type(obj), describe_object(obj), message); + return 1; + default: + BUG("%d (FSCK_IGNORE?) should never trigger this callback", type); + } } static struct object_array pending; @@ -138,17 +154,18 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt */ if (!obj) { /* ... these references to parent->fld are safe here */ - printf("broken link from %7s %s\n", - printable_type(parent), describe_object(parent)); - printf("broken link from %7s %s\n", - (type == OBJ_ANY ? "unknown" : type_name(type)), "unknown"); + printf_ln(_("broken link from %7s %s"), + printable_type(parent), describe_object(parent)); + printf_ln(_("broken link from %7s %s"), + (type == OBJ_ANY ? _("unknown") : type_name(type)), + _("unknown")); errors_found |= ERROR_REACHABLE; return 1; } if (type != OBJ_ANY && obj->type != type) /* ... and the reference to parent is safe here */ - objerror(parent, "wrong object type in link"); + objerror(parent, _("wrong object type in link")); if (obj->flags & REACHABLE) return 0; @@ -164,10 +181,12 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt if (!(obj->flags & HAS_OBJ)) { if (parent && !has_object_file(&obj->oid)) { - printf("broken link from %7s %s\n", - printable_type(parent), describe_object(parent)); - printf(" to %7s %s\n", - printable_type(obj), describe_object(obj)); + printf_ln(_("broken link from %7s %s\n" + " to %7s %s"), + printable_type(parent), + describe_object(parent), + printable_type(obj), + describe_object(obj)); errors_found |= ERROR_REACHABLE; } return 1; @@ -231,8 +250,8 @@ static void check_reachable_object(struct object *obj) return; if (has_object_pack(&obj->oid)) return; /* it is in pack - forget about it */ - printf("missing %s %s\n", printable_type(obj), - describe_object(obj)); + printf_ln(_("missing %s %s"), printable_type(obj), + describe_object(obj)); errors_found |= ERROR_REACHABLE; return; } @@ -257,8 +276,8 @@ static void check_unreachable_object(struct object *obj) * since this is something that is prunable. */ if (show_unreachable) { - printf("unreachable %s %s\n", printable_type(obj), - describe_object(obj)); + printf_ln(_("unreachable %s %s"), printable_type(obj), + describe_object(obj)); return; } @@ -276,8 +295,8 @@ static void check_unreachable_object(struct object *obj) */ if (!(obj->flags & USED)) { if (show_dangling) - printf("dangling %s %s\n", printable_type(obj), - describe_object(obj)); + printf_ln(_("dangling %s %s"), printable_type(obj), + describe_object(obj)); if (write_lost_and_found) { char *filename = git_pathdup("lost-found/%s/%s", obj->type == OBJ_COMMIT ? "commit" : "other", @@ -285,18 +304,18 @@ static void check_unreachable_object(struct object *obj) FILE *f; if (safe_create_leading_directories_const(filename)) { - error("Could not create lost-found"); + error(_("could not create lost-found")); free(filename); return; } f = xfopen(filename, "w"); if (obj->type == OBJ_BLOB) { if (stream_blob_to_fd(fileno(f), &obj->oid, NULL, 1)) - die_errno("Could not write '%s'", filename); + die_errno(_("could not write '%s'"), filename); } else fprintf(f, "%s\n", describe_object(obj)); if (fclose(f)) - die_errno("Could not finish '%s'", + die_errno(_("could not finish '%s'"), filename); free(filename); } @@ -313,7 +332,7 @@ static void check_unreachable_object(struct object *obj) static void check_object(struct object *obj) { if (verbose) - fprintf(stderr, "Checking %s\n", describe_object(obj)); + fprintf_ln(stderr, _("Checking %s"), describe_object(obj)); if (obj->flags & REACHABLE) check_reachable_object(obj); @@ -331,7 +350,7 @@ static void check_connectivity(void) /* Look up all the requirements, warn about missing objects.. */ max = get_max_object_index(); if (verbose) - fprintf(stderr, "Checking connectivity (%d objects)\n", max); + fprintf_ln(stderr, _("Checking connectivity (%d objects)"), max); for (i = 0; i < max; i++) { struct object *obj = get_indexed_object(i); @@ -350,11 +369,11 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size) obj->flags |= SEEN; if (verbose) - fprintf(stderr, "Checking %s %s\n", - printable_type(obj), describe_object(obj)); + fprintf_ln(stderr, _("Checking %s %s"), + printable_type(obj), describe_object(obj)); if (fsck_walk(obj, NULL, &fsck_obj_options)) - objerror(obj, "broken links"); + objerror(obj, _("broken links")); err = fsck_object(obj, buffer, size, &fsck_obj_options); if (err) goto out; @@ -363,17 +382,19 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size) struct commit *commit = (struct commit *) obj; if (!commit->parents && show_root) - printf("root %s\n", describe_object(&commit->object)); + printf_ln(_("root %s"), + describe_object(&commit->object)); } if (obj->type == OBJ_TAG) { struct tag *tag = (struct tag *) obj; if (show_tags && tag->tagged) { - printf("tagged %s %s", printable_type(tag->tagged), - describe_object(tag->tagged)); - printf(" (%s) in %s\n", tag->tag, - describe_object(&tag->object)); + printf_ln(_("tagged %s %s (%s) in %s"), + printable_type(tag->tagged), + describe_object(tag->tagged), + tag->tag, + describe_object(&tag->object)); } } @@ -381,7 +402,8 @@ out: if (obj->type == OBJ_TREE) free_tree_buffer((struct tree *)obj); if (obj->type == OBJ_COMMIT) - free_commit_buffer((struct commit *)obj); + free_commit_buffer(the_repository->parsed_objects, + (struct commit *)obj); return err; } @@ -397,7 +419,8 @@ static int fsck_obj_buffer(const struct object_id *oid, enum object_type type, eaten); if (!obj) { errors_found |= ERROR_OBJECT; - return error("%s: object corrupt or missing", oid_to_hex(oid)); + return error(_("%s: object corrupt or missing"), + oid_to_hex(oid)); } obj->flags &= ~(REACHABLE | SEEN); obj->flags |= HAS_OBJ; @@ -421,7 +444,8 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid, obj->flags |= USED; mark_object_reachable(obj); } else if (!is_promisor_object(oid)) { - error("%s: invalid reflog entry %s", refname, oid_to_hex(oid)); + error(_("%s: invalid reflog entry %s"), + refname, oid_to_hex(oid)); errors_found |= ERROR_REACHABLE; } } @@ -434,8 +458,8 @@ static int fsck_handle_reflog_ent(struct object_id *ooid, struct object_id *noid const char *refname = cb_data; if (verbose) - fprintf(stderr, "Checking reflog %s->%s\n", - oid_to_hex(ooid), oid_to_hex(noid)); + fprintf_ln(stderr, _("Checking reflog %s->%s"), + oid_to_hex(ooid), oid_to_hex(noid)); fsck_handle_reflog_oid(refname, ooid, 0); fsck_handle_reflog_oid(refname, noid, timestamp); @@ -468,13 +492,14 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid, default_refs++; return 0; } - error("%s: invalid sha1 pointer %s", refname, oid_to_hex(oid)); + error(_("%s: invalid sha1 pointer %s"), + refname, oid_to_hex(oid)); errors_found |= ERROR_REACHABLE; /* We'll continue with the rest despite the error.. */ return 0; } if (obj->type != OBJ_COMMIT && is_branch(refname)) { - error("%s: not a commit", refname); + error(_("%s: not a commit"), refname); errors_found |= ERROR_REFS; } default_refs++; @@ -529,7 +554,7 @@ static void get_default_heads(void) * "show_unreachable" flag. */ if (!default_refs) { - fprintf(stderr, "notice: No default references\n"); + fprintf_ln(stderr, _("notice: No default references")); show_unreachable = 0; } } @@ -544,7 +569,7 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data) if (read_loose_object(path, oid, &type, &size, &contents) < 0) { errors_found |= ERROR_OBJECT; - error("%s: object corrupt or missing: %s", + error(_("%s: object corrupt or missing: %s"), oid_to_hex(oid), path); return 0; /* keep checking other objects */ } @@ -557,7 +582,7 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data) if (!obj) { errors_found |= ERROR_OBJECT; - error("%s: object could not be parsed: %s", + error(_("%s: object could not be parsed: %s"), oid_to_hex(oid), path); if (!eaten) free(contents); @@ -577,7 +602,7 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data) static int fsck_cruft(const char *basename, const char *path, void *data) { if (!starts_with(basename, "tmp_obj_")) - fprintf(stderr, "bad sha1 file: %s\n", path); + fprintf_ln(stderr, _("bad sha1 file: %s"), path); return 0; } @@ -592,7 +617,7 @@ static void fsck_object_dir(const char *path) struct progress *progress = NULL; if (verbose) - fprintf(stderr, "Checking object directory\n"); + fprintf_ln(stderr, _("Checking object directory")); if (show_progress) progress = start_progress(_("Checking object directories"), 256); @@ -610,29 +635,30 @@ static int fsck_head_link(const char *head_ref_name, int null_is_error = 0; if (verbose) - fprintf(stderr, "Checking %s link\n", head_ref_name); + fprintf_ln(stderr, _("Checking %s link"), head_ref_name); *head_points_at = resolve_ref_unsafe(head_ref_name, 0, head_oid, NULL); if (!*head_points_at) { errors_found |= ERROR_REFS; - return error("Invalid %s", head_ref_name); + return error(_("invalid %s"), head_ref_name); } if (!strcmp(*head_points_at, head_ref_name)) /* detached HEAD */ null_is_error = 1; else if (!starts_with(*head_points_at, "refs/heads/")) { errors_found |= ERROR_REFS; - return error("%s points to something strange (%s)", + return error(_("%s points to something strange (%s)"), head_ref_name, *head_points_at); } if (is_null_oid(head_oid)) { if (null_is_error) { errors_found |= ERROR_REFS; - return error("%s: detached HEAD points at nothing", + return error(_("%s: detached HEAD points at nothing"), head_ref_name); } - fprintf(stderr, "notice: %s points to an unborn branch (%s)\n", - head_ref_name, *head_points_at + 11); + fprintf_ln(stderr, + _("notice: %s points to an unborn branch (%s)"), + head_ref_name, *head_points_at + 11); } return 0; } @@ -643,12 +669,12 @@ static int fsck_cache_tree(struct cache_tree *it) int err = 0; if (verbose) - fprintf(stderr, "Checking cache tree\n"); + fprintf_ln(stderr, _("Checking cache tree")); if (0 <= it->entry_count) { struct object *obj = parse_object(the_repository, &it->oid); if (!obj) { - error("%s: invalid sha1 pointer in cache-tree", + error(_("%s: invalid sha1 pointer in cache-tree"), oid_to_hex(&it->oid)); errors_found |= ERROR_REFS; return 1; @@ -659,7 +685,7 @@ static int fsck_cache_tree(struct cache_tree *it) obj, xstrdup(":")); mark_object_reachable(obj); if (obj->type != OBJ_TREE) - err |= objerror(obj, "non-tree in cache-tree"); + err |= objerror(obj, _("non-tree in cache-tree")); } for (i = 0; i < it->subtree_nr; i++) err |= fsck_cache_tree(it->down[i]->cache_tree); @@ -715,7 +741,7 @@ static struct option fsck_opts[] = { int cmd_fsck(int argc, const char **argv, const char *prefix) { int i; - struct alternate_object_database *alt; + struct object_directory *odb; /* fsck knows how to handle missing promisor objects */ fetch_if_missing = 0; @@ -751,14 +777,9 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) for_each_loose_object(mark_loose_for_connectivity, NULL, 0); for_each_packed_object(mark_packed_for_connectivity, NULL, 0); } else { - struct alternate_object_database *alt_odb_list; - - fsck_object_dir(get_object_directory()); - prepare_alt_odb(the_repository); - alt_odb_list = the_repository->objects->alt_odb_list; - for (alt = alt_odb_list; alt; alt = alt->next) - fsck_object_dir(alt->path); + for (odb = the_repository->objects->odb; odb; odb = odb->next) + fsck_object_dir(odb->path); if (check_full) { struct packed_git *p; @@ -778,7 +799,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) for (p = get_all_packs(the_repository); p; p = p->next) { /* verify gives error messages itself */ - if (verify_pack(p, fsck_obj_buffer, + if (verify_pack(the_repository, + p, fsck_obj_buffer, progress, count)) errors_found |= ERROR_PACK; count += p->num_objects; @@ -800,7 +822,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) if (!obj || !(obj->flags & HAS_OBJ)) { if (is_promisor_object(&oid)) continue; - error("%s: object missing", oid_to_hex(&oid)); + error(_("%s: object missing"), oid_to_hex(&oid)); errors_found |= ERROR_OBJECT; continue; } @@ -812,7 +834,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) mark_object_reachable(obj); continue; } - error("invalid parameter: expected sha1, got '%s'", arg); + error(_("invalid parameter: expected sha1, got '%s'"), arg); errors_found |= ERROR_OBJECT; } @@ -860,15 +882,13 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) struct child_process commit_graph_verify = CHILD_PROCESS_INIT; const char *verify_argv[] = { "commit-graph", "verify", NULL, NULL, NULL }; - commit_graph_verify.argv = verify_argv; - commit_graph_verify.git_cmd = 1; - if (run_command(&commit_graph_verify)) - errors_found |= ERROR_COMMIT_GRAPH; - prepare_alt_odb(the_repository); - for (alt = the_repository->objects->alt_odb_list; alt; alt = alt->next) { + for (odb = the_repository->objects->odb; odb; odb = odb->next) { + child_process_init(&commit_graph_verify); + commit_graph_verify.argv = verify_argv; + commit_graph_verify.git_cmd = 1; verify_argv[2] = "--object-dir"; - verify_argv[3] = alt->path; + verify_argv[3] = odb->path; if (run_command(&commit_graph_verify)) errors_found |= ERROR_COMMIT_GRAPH; } @@ -878,15 +898,13 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) struct child_process midx_verify = CHILD_PROCESS_INIT; const char *midx_argv[] = { "multi-pack-index", "verify", NULL, NULL, NULL }; - midx_verify.argv = midx_argv; - midx_verify.git_cmd = 1; - if (run_command(&midx_verify)) - errors_found |= ERROR_COMMIT_GRAPH; - prepare_alt_odb(the_repository); - for (alt = the_repository->objects->alt_odb_list; alt; alt = alt->next) { + for (odb = the_repository->objects->odb; odb; odb = odb->next) { + child_process_init(&midx_verify); + midx_verify.argv = midx_argv; + midx_verify.git_cmd = 1; midx_argv[2] = "--object-dir"; - midx_argv[3] = alt->path; + midx_argv[3] = odb->path; if (run_command(&midx_verify)) errors_found |= ERROR_COMMIT_GRAPH; } diff --git a/builtin/gc.c b/builtin/gc.c index 871a56f..020f725 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -317,7 +317,7 @@ static void add_repack_all_option(struct string_list *keep_pack) static void add_repack_incremental_option(void) { - argv_array_push(&repack, "--no-write-bitmap-index"); + argv_array_push(&repack, "--no-write-bitmap-index"); } static int need_to_gc(void) @@ -659,8 +659,10 @@ int cmd_gc(int argc, const char **argv, const char *prefix) report_garbage = report_pack_garbage; reprepare_packed_git(the_repository); - if (pack_garbage.nr > 0) + if (pack_garbage.nr > 0) { + close_all_packs(the_repository->objects); clean_pack_garbage(); + } if (gc_write_commit_graph) write_commit_graph_reachable(get_object_directory(), 0, diff --git a/builtin/grep.c b/builtin/grep.c index 71df52a..580fd38 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -3,6 +3,7 @@ * * Copyright (c) 2006 Junio C Hamano */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "repository.h" #include "config.h" @@ -393,18 +394,22 @@ static void run_pager(struct grep_opt *opt, const char *prefix) exit(status); } -static int grep_cache(struct grep_opt *opt, struct repository *repo, +static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int cached); static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, struct tree_desc *tree, struct strbuf *base, int tn_len, - int check_attr, struct repository *repo); + int check_attr); -static int grep_submodule(struct grep_opt *opt, struct repository *superproject, +static int grep_submodule(struct grep_opt *opt, const struct pathspec *pathspec, const struct object_id *oid, const char *filename, const char *path) { - struct repository submodule; + struct repository subrepo; + struct repository *superproject = opt->repo; + const struct submodule *sub = submodule_from_path(superproject, + &null_oid, path); + struct grep_opt subopt; int hit; /* @@ -420,12 +425,12 @@ static int grep_submodule(struct grep_opt *opt, struct repository *superproject, return 0; } - if (repo_submodule_init(&submodule, superproject, path)) { + if (repo_submodule_init(&subrepo, superproject, sub)) { grep_read_unlock(); return 0; } - repo_read_gitmodules(&submodule); + repo_read_gitmodules(&subrepo); /* * NEEDSWORK: This adds the submodule's object directory to the list of @@ -437,9 +442,12 @@ static int grep_submodule(struct grep_opt *opt, struct repository *superproject, * store is no longer global and instead is a member of the repository * object. */ - add_to_alternates_memory(submodule.objects->objectdir); + add_to_alternates_memory(subrepo.objects->odb->path); grep_read_unlock(); + memcpy(&subopt, opt, sizeof(subopt)); + subopt.repo = &subrepo; + if (oid) { struct object *object; struct tree_desc tree; @@ -461,21 +469,22 @@ static int grep_submodule(struct grep_opt *opt, struct repository *superproject, strbuf_addch(&base, '/'); init_tree_desc(&tree, data, size); - hit = grep_tree(opt, pathspec, &tree, &base, base.len, - object->type == OBJ_COMMIT, &submodule); + hit = grep_tree(&subopt, pathspec, &tree, &base, base.len, + object->type == OBJ_COMMIT); strbuf_release(&base); free(data); } else { - hit = grep_cache(opt, &submodule, pathspec, 1); + hit = grep_cache(&subopt, pathspec, 1); } - repo_clear(&submodule); + repo_clear(&subrepo); return hit; } -static int grep_cache(struct grep_opt *opt, struct repository *repo, +static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int cached) { + struct repository *repo = opt->repo; int hit = 0; int nr; struct strbuf name = STRBUF_INIT; @@ -513,7 +522,7 @@ static int grep_cache(struct grep_opt *opt, struct repository *repo, } } else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) && submodule_path_match(repo->index, pathspec, name.buf, NULL)) { - hit |= grep_submodule(opt, repo, pathspec, NULL, ce->name, ce->name); + hit |= grep_submodule(opt, pathspec, NULL, ce->name, ce->name); } else { continue; } @@ -535,8 +544,9 @@ static int grep_cache(struct grep_opt *opt, struct repository *repo, static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, struct tree_desc *tree, struct strbuf *base, int tn_len, - int check_attr, struct repository *repo) + int check_attr) { + struct repository *repo = opt->repo; int hit = 0; enum interesting match = entry_not_interesting; struct name_entry entry; @@ -553,7 +563,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, if (match != all_entries_interesting) { strbuf_addstr(&name, base->buf + tn_len); - match = tree_entry_interesting(&entry, &name, + match = tree_entry_interesting(repo->index, + &entry, &name, 0, pathspec); strbuf_setlen(&name, name_base_len); @@ -566,7 +577,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, strbuf_add(base, entry.path, te_len); if (S_ISREG(entry.mode)) { - hit |= grep_oid(opt, entry.oid, base->buf, tn_len, + hit |= grep_oid(opt, &entry.oid, base->buf, tn_len, check_attr ? base->buf + tn_len : NULL); } else if (S_ISDIR(entry.mode)) { enum object_type type; @@ -574,18 +585,18 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, void *data; unsigned long size; - data = lock_and_read_oid_file(entry.oid, &type, &size); + data = lock_and_read_oid_file(&entry.oid, &type, &size); if (!data) die(_("unable to read tree (%s)"), - oid_to_hex(entry.oid)); + oid_to_hex(&entry.oid)); strbuf_addch(base, '/'); init_tree_desc(&sub, data, size); hit |= grep_tree(opt, pathspec, &sub, base, tn_len, - check_attr, repo); + check_attr); free(data); } else if (recurse_submodules && S_ISGITLINK(entry.mode)) { - hit |= grep_submodule(opt, repo, pathspec, entry.oid, + hit |= grep_submodule(opt, pathspec, &entry.oid, base->buf, base->buf + tn_len); } @@ -627,7 +638,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, } init_tree_desc(&tree, data, size); hit = grep_tree(opt, pathspec, &tree, &base, base.len, - obj->type == OBJ_COMMIT, the_repository); + obj->type == OBJ_COMMIT); strbuf_release(&base); free(data); return hit; @@ -644,12 +655,12 @@ static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec, for (i = 0; i < nr; i++) { struct object *real_obj; - real_obj = deref_tag(the_repository, list->objects[i].item, + real_obj = deref_tag(opt->repo, list->objects[i].item, NULL, 0); /* load the gitmodules file for this rev */ if (recurse_submodules) { - submodule_free(the_repository); + submodule_free(opt->repo); gitmodules_config_oid(&real_obj->oid); } if (grep_object(opt, pathspec, real_obj, list->objects[i].name, @@ -674,9 +685,9 @@ static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec, if (exc_std) setup_standard_excludes(&dir); - fill_directory(&dir, &the_index, pathspec); + fill_directory(&dir, opt->repo->index, pathspec); for (i = 0; i < dir.nr; i++) { - if (!dir_path_match(&the_index, dir.entries[i], pathspec, 0, NULL)) + if (!dir_path_match(opt->repo->index, dir.entries[i], pathspec, 0, NULL)) continue; hit |= grep_file(opt, dir.entries[i]->name); if (hit && opt->status_only) @@ -1014,7 +1025,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix) break; } - if (get_oid_with_context(arg, GET_OID_RECORD_PATH, + if (get_oid_with_context(the_repository, arg, + GET_OID_RECORD_PATH, &oid, &oc)) { if (seen_dashdash) die(_("unable to resolve revision: %s"), arg); @@ -1117,7 +1129,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) if (!cached) setup_work_tree(); - hit = grep_cache(&opt, the_repository, &pathspec, cached); + hit = grep_cache(&opt, &pathspec, cached); } else { if (cached) die(_("both --cached and trees are given")); diff --git a/builtin/hash-object.c b/builtin/hash-object.c index d6f06ea..e055c11 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -40,7 +40,8 @@ static void hash_fd(int fd, const char *type, const char *path, unsigned flags, if (fstat(fd, &st) < 0 || (literally ? hash_literally(&oid, fd, type, flags) - : index_fd(&the_index, &oid, fd, &st, type_from_string(type), path, flags))) + : index_fd(the_repository->index, &oid, fd, &st, + type_from_string(type), path, flags))) die((flags & HASH_WRITE_OBJECT) ? "Unable to add %s to database" : "Unable to hash %s", path); diff --git a/builtin/index-pack.c b/builtin/index-pack.c index ac1f4ea..31046c7 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -772,7 +772,7 @@ static void sha1_object(const void *data, struct object_entry *obj_entry, if (startup_info->have_repository) { read_lock(); collision_test_needed = - has_sha1_file_with_flags(oid->hash, OBJECT_INFO_QUICK); + has_object_file_with_flags(oid, OBJECT_INFO_QUICK); read_unlock(); } diff --git a/builtin/init-db.c b/builtin/init-db.c index 41faffd..93eff76 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -542,8 +542,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR * without --bare. Catch the error early. */ - git_dir = getenv(GIT_DIR_ENVIRONMENT); - work_tree = getenv(GIT_WORK_TREE_ENVIRONMENT); + git_dir = xstrdup_or_null(getenv(GIT_DIR_ENVIRONMENT)); + work_tree = xstrdup_or_null(getenv(GIT_WORK_TREE_ENVIRONMENT)); if ((!git_dir || is_bare_repository_cfg == 1) && work_tree) die(_("%s (or --work-tree=) not allowed without " "specifying %s (or --git-dir=)"), @@ -582,6 +582,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) } UNLEAK(real_git_dir); + UNLEAK(git_dir); + UNLEAK(work_tree); flags |= INIT_DB_EXIST_OK; return init_db(git_dir, real_git_dir, template_dir, flags); diff --git a/builtin/log.c b/builtin/log.c index e8e5106..5786926 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -4,6 +4,7 @@ * (C) Copyright 2006 Linus Torvalds * 2006 Junio Hamano */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "config.h" #include "refs.h" @@ -203,7 +204,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix, rev->diffopt.filter || rev->diffopt.flags.follow_renames) rev->always_show_header = 0; - if (source) { + if (source || w.source) { init_revision_sources(&revision_sources); rev->sources = &revision_sources; } @@ -397,7 +398,8 @@ static int cmd_log_walk(struct rev_info *rev) * We may show a given commit multiple times when * walking the reflogs. */ - free_commit_buffer(commit); + free_commit_buffer(the_repository->parsed_objects, + commit); free_commit_list(commit->parents); commit->parents = NULL; } @@ -508,7 +510,8 @@ static int show_blob_object(const struct object_id *oid, struct rev_info *rev, c !rev->diffopt.flags.allow_textconv) return stream_blob_to_fd(1, oid, NULL, 0); - if (get_oid_with_context(obj_name, GET_OID_RECORD_PATH, + if (get_oid_with_context(the_repository, obj_name, + GET_OID_RECORD_PATH, &oidc, &obj_context)) die(_("Not a valid object name %s"), obj_name); if (!obj_context.path || @@ -641,8 +644,9 @@ int cmd_show(int argc, const char **argv, const char *prefix) diff_get_color_opt(&rev.diffopt, DIFF_COMMIT), name, diff_get_color_opt(&rev.diffopt, DIFF_RESET)); - read_tree_recursive((struct tree *)o, "", 0, 0, &match_all, - show_tree_object, rev.diffopt.file); + read_tree_recursive(the_repository, (struct tree *)o, "", + 0, 0, &match_all, show_tree_object, + rev.diffopt.file); rev.shown_one = 1; break; case OBJ_COMMIT: @@ -1939,7 +1943,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet)) die(_("Failed to create output files")); shown = log_tree_commit(&rev, commit); - free_commit_buffer(commit); + free_commit_buffer(the_repository->parsed_objects, + commit); /* We put one extra blank line between formatted * patches and this flag is used by log-tree code diff --git a/builtin/ls-files.c b/builtin/ls-files.c index c70a9c7..29a8762 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -5,7 +5,6 @@ * * Copyright (C) Linus Torvalds, 2005 */ -#define NO_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "repository.h" #include "config.h" @@ -206,17 +205,19 @@ static void show_files(struct repository *repo, struct dir_struct *dir); static void show_submodule(struct repository *superproject, struct dir_struct *dir, const char *path) { - struct repository submodule; + struct repository subrepo; + const struct submodule *sub = submodule_from_path(superproject, + &null_oid, path); - if (repo_submodule_init(&submodule, superproject, path)) + if (repo_submodule_init(&subrepo, superproject, sub)) return; - if (repo_read_index(&submodule) < 0) + if (repo_read_index(&subrepo) < 0) die("index file corrupt"); - show_files(&submodule, dir); + show_files(&subrepo, dir); - repo_clear(&submodule); + repo_clear(&subrepo); } static void show_ce(struct repository *repo, struct dir_struct *dir, @@ -441,7 +442,7 @@ void overlay_tree_on_index(struct index_state *istate, PATHSPEC_PREFER_CWD, prefix, matchbuf); } else memset(&pathspec, 0, sizeof(pathspec)); - if (read_tree(tree, 1, &pathspec, istate)) + if (read_tree(the_repository, tree, 1, &pathspec, istate)) die("unable to read tree entries %s", tree_name); for (i = 0; i < istate->cache_nr; i++) { diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index 7d581d6..7cad3f2 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -185,5 +185,6 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) tree = parse_tree_indirect(&oid); if (!tree) die("not a tree object"); - return !!read_tree_recursive(tree, "", 0, 0, &pathspec, show_tree, NULL); + return !!read_tree_recursive(the_repository, tree, "", 0, 0, + &pathspec, show_tree, NULL); } diff --git a/builtin/merge-index.c b/builtin/merge-index.c index c99443b..38ea6ad 100644 --- a/builtin/merge-index.c +++ b/builtin/merge-index.c @@ -1,3 +1,4 @@ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "builtin.h" #include "run-command.h" diff --git a/builtin/merge-ours.c b/builtin/merge-ours.c index c84c6e0..4594507 100644 --- a/builtin/merge-ours.c +++ b/builtin/merge-ours.c @@ -7,6 +7,7 @@ * * Pretend we resolved the heads, but declare our tree trumps everybody else. */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "git-compat-util.h" #include "builtin.h" #include "diff.h" @@ -26,7 +27,7 @@ int cmd_merge_ours(int argc, const char **argv, const char *prefix) */ if (read_cache() < 0) die_errno("read_cache failed"); - if (index_differs_from("HEAD", NULL, 0)) + if (index_differs_from(the_repository, "HEAD", NULL, 0)) exit(2); exit(0); } diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c index 9b2f707..5b910e3 100644 --- a/builtin/merge-recursive.c +++ b/builtin/merge-recursive.c @@ -7,16 +7,16 @@ static const char builtin_merge_recursive_usage[] = "git %s ... -- ..."; -static const char *better_branch_name(const char *branch) +static char *better_branch_name(const char *branch) { static char githead_env[8 + GIT_MAX_HEXSZ + 1]; char *name; if (strlen(branch) != the_hash_algo->hexsz) - return branch; + return xstrdup(branch); xsnprintf(githead_env, sizeof(githead_env), "GITHEAD_%s", branch); name = getenv(githead_env); - return name ? name : branch; + return xstrdup(name ? name : branch); } int cmd_merge_recursive(int argc, const char **argv, const char *prefix) @@ -26,9 +26,10 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix) int i, failed; struct object_id h1, h2; struct merge_options o; + char *better1, *better2; struct commit *result; - init_merge_options(&o); + init_merge_options(&o, the_repository); if (argv[0] && ends_with(argv[0], "-subtree")) o.subtree_shift = ""; @@ -70,13 +71,17 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix) if (get_oid(o.branch2, &h2)) die(_("could not resolve ref '%s'"), o.branch2); - o.branch1 = better_branch_name(o.branch1); - o.branch2 = better_branch_name(o.branch2); + o.branch1 = better1 = better_branch_name(o.branch1); + o.branch2 = better2 = better_branch_name(o.branch2); if (o.verbosity >= 3) printf(_("Merging %s with %s\n"), o.branch1, o.branch2); failed = merge_recursive_generic(&o, &h1, &h2, bases_count, bases, &result); + + free(better1); + free(better2); + if (failed < 0) return 128; /* die() error code */ return failed; diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 70f6fc9..34ca025 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -1,3 +1,4 @@ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "builtin.h" #include "tree-walk.h" #include "xdiff-interface.h" @@ -76,7 +77,8 @@ static void *result(struct merge_list *entry, unsigned long *size) their = NULL; if (entry) their = entry->blob; - return merge_blobs(&the_index, path, base, our, their, size); + return merge_blobs(the_repository->index, path, + base, our, their, size); } static void *origin(struct merge_list *entry, unsigned long *size) @@ -154,15 +156,15 @@ static void show_result(void) /* An empty entry never compares same, not even to another empty entry */ static int same_entry(struct name_entry *a, struct name_entry *b) { - return a->oid && - b->oid && - oideq(a->oid, b->oid) && + return !is_null_oid(&a->oid) && + !is_null_oid(&b->oid) && + oideq(&a->oid, &b->oid) && a->mode == b->mode; } static int both_empty(struct name_entry *a, struct name_entry *b) { - return !(a->oid || b->oid); + return is_null_oid(&a->oid) && is_null_oid(&b->oid); } static struct merge_list *create_entry(unsigned stage, unsigned mode, const struct object_id *oid, const char *path) @@ -178,7 +180,7 @@ static struct merge_list *create_entry(unsigned stage, unsigned mode, const stru static char *traverse_path(const struct traverse_info *info, const struct name_entry *n) { - char *path = xmallocz(traverse_path_len(info, n)); + char *path = xmallocz(traverse_path_len(info, n) + the_hash_algo->rawsz); return make_traverse_path(path, info, n); } @@ -192,8 +194,8 @@ static void resolve(const struct traverse_info *info, struct name_entry *ours, s return; path = traverse_path(info, result); - orig = create_entry(2, ours->mode, ours->oid, path); - final = create_entry(0, result->mode, result->oid, path); + orig = create_entry(2, ours->mode, &ours->oid, path); + final = create_entry(0, result->mode, &result->oid, path); final->link = orig; @@ -217,7 +219,7 @@ static void unresolved_directory(const struct traverse_info *info, newbase = traverse_path(info, p); -#define ENTRY_OID(e) (((e)->mode && S_ISDIR((e)->mode)) ? (e)->oid : NULL) +#define ENTRY_OID(e) (((e)->mode && S_ISDIR((e)->mode)) ? &(e)->oid : NULL) buf0 = fill_tree_descriptor(t + 0, ENTRY_OID(n + 0)); buf1 = fill_tree_descriptor(t + 1, ENTRY_OID(n + 1)); buf2 = fill_tree_descriptor(t + 2, ENTRY_OID(n + 2)); @@ -243,7 +245,7 @@ static struct merge_list *link_entry(unsigned stage, const struct traverse_info path = entry->path; else path = traverse_path(info, n); - link = create_entry(stage, n->mode, n->oid, path); + link = create_entry(stage, n->mode, &n->oid, path); link->link = entry; return link; } @@ -318,7 +320,7 @@ static int threeway_callback(int n, unsigned long mask, unsigned long dirmask, s } if (same_entry(entry+0, entry+1)) { - if (entry[2].oid && !S_ISDIR(entry[2].mode)) { + if (!is_null_oid(&entry[2].oid) && !S_ISDIR(entry[2].mode)) { /* We did not touch, they modified -- take theirs */ resolve(info, entry+1, entry+2); return mask; @@ -346,7 +348,7 @@ static void merge_trees(struct tree_desc t[3], const char *base) setup_traverse_info(&info, base); info.fn = threeway_callback; - traverse_trees(3, t, &info); + traverse_trees(&the_index, 3, t, &info); } static void *get_tree_descriptor(struct tree_desc *desc, const char *rev) diff --git a/builtin/merge.c b/builtin/merge.c index c3c976d..e47d77b 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -6,6 +6,7 @@ * Based on git-merge.sh by Junio C Hamano. */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "config.h" #include "parse-options.h" @@ -128,7 +129,7 @@ static int option_read_message(struct parse_opt_ctx_t *ctx, ctx->argc--; arg = *++ctx->argv; } else - return opterror(opt, "requires a value", 0); + return error(_("option `%s' requires a value"), opt->long_name); if (buf->len) strbuf_addch(buf, '\n'); @@ -578,7 +579,7 @@ static void parse_branch_merge_options(char *bmo) argc = split_cmdline(bmo, &argv); if (argc < 0) die(_("Bad branch.%s.mergeoptions string: %s"), branch, - split_cmdline_strerror(argc)); + _(split_cmdline_strerror(argc))); REALLOC_ARRAY(argv, argc + 2); MOVE_ARRAY(argv + 1, argv, argc + 1); argc++; @@ -702,7 +703,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, return 2; } - init_merge_options(&o); + init_merge_options(&o, the_repository); if (!strcmp(strategy, "subtree")) o.subtree_shift = ""; @@ -897,7 +898,7 @@ static int suggest_conflicts(void) filename = git_path_merge_msg(the_repository); fp = xfopen(filename, "a"); - append_conflicts_hint(&msgbuf); + append_conflicts_hint(&the_index, &msgbuf); fputs(msgbuf.buf, fp); strbuf_release(&msgbuf); fclose(fp); diff --git a/builtin/mv.c b/builtin/mv.c index 80bb967..be15ba7 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -3,6 +3,7 @@ * * Copyright (C) 2006 Johannes Schindelin */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "builtin.h" #include "config.h" #include "pathspec.h" diff --git a/builtin/notes.c b/builtin/notes.c index c78b7a0..02e97f5 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -330,10 +330,10 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd) } if (!rewrite_cmd) { - commit_notes(t, msg); + commit_notes(the_repository, t, msg); free_notes(t); } else { - finish_copy_notes_for_rewrite(c, msg); + finish_copy_notes_for_rewrite(the_repository, c, msg); } strbuf_release(&buf); return ret; @@ -469,12 +469,14 @@ static int add(int argc, const char **argv, const char *prefix) write_note_data(&d, &new_note); if (add_note(t, &object, &new_note, combine_notes_overwrite)) BUG("combine_notes_overwrite failed"); - commit_notes(t, "Notes added by 'git notes add'"); + commit_notes(the_repository, t, + "Notes added by 'git notes add'"); } else { fprintf(stderr, _("Removing note for object %s\n"), oid_to_hex(&object)); remove_note(t, object.hash); - commit_notes(t, "Notes removed by 'git notes add'"); + commit_notes(the_repository, t, + "Notes removed by 'git notes add'"); } free_note_data(&d); @@ -552,7 +554,8 @@ static int copy(int argc, const char **argv, const char *prefix) if (add_note(t, &object, from_note, combine_notes_overwrite)) BUG("combine_notes_overwrite failed"); - commit_notes(t, "Notes added by 'git notes copy'"); + commit_notes(the_repository, t, + "Notes added by 'git notes copy'"); out: free_notes(t); return retval; @@ -636,7 +639,7 @@ static int append_edit(int argc, const char **argv, const char *prefix) remove_note(t, object.hash); logmsg = xstrfmt("Notes removed by 'git notes %s'", argv[0]); } - commit_notes(t, logmsg); + commit_notes(the_repository, t, logmsg); free(logmsg); free_note_data(&d); @@ -813,7 +816,7 @@ static int merge(int argc, const char **argv, const char *prefix) usage_with_options(git_notes_merge_usage, options); } - init_notes_merge_options(&o); + init_notes_merge_options(the_repository, &o); o.verbosity = verbosity + NOTES_MERGE_VERBOSITY_DEFAULT; if (do_abort) @@ -937,7 +940,8 @@ static int remove_cmd(int argc, const char **argv, const char *prefix) strbuf_release(&sb); } if (!retval) - commit_notes(t, "Notes removed by 'git notes remove'"); + commit_notes(the_repository, t, + "Notes removed by 'git notes remove'"); free_notes(t); return retval; } @@ -965,7 +969,8 @@ static int prune(int argc, const char **argv, const char *prefix) prune_notes(t, (verbose ? NOTES_PRUNE_VERBOSE : 0) | (show_only ? NOTES_PRUNE_VERBOSE|NOTES_PRUNE_DRYRUN : 0) ); if (!show_only) - commit_notes(t, "Notes removed by 'git notes prune'"); + commit_notes(the_repository, t, + "Notes removed by 'git notes prune'"); free_notes(t); return 0; } diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 411aefd..a9fac7c 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -84,6 +84,7 @@ static unsigned long pack_size_limit; static int depth = 50; static int delta_search_threads; static int pack_to_stdout; +static int sparse; static int thin; static int num_preferred_base; static struct progress *progress_state; @@ -970,7 +971,7 @@ static int no_try_delta(const char *path) if (!check) check = attr_check_initl("delta", NULL); - git_check_attr(&the_index, path, check); + git_check_attr(the_repository->index, path, check); if (ATTR_FALSE(check->items[0].value)) return 1; return 0; @@ -1334,7 +1335,7 @@ static void add_pbase_object(struct tree_desc *tree, if (cmp < 0) return; if (name[cmplen] != '/') { - add_object_entry(entry.oid, + add_object_entry(&entry.oid, object_type(entry.mode), fullname, 1); return; @@ -1345,7 +1346,7 @@ static void add_pbase_object(struct tree_desc *tree, const char *down = name+cmplen+1; int downlen = name_cmp_len(down); - tree = pbase_tree_get(entry.oid); + tree = pbase_tree_get(&entry.oid); if (!tree) return; init_tree_desc(&sub, tree->tree_data, tree->tree_size); @@ -1642,7 +1643,7 @@ static void check_object(struct object_entry *entry) /* * No choice but to fall back to the recursive delta walk - * with sha1_object_info() to find about the object type + * with oid_object_info() to find about the object type * at this point... */ give_up: @@ -1718,7 +1719,7 @@ static void drop_reused_delta(struct object_entry *entry) if (packed_object_info(the_repository, IN_PACK(entry), entry->in_pack_offset, &oi) < 0) { /* * We failed to get the info from this pack for some reason; - * fall back to sha1_object_info, which may find another copy. + * fall back to oid_object_info, which may find another copy. * And if that fails, the error will be recorded in oe_type(entry) * and dealt with in prepare_pack(). */ @@ -1901,10 +1902,10 @@ static int type_size_sort(const void *_a, const void *_b) { const struct object_entry *a = *(struct object_entry **)_a; const struct object_entry *b = *(struct object_entry **)_b; - enum object_type a_type = oe_type(a); - enum object_type b_type = oe_type(b); - unsigned long a_size = SIZE(a); - unsigned long b_size = SIZE(b); + const enum object_type a_type = oe_type(a); + const enum object_type b_type = oe_type(b); + const unsigned long a_size = SIZE(a); + const unsigned long b_size = SIZE(b); if (a_type > b_type) return -1; @@ -1919,7 +1920,7 @@ static int type_size_sort(const void *_a, const void *_b) if (a->preferred_base < b->preferred_base) return 1; if (use_delta_islands) { - int island_cmp = island_delta_cmp(&a->idx.oid, &b->idx.oid); + const int island_cmp = island_delta_cmp(&a->idx.oid, &b->idx.oid); if (island_cmp) return island_cmp; } @@ -1953,11 +1954,6 @@ static int delta_cacheable(unsigned long src_size, unsigned long trg_size, return 0; } -/* Protect access to object database */ -static pthread_mutex_t read_mutex; -#define read_lock() pthread_mutex_lock(&read_mutex) -#define read_unlock() pthread_mutex_unlock(&read_mutex) - /* Protect delta_cache_size */ static pthread_mutex_t cache_mutex; #define cache_lock() pthread_mutex_lock(&cache_mutex) @@ -1993,11 +1989,11 @@ unsigned long oe_get_size_slow(struct packing_data *pack, unsigned long used, avail, size; if (e->type_ != OBJ_OFS_DELTA && e->type_ != OBJ_REF_DELTA) { - read_lock(); + packing_data_lock(&to_pack); if (oid_object_info(the_repository, &e->idx.oid, &size) < 0) die(_("unable to get size of %s"), oid_to_hex(&e->idx.oid)); - read_unlock(); + packing_data_unlock(&to_pack); return size; } @@ -2005,7 +2001,7 @@ unsigned long oe_get_size_slow(struct packing_data *pack, if (!p) BUG("when e->type is a delta, it must belong to a pack"); - read_lock(); + packing_data_lock(&to_pack); w_curs = NULL; buf = use_pack(p, &w_curs, e->in_pack_offset, &avail); used = unpack_object_header_buffer(buf, avail, &type, &size); @@ -2014,7 +2010,7 @@ unsigned long oe_get_size_slow(struct packing_data *pack, oid_to_hex(&e->idx.oid)); unuse_pack(&w_curs); - read_unlock(); + packing_data_unlock(&to_pack); return size; } @@ -2076,9 +2072,9 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, /* Load data if not already done */ if (!trg->data) { - read_lock(); + packing_data_lock(&to_pack); trg->data = read_object_file(&trg_entry->idx.oid, &type, &sz); - read_unlock(); + packing_data_unlock(&to_pack); if (!trg->data) die(_("object %s cannot be read"), oid_to_hex(&trg_entry->idx.oid)); @@ -2089,9 +2085,9 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, *mem_usage += sz; } if (!src->data) { - read_lock(); + packing_data_lock(&to_pack); src->data = read_object_file(&src_entry->idx.oid, &type, &sz); - read_unlock(); + packing_data_unlock(&to_pack); if (!src->data) { if (src_entry->preferred_base) { static int warned = 0; @@ -2171,7 +2167,7 @@ static unsigned int check_delta_limit(struct object_entry *me, unsigned int n) struct object_entry *child = DELTA_CHILD(me); unsigned int m = n; while (child) { - unsigned int c = check_delta_limit(child, n + 1); + const unsigned int c = check_delta_limit(child, n + 1); if (m < c) m = c; child = DELTA_SIBLING(child); @@ -2226,7 +2222,7 @@ static void find_deltas(struct object_entry **list, unsigned *list_size, while (window_memory_limit && mem_usage > window_memory_limit && count > 1) { - uint32_t tail = (idx + window - count) % window; + const uint32_t tail = (idx + window - count) % window; mem_usage -= free_unpacked(array + tail); count--; } @@ -2337,9 +2333,9 @@ static void find_deltas(struct object_entry **list, unsigned *list_size, static void try_to_free_from_threads(size_t size) { - read_lock(); + packing_data_lock(&to_pack); release_pack_memory(size); - read_unlock(); + packing_data_unlock(&to_pack); } static try_to_free_t old_try_to_free_routine; @@ -2381,7 +2377,6 @@ static pthread_cond_t progress_cond; */ static void init_threaded_search(void) { - init_recursive_mutex(&read_mutex); pthread_mutex_init(&cache_mutex, NULL); pthread_mutex_init(&progress_mutex, NULL); pthread_cond_init(&progress_cond, NULL); @@ -2392,7 +2387,6 @@ static void cleanup_threaded_search(void) { set_try_to_free_routine(old_try_to_free_routine); pthread_cond_destroy(&progress_cond); - pthread_mutex_destroy(&read_mutex); pthread_mutex_destroy(&cache_mutex); pthread_mutex_destroy(&progress_mutex); } @@ -2610,7 +2604,7 @@ static void prepare_pack(int window, int depth) unsigned n; if (use_delta_islands) - resolve_tree_islands(progress, &to_pack); + resolve_tree_islands(the_repository, progress, &to_pack); get_object_details(); @@ -2710,6 +2704,10 @@ static int git_pack_config(const char *k, const char *v, void *cb) use_bitmap_index_default = git_config_bool(k, v); return 0; } + if (!strcmp(k, "pack.usesparse")) { + sparse = git_config_bool(k, v); + return 0; + } if (!strcmp(k, "pack.threads")) { delta_search_threads = git_config_int(k, v); if (delta_search_threads < 0) @@ -3084,14 +3082,16 @@ static void record_recent_commit(struct commit *commit, void *data) static void get_object_list(int ac, const char **av) { struct rev_info revs; + struct setup_revision_opt s_r_opt = { + .allow_exclude_promisor_objects = 1, + }; char line[1000]; int flags = 0; int save_warning; repo_init_revisions(the_repository, &revs, NULL); save_commit_buffer = 0; - revs.allow_exclude_promisor_objects_opt = 1; - setup_revisions(ac, av, &revs, NULL); + setup_revisions(ac, av, &revs, &s_r_opt); /* make sure shallows are read */ is_repository_shallow(the_repository); @@ -3131,11 +3131,11 @@ static void get_object_list(int ac, const char **av) return; if (use_delta_islands) - load_delta_islands(); + load_delta_islands(the_repository); if (prepare_revision_walk(&revs)) die(_("revision walk setup failed")); - mark_edges_uninteresting(&revs, show_edge); + mark_edges_uninteresting(&revs, show_edge, sparse); if (!fn_show_object) fn_show_object = show_object; @@ -3292,6 +3292,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) { OPTION_CALLBACK, 0, "unpack-unreachable", NULL, N_("time"), N_("unpack unreachable objects newer than