summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml2
-rw-r--r--.github/workflows/main.yml18
-rw-r--r--.gitignore1
-rw-r--r--.gitlab-ci.yml5
-rw-r--r--Documentation/RelNotes/2.46.2.txt23
-rw-r--r--Documentation/RelNotes/2.47.0.txt91
-rw-r--r--Documentation/config/credential.txt8
-rw-r--r--Documentation/config/reftable.txt8
-rw-r--r--Documentation/config/sendemail.txt15
-rw-r--r--Documentation/git-apply.txt9
-rw-r--r--Documentation/git-send-email.txt6
-rw-r--r--Documentation/technical/sparse-checkout.txt2
-rw-r--r--Documentation/technical/unit-tests.txt2
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--Makefile73
-rw-r--r--alias.c6
-rw-r--r--apply.c472
-rw-r--r--apply.h1
-rw-r--r--archive.c39
-rw-r--r--attr.c2
-rw-r--r--bloom.h2
-rw-r--r--branch.c5
-rw-r--r--builtin.h285
-rw-r--r--builtin/add.c119
-rw-r--r--builtin/am.c20
-rw-r--r--builtin/annotate.c9
-rw-r--r--builtin/apply.c7
-rw-r--r--builtin/archive.c7
-rw-r--r--builtin/bisect.c6
-rw-r--r--builtin/blame.c10
-rw-r--r--builtin/branch.c8
-rw-r--r--builtin/bugreport.c6
-rw-r--r--builtin/bundle.c7
-rw-r--r--builtin/cat-file.c9
-rw-r--r--builtin/check-attr.c7
-rw-r--r--builtin/check-ignore.c7
-rw-r--r--builtin/check-mailmap.c6
-rw-r--r--builtin/check-ref-format.c6
-rw-r--r--builtin/checkout--worker.c6
-rw-r--r--builtin/checkout-index.c8
-rw-r--r--builtin/checkout.c21
-rw-r--r--builtin/clean.c8
-rw-r--r--builtin/clone.c8
-rw-r--r--builtin/column.c6
-rw-r--r--builtin/commit-graph.c12
-rw-r--r--builtin/commit-tree.c8
-rw-r--r--builtin/commit.c27
-rw-r--r--builtin/config.c11
-rw-r--r--builtin/count-objects.c11
-rw-r--r--builtin/credential-cache--daemon.c11
-rw-r--r--builtin/credential-cache.c5
-rw-r--r--builtin/credential-store.c6
-rw-r--r--builtin/credential.c7
-rw-r--r--builtin/describe.c10
-rw-r--r--builtin/diagnose.c5
-rw-r--r--builtin/diff-files.c9
-rw-r--r--builtin/diff-index.c9
-rw-r--r--builtin/diff-tree.c21
-rw-r--r--builtin/diff.c9
-rw-r--r--builtin/difftool.c17
-rw-r--r--builtin/fast-export.c6
-rw-r--r--builtin/fast-import.c7
-rw-r--r--builtin/fetch-pack.c6
-rw-r--r--builtin/fetch.c7
-rw-r--r--builtin/fmt-merge-msg.c6
-rw-r--r--builtin/for-each-ref.c7
-rw-r--r--builtin/for-each-repo.c7
-rw-r--r--builtin/fsck.c7
-rw-r--r--builtin/fsmonitor--daemon.c17
-rw-r--r--builtin/gc.c68
-rw-r--r--builtin/get-tar-commit-id.c5
-rw-r--r--builtin/grep.c7
-rw-r--r--builtin/hash-object.c6
-rw-r--r--builtin/help.c9
-rw-r--r--builtin/hook.c6
-rw-r--r--builtin/index-pack.c6
-rw-r--r--builtin/init-db.c11
-rw-r--r--builtin/interpret-trailers.c7
-rw-r--r--builtin/log.c51
-rw-r--r--builtin/ls-files.c9
-rw-r--r--builtin/ls-remote.c6
-rw-r--r--builtin/ls-tree.c7
-rw-r--r--builtin/mailinfo.c6
-rw-r--r--builtin/mailsplit.c5
-rw-r--r--builtin/merge-base.c7
-rw-r--r--builtin/merge-file.c6
-rw-r--r--builtin/merge-index.c7
-rw-r--r--builtin/merge-ours.c8
-rw-r--r--builtin/merge-recursive.c7
-rw-r--r--builtin/merge-tree.c7
-rw-r--r--builtin/merge.c30
-rw-r--r--builtin/mktag.c6
-rw-r--r--builtin/mktree.c7
-rw-r--r--builtin/multi-pack-index.c11
-rw-r--r--builtin/mv.c8
-rw-r--r--builtin/name-rev.c9
-rw-r--r--builtin/notes.c31
-rw-r--r--builtin/pack-objects.c9
-rw-r--r--builtin/pack-redundant.c10
-rw-r--r--builtin/pack-refs.c7
-rw-r--r--builtin/patch-id.c99
-rw-r--r--builtin/prune-packed.c5
-rw-r--r--builtin/prune.c14
-rw-r--r--builtin/pull.c6
-rw-r--r--builtin/push.c7
-rw-r--r--builtin/range-diff.c8
-rw-r--r--builtin/read-tree.c8
-rw-r--r--builtin/rebase.c47
-rw-r--r--builtin/receive-pack.c28
-rw-r--r--builtin/reflog.c11
-rw-r--r--builtin/refs.c7
-rw-r--r--builtin/remote-ext.c5
-rw-r--r--builtin/remote-fd.c5
-rw-r--r--builtin/remote.c6
-rw-r--r--builtin/repack.c13
-rw-r--r--builtin/replace.c11
-rw-r--r--builtin/replay.c6
-rw-r--r--builtin/rerere.c8
-rw-r--r--builtin/reset.c12
-rw-r--r--builtin/rev-list.c6
-rw-r--r--builtin/rev-parse.c19
-rw-r--r--builtin/revert.c12
-rw-r--r--builtin/rm.c9
-rw-r--r--builtin/send-pack.c6
-rw-r--r--builtin/shortlog.c7
-rw-r--r--builtin/show-branch.c8
-rw-r--r--builtin/show-index.c7
-rw-r--r--builtin/show-ref.c6
-rw-r--r--builtin/sparse-checkout.c12
-rw-r--r--builtin/stash.c29
-rw-r--r--builtin/stripspace.c6
-rw-r--r--builtin/submodule--helper.c18
-rw-r--r--builtin/symbolic-ref.c6
-rw-r--r--builtin/tag.c8
-rw-r--r--builtin/unpack-file.c6
-rw-r--r--builtin/unpack-objects.c6
-rw-r--r--builtin/update-index.c12
-rw-r--r--builtin/update-ref.c7
-rw-r--r--builtin/update-server-info.c6
-rw-r--r--builtin/upload-archive.c12
-rw-r--r--builtin/upload-pack.c5
-rw-r--r--builtin/var.c7
-rw-r--r--builtin/verify-commit.c7
-rw-r--r--builtin/verify-pack.c6
-rw-r--r--builtin/verify-tag.c7
-rw-r--r--builtin/worktree.c11
-rw-r--r--builtin/write-tree.c12
-rw-r--r--bulk-checkin.c4
-rw-r--r--bundle-uri.c2
-rw-r--r--cache-tree.c5
-rw-r--r--cbtree.c2
-rwxr-xr-xci/install-dependencies.sh54
-rwxr-xr-xci/lib.sh9
-rwxr-xr-xci/run-docker-build.sh66
-rwxr-xr-xci/run-docker.sh47
-rw-r--r--commit-graph.c1
-rw-r--r--commit.c4
-rw-r--r--commit.h5
-rw-r--r--compat/mingw.c2
-rw-r--r--compat/win32/path-utils.c2
-rw-r--r--config.c57
-rw-r--r--config.h13
-rw-r--r--config.mak.dev2
-rw-r--r--contrib/buildsystems/CMakeLists.txt66
-rwxr-xr-xcontrib/git-jump/git-jump4
-rw-r--r--credential.c30
-rw-r--r--diff-no-index.c2
-rw-r--r--diff.c11
-rw-r--r--diff.h2
-rw-r--r--diffcore-rename.c4
-rw-r--r--dir.c3
-rw-r--r--environment.c237
-rw-r--r--environment.h142
-rw-r--r--fetch-pack.c2
-rw-r--r--fsmonitor-settings.c2
-rw-r--r--fsmonitor.c3
-rwxr-xr-xgit-instaweb.sh2
-rwxr-xr-xgit-p4.py4
-rw-r--r--git.c12
-rw-r--r--gpg-interface.c2
-rw-r--r--help.c5
-rw-r--r--http-backend.c2
-rw-r--r--http.c2
-rw-r--r--imap-send.c7
-rw-r--r--log-tree.c16
-rw-r--r--merge-ll.c2
-rw-r--r--merge-ort.c4
-rw-r--r--name-hash.c3
-rw-r--r--notes.c21
-rw-r--r--notes.h3
-rw-r--r--object-file.c39
-rw-r--r--object-name.c5
-rw-r--r--object-store-ll.h15
-rw-r--r--pack-write.c3
-rw-r--r--packfile.c2
-rw-r--r--pager.c7
-rw-r--r--path.c2
-rw-r--r--pathspec.c4
-rw-r--r--perl/Git.pm14
-rw-r--r--preload-index.c3
-rw-r--r--pretty.c2
-rw-r--r--prompt.c2
-rw-r--r--prune-packed.c6
-rw-r--r--read-cache-ll.h2
-rw-r--r--read-cache.c6
-rw-r--r--rebase.c2
-rw-r--r--ref-filter.c103
-rw-r--r--ref-filter.h3
-rw-r--r--refs.c44
-rw-r--r--refs.h19
-rw-r--r--refs/files-backend.c32
-rw-r--r--refs/reftable-backend.c168
-rw-r--r--reftable/reader.c1
-rw-r--r--reftable/reftable-stack.h13
-rw-r--r--reftable/reftable-tests.h14
-rw-r--r--reftable/reftable-writer.h11
-rw-r--r--reftable/stack.c38
-rw-r--r--reftable/test_framework.c27
-rw-r--r--reftable/test_framework.h61
-rw-r--r--remote.c8
-rw-r--r--remote.h2
-rw-r--r--repo-settings.c35
-rw-r--r--repo-settings.h75
-rw-r--r--repository.c40
-rw-r--r--repository.h58
-rw-r--r--revision.h2
-rw-r--r--run-command.h2
-rw-r--r--scalar.c3
-rw-r--r--server-info.c4
-rw-r--r--setup.c142
-rw-r--r--setup.h5
-rw-r--r--sideband.c2
-rw-r--r--sparse-index.c7
-rw-r--r--sparse-index.h7
-rw-r--r--statinfo.c2
-rw-r--r--submodule.c2
-rw-r--r--t/Makefile4
-rwxr-xr-xt/chainlint.pl42
-rw-r--r--t/chainlint/arithmetic-expansion.expect2
-rw-r--r--t/chainlint/block.expect8
-rw-r--r--t/chainlint/broken-chain.expect2
-rw-r--r--t/chainlint/case.expect4
-rw-r--r--t/chainlint/chain-break-false.expect2
-rw-r--r--t/chainlint/chained-block.expect2
-rw-r--r--t/chainlint/chained-subshell.expect4
-rw-r--r--t/chainlint/command-substitution.expect2
-rw-r--r--t/chainlint/complex-if-in-cuddled-loop.expect2
-rw-r--r--t/chainlint/cuddled.expect4
-rw-r--r--t/chainlint/for-loop.expect8
-rw-r--r--t/chainlint/function.expect4
-rw-r--r--t/chainlint/here-doc-body-indent.expect2
-rw-r--r--t/chainlint/here-doc-body-pathological.expect4
-rw-r--r--t/chainlint/here-doc-body.expect4
-rw-r--r--t/chainlint/here-doc-double.expect2
-rw-r--r--t/chainlint/here-doc-indent-operator.expect2
-rw-r--r--t/chainlint/here-doc-multi-line-command-subst.expect2
-rw-r--r--t/chainlint/here-doc-multi-line-string.expect2
-rw-r--r--t/chainlint/if-condition-split.expect2
-rw-r--r--t/chainlint/if-in-loop.expect4
-rw-r--r--t/chainlint/if-then-else.expect4
-rw-r--r--t/chainlint/inline-comment.expect2
-rw-r--r--t/chainlint/loop-detect-failure.expect2
-rw-r--r--t/chainlint/loop-in-if.expect8
-rw-r--r--t/chainlint/multi-line-string.expect2
-rw-r--r--t/chainlint/negated-one-liner.expect4
-rw-r--r--t/chainlint/nested-cuddled-subshell.expect6
-rw-r--r--t/chainlint/nested-here-doc.expect2
-rw-r--r--t/chainlint/nested-loop-detect-failure.expect6
-rw-r--r--t/chainlint/nested-subshell-comment.expect2
-rw-r--r--t/chainlint/nested-subshell.expect2
-rw-r--r--t/chainlint/not-heredoc.expect2
-rw-r--r--t/chainlint/one-liner-for-loop.expect2
-rw-r--r--t/chainlint/one-liner.expect6
-rw-r--r--t/chainlint/pipe.expect2
-rw-r--r--t/chainlint/semicolon.expect12
-rw-r--r--t/chainlint/subshell-here-doc.expect2
-rw-r--r--t/chainlint/subshell-one-liner.expect10
-rw-r--r--t/chainlint/token-pasting.expect8
-rw-r--r--t/chainlint/unclosed-here-doc-indent.expect2
-rw-r--r--t/chainlint/unclosed-here-doc.expect2
-rw-r--r--t/chainlint/while-loop.expect8
-rw-r--r--t/helper/test-config.c3
-rw-r--r--t/helper/test-path-utils.c2
-rw-r--r--t/helper/test-reftable.c8
-rw-r--r--t/helper/test-tool.c3
-rw-r--r--t/helper/test-tool.h1
-rw-r--r--t/interop/README7
-rwxr-xr-xt/interop/i5500-git-daemon.sh1
-rw-r--r--t/interop/interop-lib.sh8
-rwxr-xr-xt/run-test.sh2
-rwxr-xr-xt/t0032-reftable-unittest.sh16
-rwxr-xr-xt/t0211-trace2-perf.sh6
-rwxr-xr-xt/t0610-reftable-basics.sh58
-rwxr-xr-xt/t1092-sparse-checkout-compatibility.sh5
-rwxr-xr-xt/t1305-config-include.sh40
-rwxr-xr-xt/t1419-exclude-refs.sh49
-rwxr-xr-xt/t1517-outside-repo.sh2
-rwxr-xr-xt/t3400-rebase.sh8
-rwxr-xr-xt/t3413-rebase-hook.sh4
-rwxr-xr-xt/t3420-rebase-autostash.sh40
-rwxr-xr-xt/t3436-rebase-more-options.sh1
-rwxr-xr-xt/t4017-diff-retval.sh8
-rwxr-xr-xt/t4107-apply-ignore-whitespace.sh4
-rwxr-xr-xt/t4108-apply-threeway.sh40
-rwxr-xr-xt/t4124-apply-ws-rule.sh1
-rwxr-xr-xt/t4125-apply-ws-fuzz.sh1
-rwxr-xr-xt/t4138-apply-ws-expansion.sh1
-rwxr-xr-xt/t4204-patch-id.sh40
-rwxr-xr-xt/t5000-tar-tree.sh12
-rwxr-xr-xt/t5509-fetch-push-namespaces.sh9
-rwxr-xr-xt/t5512-ls-remote.sh1
-rwxr-xr-xt/t5551-http-fetch-smart.sh22
-rwxr-xr-xt/t5801-remote-helpers.sh11
-rwxr-xr-xt/t6300-for-each-ref.sh41
-rwxr-xr-xt/t6302-for-each-ref-filter.sh1
-rwxr-xr-xt/t7422-submodule-output.sh7
-rwxr-xr-xt/t7900-maintenance.sh3
-rwxr-xr-xt/t9001-send-email.sh4
-rwxr-xr-xt/t9210-scalar.sh7
-rwxr-xr-xt/t9700-perl-git.sh3
-rwxr-xr-xt/t9700/test.pl5
-rw-r--r--t/test-lib.sh2
-rw-r--r--t/unit-tests/.gitignore2
-rw-r--r--t/unit-tests/clar-generate.awk50
-rw-r--r--t/unit-tests/clar/.github/workflows/ci.yml23
-rw-r--r--t/unit-tests/clar/COPYING15
-rw-r--r--t/unit-tests/clar/README.md329
-rw-r--r--t/unit-tests/clar/clar.c842
-rw-r--r--t/unit-tests/clar/clar.h173
-rw-r--r--t/unit-tests/clar/clar/fixtures.h50
-rw-r--r--t/unit-tests/clar/clar/fs.h524
-rw-r--r--t/unit-tests/clar/clar/print.h211
-rw-r--r--t/unit-tests/clar/clar/sandbox.h159
-rw-r--r--t/unit-tests/clar/clar/summary.h143
-rwxr-xr-xt/unit-tests/clar/generate.py266
-rw-r--r--t/unit-tests/clar/test/.gitignore4
-rw-r--r--t/unit-tests/clar/test/Makefile39
-rw-r--r--t/unit-tests/clar/test/clar_test.h16
-rw-r--r--t/unit-tests/clar/test/main.c40
-rw-r--r--t/unit-tests/clar/test/main.c.sample27
-rw-r--r--t/unit-tests/clar/test/resources/test/file1
-rw-r--r--t/unit-tests/clar/test/sample.c84
-rw-r--r--t/unit-tests/ctype.c (renamed from t/unit-tests/t-ctype.c)71
-rw-r--r--t/unit-tests/lib-reftable.c93
-rw-r--r--t/unit-tests/lib-reftable.h20
-rw-r--r--t/unit-tests/strvec.c241
-rw-r--r--t/unit-tests/t-reftable-merged.c163
-rw-r--r--t/unit-tests/t-reftable-reader.c96
-rw-r--r--t/unit-tests/t-reftable-readwrite.c130
-rw-r--r--t/unit-tests/t-reftable-stack.c (renamed from reftable/stack_test.c)743
-rw-r--r--t/unit-tests/t-strvec.c211
-rw-r--r--t/unit-tests/unit-test.c47
-rw-r--r--t/unit-tests/unit-test.h10
-rw-r--r--tmp-objdir.c8
-rw-r--r--trace.c10
-rw-r--r--trace2.h1
-rw-r--r--trace2/tr2_cfg.c4
-rw-r--r--trace2/tr2_ctr.c5
-rw-r--r--transport-helper.c18
-rw-r--r--tree-diff.c3
-rw-r--r--unicode-width.h37
-rw-r--r--upload-pack.c2
-rw-r--r--userdiff.c2
-rw-r--r--worktree.c12
-rw-r--r--wt-status.c7
365 files changed, 7425 insertions, 2680 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 77346a4929..1fbdc2652b 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -9,7 +9,7 @@ freebsd_task:
DEFAULT_TEST_TARGET: prove
DEVELOPER: 1
freebsd_instance:
- image_family: freebsd-13-2
+ image_family: freebsd-13-4
memory: 2G
install_script:
pkg install -y gettext gmake perl5
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 1ee0433acc..916a64b673 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -339,8 +339,8 @@ jobs:
image: alpine
distro: alpine-latest
- jobname: linux32
- image: daald/ubuntu32:xenial
- distro: ubuntu32-16.04
+ image: i386/ubuntu:focal
+ distro: ubuntu32-20.04
- jobname: pedantic
image: fedora
distro: fedora-latest
@@ -350,27 +350,21 @@ jobs:
runs-on: ubuntu-latest
container: ${{matrix.vector.image}}
steps:
- - uses: actions/checkout@v4
- if: matrix.vector.jobname != 'linux32'
- - uses: actions/checkout@v1 # cannot be upgraded because Node.js Actions aren't supported in this container
+ - name: prepare libc6 for actions
if: matrix.vector.jobname == 'linux32'
+ run: apt -q update && apt -q -y install libc6-amd64 lib64stdc++6
+ - uses: actions/checkout@v4
- run: ci/install-dependencies.sh
- run: ci/run-build-and-tests.sh
- name: print test failures
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
run: ci/print-test-failures.sh
- name: Upload failed tests' directories
- if: failure() && env.FAILED_TEST_ARTIFACTS != '' && matrix.vector.jobname != 'linux32'
+ if: failure() && env.FAILED_TEST_ARTIFACTS != ''
uses: actions/upload-artifact@v4
with:
name: failed-tests-${{matrix.vector.jobname}}
path: ${{env.FAILED_TEST_ARTIFACTS}}
- - name: Upload failed tests' directories
- if: failure() && env.FAILED_TEST_ARTIFACTS != '' && matrix.vector.jobname == 'linux32'
- uses: actions/upload-artifact@v1 # cannot be upgraded because Node.js Actions aren't supported in this container
- with:
- name: failed-tests-${{matrix.vector.jobname}}
- path: ${{env.FAILED_TEST_ARTIFACTS}}
static-analysis:
needs: ci-config
if: needs.ci-config.outputs.enabled == 'yes'
diff --git a/.gitignore b/.gitignore
index 8caf3700c2..6687bd6db4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@
/GIT-PYTHON-VARS
/GIT-SCRIPT-DEFINES
/GIT-SPATCH-DEFINES
+/GIT-TEST-SUITES
/GIT-USER-AGENT
/GIT-VERSION-FILE
/bin-wrappers/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 2589098eff..4abfbc3e20 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -9,6 +9,8 @@ workflow:
test:linux:
image: $image
+ tags:
+ - saas-linux-medium-amd64
variables:
CUSTOM_PATH: "/custom"
before_script:
@@ -25,6 +27,9 @@ test:linux:
fi
parallel:
matrix:
+ - jobname: linux-old
+ image: ubuntu:16.04
+ CC: gcc
- jobname: linux-sha256
image: ubuntu:latest
CC: clang
diff --git a/Documentation/RelNotes/2.46.2.txt b/Documentation/RelNotes/2.46.2.txt
new file mode 100644
index 0000000000..613386878d
--- /dev/null
+++ b/Documentation/RelNotes/2.46.2.txt
@@ -0,0 +1,23 @@
+Git 2.46.2 Release Notes
+========================
+
+This release is primarily to merge changes to unbreak the 32-bit
+GitHub actions jobs we use for CI testing, so that we can release
+real fixes for the 2.46.x track after they pass CI.
+
+It also reverts the "git patch-id" change that went into 2.46.1,
+as it seems to have got a regression reported (I haven't verified,
+but it is better to keep a known breakage than adding an unintended
+regression).
+
+Other than that, a handful of minor bugfixes are included.
+
+ * In a few corner cases "git diff --exit-code" failed to report
+ "changes" (e.g., renamed without any content change), which has
+ been corrected.
+
+ * Cygwin does have /dev/tty support that is needed by things like
+ single-key input mode.
+
+ * The interpret-trailers command failed to recognise the end of the
+ message when the commit log ends in an incomplete line.
diff --git a/Documentation/RelNotes/2.47.0.txt b/Documentation/RelNotes/2.47.0.txt
index ffc0c5c4a2..fbbea257a9 100644
--- a/Documentation/RelNotes/2.47.0.txt
+++ b/Documentation/RelNotes/2.47.0.txt
@@ -65,6 +65,9 @@ UI, Workflows & Features
to discourage its use by interactive users. Add documentation to
help tool writers.
+ * "git apply --3way" learned to take "--ours" and other options.
+
+
Performance, Internal Implementation, Development Support etc.
--------------------------------------------------------------
@@ -133,6 +136,32 @@ Performance, Internal Implementation, Development Support etc.
* "git cat-file" works well with the sparse-index, and gets marked as
such.
+ * CI started failing completely for linux32 jobs, as the step to
+ upload failed test directory uses GitHub actions that is deprecated
+ and is now disabled.
+
+ * Import clar unit tests framework libgit2 folks invented for our
+ use.
+
+ * The error messages from the test script checker have been improved.
+
+ * The convention to calling into built-in command implementation has
+ been updated to pass the repository, if known, together with the
+ prefix value.
+
+ * "git apply" had custom buffer management code that predated before
+ use of strbuf got widespread, which has been updated to use strbuf,
+ which also plugged some memory leaks.
+
+ * The reftable backend learned to more efficiently handle exclude
+ patterns while enumerating the refs.
+
+ * CI updates. FreeBSD image has been updated to 13.4.
+ (merge 2eeb29702e cb/ci-freebsd-13-4 later to maint).
+
+ * Give timeout to the locking code to write to reftable, instead of
+ failing on the first failure without retrying.
+
Fixes since v2.46
-----------------
@@ -228,16 +257,70 @@ Fixes since v2.46
* In a few corner cases "git diff --exit-code" failed to report
"changes" (e.g., renamed without any content change), which has
been corrected.
- (merge 11591850dd rs/diff-exit-code-fix later to maint).
* Cygwin does have /dev/tty support that is needed by things like
single-key input mode.
- (merge 39ba986b0e rj/cygwin-has-dev-tty later to maint).
* The interpret-trailers command failed to recognise the end of the
message when the commit log ends in an incomplete line.
- (merge c02414a997 bl/trailers-and-incomplete-last-line-fix later to maint).
+
+ * "git rebase --autostash" failed to resurrect the autostashed
+ changes when the command gets aborted after giving back control
+ asking for hlep in conflict resolution.
+ (merge bf6ab087d1 pw/rebase-autostash-fix later to maint).
+
+ * The "imap-send" now allows to be compiled with NO_OPENSSL and
+ OPENSSL_SHA1 defined together.
+ (merge 997950a750 jk/no-openssl-with-openssl-sha1 later to maint).
+
+ * The support to customize build options to adjust for older versions
+ and/or older systems for the interop tests has been improved.
+ (merge 22ef5f02a8 jk/interop-test-build-options later to maint).
+
+ * Update the character width table for Unicode 16.
+ (merge 44dc651132 bb/unicode-width-table-16 later to maint).
+
+ * In Git 2.39, Git.pm stopped working in a bare repository, which has
+ been corrected.
+ (merge d3edb0bdde jk/git-pm-bare-repo-fix later to maint).
+
+ * When a remote-helper dies before Git writes to it, SIGPIPE killed
+ Git silently. We now explain the situation a bit better to the end
+ user in our error message.
+ (merge 6e7fac9bca jk/diag-unexpected-remote-helper-death later to maint).
+
+ * A few usability fixes to "git jump" (in contrib/).
+ (merge 083b82544d jk/jump-quickfix-fixes later to maint).
+
+ * "git diff --exit-code" ignored modified binary files, which has
+ been corrected.
+ (merge 9a41735af6 rs/diff-exit-code-binary later to maint).
+
+ * When a subprocess to work in a submodule spawned by "git submodule"
+ fails with SIGPIPE, the parent Git process caught the death of it,
+ but gave a generic "failed to work in that submodule", which was
+ misleading. We now behave as if the parent got SIGPIPE and die.
+ (merge 082caf527e pw/submodule-process-sigpipe later to maint).
+
+ * "git archive" with pathspec magic that uses the attribute
+ information did not work well, which has been corrected.
+ (merge 296743a7ca rs/archive-with-attr-pathspec-fix later to maint).
+
+ * Background tasks "git maintenance" runs may need to use credential
+ information when going over the network, but a credential helper
+ may work only in an interactive environment, and end up blocking a
+ scheduled task waiting for UI. Credential helpers can now behave
+ differently when they are not running interactively.
+ (merge b9183b0a02 ds/background-maintenance-with-credential later to maint).
+
+ * "git --git-dir=nowhere cmd" failed to properly notice that it
+ wasn't in any repository while processing includeIf.onbranch
+ configuration and instead crashed.
* Other code cleanup, docfix, build fix, etc.
(merge be10ac7037 jc/mailinfo-header-cleanup later to maint).
- (merge 9a36ea37ae jc/doc-skip-fetch-all-and-prefetch later to maint).
+ (merge 4460e052e0 jc/range-diff-lazy-setup later to maint).
+ (merge 0627c58e7a ak/typofixes later to maint).
+ (merge 83799f1500 jk/t9001-deflake later to maint).
+ (merge e02cc08a88 ak/typofix-2.46-maint later to maint).
+ (merge 5c5d29e1c4 ps/ci-gitlab-upgrade later to maint).
diff --git a/Documentation/config/credential.txt b/Documentation/config/credential.txt
index 0221c3e620..470482ff4c 100644
--- a/Documentation/config/credential.txt
+++ b/Documentation/config/credential.txt
@@ -9,6 +9,14 @@ credential.helper::
Note that multiple helpers may be defined. See linkgit:gitcredentials[7]
for details and examples.
+credential.interactive::
+ By default, Git and any configured credential helpers will ask for
+ user input when new credentials are required. Many of these helpers
+ will succeed based on stored credentials if those credentials are
+ still valid. To avoid the possibility of user interactivity from
+ Git, set `credential.interactive=false`. Some credential helpers
+ respect this option as well.
+
credential.useHttpPath::
When acquiring credentials, consider the "path" component of an http
or https URL to be important. Defaults to false. See
diff --git a/Documentation/config/reftable.txt b/Documentation/config/reftable.txt
index 0515727977..57087803a5 100644
--- a/Documentation/config/reftable.txt
+++ b/Documentation/config/reftable.txt
@@ -46,3 +46,11 @@ reftable.geometricFactor::
By default, the geometric sequence uses a factor of 2, meaning that for any
table, the next-biggest table must at least be twice as big. A maximum factor
of 256 is supported.
+
+reftable.lockTimeout::
+ Whenever the reftable backend appends a new table to the stack, it has
+ to lock the central "tables.list" file before updating it. This config
+ controls how long the process will wait to acquire the lock in case
+ another process has already acquired it. Value 0 means not to retry at
+ all; -1 means to try indefinitely. Default is 100 (i.e., retry for
+ 100ms).
diff --git a/Documentation/config/sendemail.txt b/Documentation/config/sendemail.txt
index 6a869d67eb..5ffcfc9f2a 100644
--- a/Documentation/config/sendemail.txt
+++ b/Documentation/config/sendemail.txt
@@ -30,6 +30,21 @@ sendemail.confirm::
in the linkgit:git-send-email[1] documentation for the meaning of these
values.
+sendemail.mailmap::
+ If true, makes linkgit:git-send-email[1] assume `--mailmap`,
+ otherwise assume `--no-mailmap`. False by default.
+
+sendemail.mailmap.file::
+ The location of a linkgit:git-send-email[1] specific augmenting
+ mailmap file. The default mailmap and `mailmap.file` are loaded
+ first. Thus, entries in this file take precedence over entries in
+ the default mailmap locations. See linkgit:gitmailmap[5].
+
+sendemail.mailmap.blob::
+ Like `sendemail.mailmap.file`, but consider the value as a reference
+ to a blob in the repository. Entries in `sendemail.mailmap.file`
+ take precedence over entries here. See linkgit:gitmailmap[5].
+
sendemail.aliasesFile::
To avoid typing long email addresses, point this to one or more
email aliases files. You must also supply `sendemail.aliasFileType`.
diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt
index 9cce68a38b..dd4a61ef28 100644
--- a/Documentation/git-apply.txt
+++ b/Documentation/git-apply.txt
@@ -9,7 +9,8 @@ git-apply - Apply a patch to files and/or to the index
SYNOPSIS
--------
[verse]
-'git apply' [--stat] [--numstat] [--summary] [--check] [--index | --intent-to-add] [--3way]
+'git apply' [--stat] [--numstat] [--summary] [--check]
+ [--index | --intent-to-add] [--3way] [--ours | --theirs | --union]
[--apply] [--no-add] [--build-fake-ancestor=<file>] [-R | --reverse]
[--allow-binary-replacement | --binary] [--reject] [-z]
[-p<n>] [-C<n>] [--inaccurate-eof] [--recount] [--cached]
@@ -92,6 +93,12 @@ OPTIONS
When used with the `--cached` option, any conflicts are left at higher stages
in the cache.
+--ours::
+--theirs::
+--union::
+ Instead of leaving conflicts in the file, resolve conflicts favouring
+ our (or their or both) side of the lines. Requires --3way.
+
--build-fake-ancestor=<file>::
Newer 'git diff' output has embedded 'index information'
for each blob to help identify the original version that
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 2e6f1d63ae..bc3ef45acb 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -414,6 +414,12 @@ exists when 'git send-email' is asked to add it (especially note that
Failure to do so may not produce the expected result in the
recipient's MUA.
+--[no-]mailmap::
+ Use the mailmap file (see linkgit:gitmailmap[5]) to map all
+ addresses to their canonical real name and email address. Additional
+ mailmap data specific to git-send-email may be provided using the
+ `sendemail.mailmap.file` or `sendemail.mailmap.blob` configuration
+ values. Defaults to `sendemail.mailmap`.
Administering
~~~~~~~~~~~~~
diff --git a/Documentation/technical/sparse-checkout.txt b/Documentation/technical/sparse-checkout.txt
index fa0d01cbda..d968659354 100644
--- a/Documentation/technical/sparse-checkout.txt
+++ b/Documentation/technical/sparse-checkout.txt
@@ -287,7 +287,7 @@ everything behaves like a dense checkout with a few exceptions (e.g. branch
checkouts and switches write fewer things, knowing the VFS will lazily
write the rest on an as-needed basis).
-Since there is no publically available VFS-related code for folks to try,
+Since there is no publicly available VFS-related code for folks to try,
the number of folks who can test such a usecase is limited.
The primary reason to note the Behavior C usecase is that as we fix things
diff --git a/Documentation/technical/unit-tests.txt b/Documentation/technical/unit-tests.txt
index 206037ffb1..5a432b7b29 100644
--- a/Documentation/technical/unit-tests.txt
+++ b/Documentation/technical/unit-tests.txt
@@ -203,6 +203,7 @@ GitHub / GitLab stars to estimate this.
:criterion: https://github.com/Snaipe/Criterion[Criterion]
:c-tap: https://github.com/rra/c-tap-harness/[C TAP]
:check: https://libcheck.github.io/check/[Check]
+:clar: https://github.com/clar-test/clar[Clar]
[format="csv",options="header",width="33%",subs="specialcharacters,attributes,quotes,macros"]
|=====
@@ -212,6 +213,7 @@ Framework,"<<license,License>>","<<vendorable-or-ubiquitous,Vendorable or ubiqui
{criterion},{mit},{false},{partial},{true},{true},{true},{true},{true},{false},{true},19,1800
{c-tap},{expat},{true},{partial},{partial},{true},{false},{true},{false},{false},{false},4,33
{check},{lgpl},{false},{partial},{true},{true},{true},{false},{false},{false},{true},17,973
+{clar},{isc},{false},{partial},{true},{true},{true},{true},{false},{false},{true},1,192
|=====
=== Additional framework candidates
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index ee71e9d8aa..38e920725c 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.46.GIT
+DEF_VER=v2.47.0-rc0
LF='
'
diff --git a/Makefile b/Makefile
index be643ef096..7344a7f725 100644
--- a/Makefile
+++ b/Makefile
@@ -911,11 +911,12 @@ TEST_SHELL_PATH = $(SHELL_PATH)
LIB_FILE = libgit.a
XDIFF_LIB = xdiff/lib.a
REFTABLE_LIB = reftable/libreftable.a
-REFTABLE_TEST_LIB = reftable/libreftable_test.a
GENERATED_H += command-list.h
GENERATED_H += config-list.h
GENERATED_H += hook-list.h
+GENERATED_H += $(UNIT_TEST_DIR)/clar-decls.h
+GENERATED_H += $(UNIT_TEST_DIR)/clar.suite
.PHONY: generated-hdrs
generated-hdrs: $(GENERATED_H)
@@ -1333,8 +1334,16 @@ THIRD_PARTY_SOURCES += compat/poll/%
THIRD_PARTY_SOURCES += compat/regex/%
THIRD_PARTY_SOURCES += sha1collisiondetection/%
THIRD_PARTY_SOURCES += sha1dc/%
+THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/%
+THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/clar/%
+
+CLAR_TEST_SUITES += ctype
+CLAR_TEST_SUITES += strvec
+CLAR_TEST_PROG = $(UNIT_TEST_BIN)/unit-tests$(X)
+CLAR_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(CLAR_TEST_SUITES))
+CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/clar/clar.o
+CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o
-UNIT_TEST_PROGRAMS += t-ctype
UNIT_TEST_PROGRAMS += t-example-decorate
UNIT_TEST_PROGRAMS += t-hash
UNIT_TEST_PROGRAMS += t-hashmap
@@ -1347,18 +1356,19 @@ UNIT_TEST_PROGRAMS += t-reftable-basics
UNIT_TEST_PROGRAMS += t-reftable-block
UNIT_TEST_PROGRAMS += t-reftable-merged
UNIT_TEST_PROGRAMS += t-reftable-pq
+UNIT_TEST_PROGRAMS += t-reftable-reader
UNIT_TEST_PROGRAMS += t-reftable-readwrite
UNIT_TEST_PROGRAMS += t-reftable-record
+UNIT_TEST_PROGRAMS += t-reftable-stack
UNIT_TEST_PROGRAMS += t-reftable-tree
UNIT_TEST_PROGRAMS += t-strbuf
UNIT_TEST_PROGRAMS += t-strcmp-offset
-UNIT_TEST_PROGRAMS += t-strvec
UNIT_TEST_PROGRAMS += t-trailer
UNIT_TEST_PROGRAMS += t-urlmatch-normalization
UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS))
-UNIT_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))
UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o
UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/lib-oid.o
+UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/lib-reftable.o
# xdiff and reftable libs may in turn depend on what is in libgit.a
GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)
@@ -2691,9 +2701,6 @@ REFTABLE_OBJS += reftable/stack.o
REFTABLE_OBJS += reftable/tree.o
REFTABLE_OBJS += reftable/writer.o
-REFTABLE_TEST_OBJS += reftable/stack_test.o
-REFTABLE_TEST_OBJS += reftable/test_framework.o
-
TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS)) $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS))
.PHONY: test-objs
@@ -2718,6 +2725,8 @@ OBJECTS += $(XDIFF_OBJS)
OBJECTS += $(FUZZ_OBJS)
OBJECTS += $(REFTABLE_OBJS) $(REFTABLE_TEST_OBJS)
OBJECTS += $(UNIT_TEST_OBJS)
+OBJECTS += $(CLAR_TEST_OBJS)
+OBJECTS += $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))
ifndef NO_CURL
OBJECTS += http.o http-walker.o remote-curl.o
@@ -2868,9 +2877,6 @@ $(XDIFF_LIB): $(XDIFF_OBJS)
$(REFTABLE_LIB): $(REFTABLE_OBJS)
$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^
-$(REFTABLE_TEST_LIB): $(REFTABLE_TEST_OBJS)
- $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^
-
export DEFAULT_EDITOR DEFAULT_PAGER
Documentation/GIT-EXCLUDED-PROGRAMS: FORCE
@@ -3220,7 +3226,7 @@ endif
test_bindir_programs := $(patsubst %,bin-wrappers/%,$(BINDIR_PROGRAMS_NEED_X) $(BINDIR_PROGRAMS_NO_X) $(TEST_PROGRAMS_NEED_X))
-all:: $(TEST_PROGRAMS) $(test_bindir_programs) $(UNIT_TEST_PROGS)
+all:: $(TEST_PROGRAMS) $(test_bindir_programs) $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG)
bin-wrappers/%: wrap-for-bin.sh
$(call mkdir_p_parent_template)
@@ -3250,15 +3256,16 @@ perf: all
t/helper/test-tool$X: $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS)) $(UNIT_TEST_DIR)/test-lib.o
-t/helper/test-%$X: t/helper/test-%.o GIT-LDFLAGS $(GITLIBS) $(REFTABLE_TEST_LIB)
+t/helper/test-%$X: t/helper/test-%.o GIT-LDFLAGS $(GITLIBS)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(filter %.a,$^) $(LIBS)
check-sha1:: t/helper/test-tool$X
t/helper/test-sha1.sh
-SP_OBJ = $(patsubst %.o,%.sp,$(OBJECTS))
+SP_SRC = $(filter-out $(THIRD_PARTY_SOURCES),$(patsubst %.o,%.c,$(OBJECTS)))
+SP_OBJ = $(patsubst %.c,%.sp,$(SP_SRC))
-$(SP_OBJ): %.sp: %.c %.o
+$(SP_OBJ): %.sp: %.c %.o $(GENERATED_H)
$(QUIET_SP)cgcc -no-compile $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) \
-Wsparse-error \
$(SPARSE_FLAGS) $(SP_EXTRA_FLAGS) $< && \
@@ -3267,7 +3274,7 @@ $(SP_OBJ): %.sp: %.c %.o
.PHONY: sparse
sparse: $(SP_OBJ)
-EXCEPT_HDRS := $(GENERATED_H) unicode-width.h compat/% xdiff/%
+EXCEPT_HDRS := $(GENERATED_H) unicode-width.h compat/% xdiff/% $(UNIT_TEST_DIR)/clar/% $(UNIT_TEST_DIR)/clar/clar/%
ifndef OPENSSL_SHA1
EXCEPT_HDRS += sha1/openssl.h
endif
@@ -3288,7 +3295,7 @@ HCC = $(HCO:hco=hcc)
@echo '#include "git-compat-util.h"' >$@
@echo '#include "$<"' >>$@
-$(HCO): %.hco: %.hcc FORCE
+$(HCO): %.hco: %.hcc $(GENERATED_H) FORCE
$(QUIET_HDR)$(CC) $(ALL_CFLAGS) -o /dev/null -c -xc $<
.PHONY: hdr-check $(HCO)
@@ -3299,7 +3306,7 @@ style:
git clang-format --style file --diff --extensions c,h
.PHONY: check
-check: $(GENERATED_H)
+check:
@if sparse; \
then \
echo >&2 "Use 'make sparse' instead"; \
@@ -3651,7 +3658,7 @@ endif
artifacts-tar:: $(ALL_COMMANDS_TO_INSTALL) $(SCRIPT_LIB) $(OTHER_PROGRAMS) \
GIT-BUILD-OPTIONS $(TEST_PROGRAMS) $(test_bindir_programs) \
- $(UNIT_TEST_PROGS) $(MOFILES)
+ $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) $(MOFILES)
$(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1) \
SHELL_PATH='$(SHELL_PATH_SQ)' PERL_PATH='$(PERL_PATH_SQ)'
test -n "$(ARTIFACTS_DIRECTORY)"
@@ -3707,11 +3714,12 @@ cocciclean:
clean: profile-clean coverage-clean cocciclean
$(RM) -r .build $(UNIT_TEST_BIN)
+ $(RM) GIT-TEST-SUITES
$(RM) po/git.pot po/git-core.pot
$(RM) git.res
$(RM) $(OBJECTS)
$(RM) headless-git.o
- $(RM) $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(REFTABLE_TEST_LIB)
+ $(RM) $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB)
$(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS)
$(RM) $(TEST_PROGRAMS)
$(RM) $(FUZZ_PROGRAMS)
@@ -3858,15 +3866,32 @@ $(FUZZ_PROGRAMS): %: %.o oss-fuzz/dummy-cmd-main.o $(GITLIBS) GIT-LDFLAGS
-Wl,--allow-multiple-definition \
$(filter %.o,$^) $(filter %.a,$^) $(LIBS) $(LIB_FUZZING_ENGINE)
-$(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o \
- $(UNIT_TEST_DIR)/test-lib.o \
- $(UNIT_TEST_DIR)/lib-oid.o \
+$(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o $(UNIT_TEST_OBJS) \
$(GITLIBS) GIT-LDFLAGS
$(call mkdir_p_parent_template)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \
$(filter %.o,$^) $(filter %.a,$^) $(LIBS)
+GIT-TEST-SUITES: FORCE
+ @FLAGS='$(CLAR_TEST_SUITES)'; \
+ if test x"$$FLAGS" != x"`cat GIT-TEST-SUITES 2>/dev/null`" ; then \
+ echo >&2 " * new test suites"; \
+ echo "$$FLAGS" >GIT-TEST-SUITES; \
+ fi
+
+$(UNIT_TEST_DIR)/clar-decls.h: $(patsubst %,$(UNIT_TEST_DIR)/%.c,$(CLAR_TEST_SUITES)) GIT-TEST-SUITES
+ $(QUIET_GEN)for suite in $(CLAR_TEST_SUITES); do \
+ sed -ne "s/^\(void test_$${suite}__[a-zA-Z_0-9][a-zA-Z_0-9]*(void)$$\)/extern \1;/p" $(UNIT_TEST_DIR)/$$suite.c; \
+ done >$@
+$(UNIT_TEST_DIR)/clar.suite: $(UNIT_TEST_DIR)/clar-decls.h
+ $(QUIET_GEN)awk -f $(UNIT_TEST_DIR)/clar-generate.awk $< >$(UNIT_TEST_DIR)/clar.suite
+$(CLAR_TEST_OBJS): $(UNIT_TEST_DIR)/clar-decls.h
+$(CLAR_TEST_OBJS): EXTRA_CPPFLAGS = -I$(UNIT_TEST_DIR)
+$(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GITLIBS) GIT-LDFLAGS
+ $(call mkdir_p_parent_template)
+ $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
+
.PHONY: build-unit-tests unit-tests
-build-unit-tests: $(UNIT_TEST_PROGS)
-unit-tests: $(UNIT_TEST_PROGS) t/helper/test-tool$X
+build-unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG)
+unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) t/helper/test-tool$X
$(MAKE) -C t/ unit-tests
diff --git a/alias.c b/alias.c
index 4daafd9bda..1a1a141a0a 100644
--- a/alias.c
+++ b/alias.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
#include "alias.h"
#include "config.h"
@@ -37,7 +39,7 @@ char *alias_lookup(const char *alias)
{
struct config_alias_data data = { alias, NULL };
- read_early_config(config_alias_cb, &data);
+ read_early_config(the_repository, config_alias_cb, &data);
return data.v;
}
@@ -46,7 +48,7 @@ void list_aliases(struct string_list *list)
{
struct config_alias_data data = { NULL, NULL, list };
- read_early_config(config_alias_cb, &data);
+ read_early_config(the_repository, config_alias_cb, &data);
}
void quote_cmdline(struct strbuf *buf, const char **argv)
diff --git a/apply.c b/apply.c
index 6e1060a952..a3fc2d5330 100644
--- a/apply.c
+++ b/apply.c
@@ -30,6 +30,7 @@
#include "path.h"
#include "quote.h"
#include "read-cache.h"
+#include "repository.h"
#include "rerere.h"
#include "apply.h"
#include "entry.h"
@@ -277,13 +278,26 @@ struct line {
* This represents a "file", which is an array of "lines".
*/
struct image {
- char *buf;
- size_t len;
- size_t nr;
- size_t alloc;
- struct line *line_allocated;
+ struct strbuf buf;
struct line *line;
+ size_t line_nr, line_alloc;
};
+#define IMAGE_INIT { \
+ .buf = STRBUF_INIT, \
+}
+
+static void image_init(struct image *image)
+{
+ struct image empty = IMAGE_INIT;
+ memcpy(image, &empty, sizeof(*image));
+}
+
+static void image_clear(struct image *image)
+{
+ strbuf_release(&image->buf);
+ free(image->line);
+ image_init(image);
+}
static uint32_t hash_line(const char *cp, size_t len)
{
@@ -297,49 +311,13 @@ static uint32_t hash_line(const char *cp, size_t len)
return h;
}
-/*
- * Compare lines s1 of length n1 and s2 of length n2, ignoring
- * whitespace difference. Returns 1 if they match, 0 otherwise
- */
-static int fuzzy_matchlines(const char *s1, size_t n1,
- const char *s2, size_t n2)
-{
- const char *end1 = s1 + n1;
- const char *end2 = s2 + n2;
-
- /* ignore line endings */
- while (s1 < end1 && (end1[-1] == '\r' || end1[-1] == '\n'))
- end1--;
- while (s2 < end2 && (end2[-1] == '\r' || end2[-1] == '\n'))
- end2--;
-
- while (s1 < end1 && s2 < end2) {
- if (isspace(*s1)) {
- /*
- * Skip whitespace. We check on both buffers
- * because we don't want "a b" to match "ab".
- */
- if (!isspace(*s2))
- return 0;
- while (s1 < end1 && isspace(*s1))
- s1++;
- while (s2 < end2 && isspace(*s2))
- s2++;
- } else if (*s1++ != *s2++)
- return 0;
- }
-
- /* If we reached the end on one side only, lines don't match. */
- return s1 == end1 && s2 == end2;
-}
-
-static void add_line_info(struct image *img, const char *bol, size_t len, unsigned flag)
+static void image_add_line(struct image *img, const char *bol, size_t len, unsigned flag)
{
- ALLOC_GROW(img->line_allocated, img->nr + 1, img->alloc);
- img->line_allocated[img->nr].len = len;
- img->line_allocated[img->nr].hash = hash_line(bol, len);
- img->line_allocated[img->nr].flag = flag;
- img->nr++;
+ ALLOC_GROW(img->line, img->line_nr + 1, img->line_alloc);
+ img->line[img->line_nr].len = len;
+ img->line[img->line_nr].hash = hash_line(bol, len);
+ img->line[img->line_nr].flag = flag;
+ img->line_nr++;
}
/*
@@ -347,37 +325,43 @@ static void add_line_info(struct image *img, const char *bol, size_t len, unsign
* attach it to "image" and add line-based index to it.
* "image" now owns the "buf".
*/
-static void prepare_image(struct image *image, char *buf, size_t len,
+static void image_prepare(struct image *image, char *buf, size_t len,
int prepare_linetable)
{
const char *cp, *ep;
- memset(image, 0, sizeof(*image));
- image->buf = buf;
- image->len = len;
+ image_clear(image);
+ strbuf_attach(&image->buf, buf, len, len + 1);
if (!prepare_linetable)
return;
- ep = image->buf + image->len;
- cp = image->buf;
+ ep = image->buf.buf + image->buf.len;
+ cp = image->buf.buf;
while (cp < ep) {
const char *next;
for (next = cp; next < ep && *next != '\n'; next++)
;
if (next < ep)
next++;
- add_line_info(image, cp, next - cp, 0);
+ image_add_line(image, cp, next - cp, 0);
cp = next;
}
- image->line = image->line_allocated;
}
-static void clear_image(struct image *image)
+static void image_remove_first_line(struct image *img)
+{
+ strbuf_remove(&img->buf, 0, img->line[0].len);
+ img->line_nr--;
+ if (img->line_nr)
+ MOVE_ARRAY(img->line, img->line + 1, img->line_nr);
+}
+
+static void image_remove_last_line(struct image *img)
{
- free(image->buf);
- free(image->line_allocated);
- memset(image, 0, sizeof(*image));
+ size_t last_line_len = img->line[img->line_nr - 1].len;
+ strbuf_setlen(&img->buf, img->buf.len - last_line_len);
+ img->line_nr--;
}
/* fmt must contain _one_ %s and no other substitution */
@@ -2326,65 +2310,43 @@ static int read_old_data(struct stat *st, struct patch *patch,
/*
* Update the preimage, and the common lines in postimage,
- * from buffer buf of length len. If postlen is 0 the postimage
- * is updated in place, otherwise it's updated on a new buffer
- * of length postlen
+ * from buffer buf of length len.
*/
-
static void update_pre_post_images(struct image *preimage,
struct image *postimage,
- char *buf,
- size_t len, size_t postlen)
+ char *buf, size_t len)
{
+ struct image fixed_preimage = IMAGE_INIT;
+ size_t insert_pos = 0;
int i, ctx, reduced;
- char *new_buf, *old_buf, *fixed;
- struct image fixed_preimage;
+ const char *fixed;
/*
* Update the preimage with whitespace fixes. Note that we
* are not losing preimage->buf -- apply_one_fragment() will
* free "oldlines".
*/
- prepare_image(&fixed_preimage, buf, len, 1);
- assert(postlen
- ? fixed_preimage.nr == preimage->nr
- : fixed_preimage.nr <= preimage->nr);
- for (i = 0; i < fixed_preimage.nr; i++)
+ image_prepare(&fixed_preimage, buf, len, 1);
+ for (i = 0; i < fixed_preimage.line_nr; i++)
fixed_preimage.line[i].flag = preimage->line[i].flag;
- free(preimage->line_allocated);
+ image_clear(preimage);
*preimage = fixed_preimage;
+ fixed = preimage->buf.buf;
/*
- * Adjust the common context lines in postimage. This can be
- * done in-place when we are shrinking it with whitespace
- * fixing, but needs a new buffer when ignoring whitespace or
- * expanding leading tabs to spaces.
- *
- * We trust the caller to tell us if the update can be done
- * in place (postlen==0) or not.
+ * Adjust the common context lines in postimage.
*/
- old_buf = postimage->buf;
- if (postlen)
- new_buf = postimage->buf = xmalloc(postlen);
- else
- new_buf = old_buf;
- fixed = preimage->buf;
-
- for (i = reduced = ctx = 0; i < postimage->nr; i++) {
+ for (i = reduced = ctx = 0; i < postimage->line_nr; i++) {
size_t l_len = postimage->line[i].len;
+
if (!(postimage->line[i].flag & LINE_COMMON)) {
/* an added line -- no counterparts in preimage */
- memmove(new_buf, old_buf, l_len);
- old_buf += l_len;
- new_buf += l_len;
+ insert_pos += l_len;
continue;
}
- /* a common context -- skip it in the original postimage */
- old_buf += l_len;
-
/* and find the corresponding one in the fixed preimage */
- while (ctx < preimage->nr &&
+ while (ctx < preimage->line_nr &&
!(preimage->line[ctx].flag & LINE_COMMON)) {
fixed += preimage->line[ctx].len;
ctx++;
@@ -2394,29 +2356,59 @@ static void update_pre_post_images(struct image *preimage,
* preimage is expected to run out, if the caller
* fixed addition of trailing blank lines.
*/
- if (preimage->nr <= ctx) {
+ if (preimage->line_nr <= ctx) {
reduced++;
continue;
}
/* and copy it in, while fixing the line length */
l_len = preimage->line[ctx].len;
- memcpy(new_buf, fixed, l_len);
- new_buf += l_len;
+ strbuf_splice(&postimage->buf, insert_pos, postimage->line[i].len,
+ fixed, l_len);
+ insert_pos += l_len;
fixed += l_len;
postimage->line[i].len = l_len;
ctx++;
}
- if (postlen
- ? postlen < new_buf - postimage->buf
- : postimage->len < new_buf - postimage->buf)
- BUG("caller miscounted postlen: asked %d, orig = %d, used = %d",
- (int)postlen, (int) postimage->len, (int)(new_buf - postimage->buf));
-
/* Fix the length of the whole thing */
- postimage->len = new_buf - postimage->buf;
- postimage->nr -= reduced;
+ postimage->line_nr -= reduced;
+}
+
+/*
+ * Compare lines s1 of length n1 and s2 of length n2, ignoring
+ * whitespace difference. Returns 1 if they match, 0 otherwise
+ */
+static int fuzzy_matchlines(const char *s1, size_t n1,
+ const char *s2, size_t n2)
+{
+ const char *end1 = s1 + n1;
+ const char *end2 = s2 + n2;
+
+ /* ignore line endings */
+ while (s1 < end1 && (end1[-1] == '\r' || end1[-1] == '\n'))
+ end1--;
+ while (s2 < end2 && (end2[-1] == '\r' || end2[-1] == '\n'))
+ end2--;
+
+ while (s1 < end1 && s2 < end2) {
+ if (isspace(*s1)) {
+ /*
+ * Skip whitespace. We check on both buffers
+ * because we don't want "a b" to match "ab".
+ */
+ if (!isspace(*s2))
+ return 0;
+ while (s1 < end1 && isspace(*s1))
+ s1++;
+ while (s2 < end2 && isspace(*s2))
+ s2++;
+ } else if (*s1++ != *s2++)
+ return 0;
+ }
+
+ /* If we reached the end on one side only, lines don't match. */
+ return s1 == end1 && s2 == end2;
}
static int line_by_line_fuzzy_match(struct image *img,
@@ -2429,7 +2421,6 @@ static int line_by_line_fuzzy_match(struct image *img,
int i;
size_t imgoff = 0;
size_t preoff = 0;
- size_t postlen = postimage->len;
size_t extra_chars;
char *buf;
char *preimage_eof;
@@ -2442,11 +2433,9 @@ static int line_by_line_fuzzy_match(struct image *img,
size_t prelen = preimage->line[i].len;
size_t imglen = img->line[current_lno+i].len;
- if (!fuzzy_matchlines(img->buf + current + imgoff, imglen,
- preimage->buf + preoff, prelen))
+ if (!fuzzy_matchlines(img->buf.buf + current + imgoff, imglen,
+ preimage->buf.buf + preoff, prelen))
return 0;
- if (preimage->line[i].flag & LINE_COMMON)
- postlen += imglen - prelen;
imgoff += imglen;
preoff += prelen;
}
@@ -2462,10 +2451,10 @@ static int line_by_line_fuzzy_match(struct image *img,
* are whitespace characters. (This can only happen if
* we are removing blank lines at the end of the file.)
*/
- buf = preimage_eof = preimage->buf + preoff;
- for ( ; i < preimage->nr; i++)
+ buf = preimage_eof = preimage->buf.buf + preoff;
+ for ( ; i < preimage->line_nr; i++)
preoff += preimage->line[i].len;
- preimage_end = preimage->buf + preoff;
+ preimage_end = preimage->buf.buf + preoff;
for ( ; buf < preimage_end; buf++)
if (!isspace(*buf))
return 0;
@@ -2479,11 +2468,11 @@ static int line_by_line_fuzzy_match(struct image *img,
*/
extra_chars = preimage_end - preimage_eof;
strbuf_init(&fixed, imgoff + extra_chars);
- strbuf_add(&fixed, img->buf + current, imgoff);
+ strbuf_add(&fixed, img->buf.buf + current, imgoff);
strbuf_add(&fixed, preimage_eof, extra_chars);
fixed_buf = strbuf_detach(&fixed, &fixed_len);
update_pre_post_images(preimage, postimage,
- fixed_buf, fixed_len, postlen);
+ fixed_buf, fixed_len);
return 1;
}
@@ -2499,16 +2488,17 @@ static int match_fragment(struct apply_state *state,
int i;
const char *orig, *target;
struct strbuf fixed = STRBUF_INIT;
- size_t postlen;
+ char *fixed_buf;
+ size_t fixed_len;
int preimage_limit;
int ret;
- if (preimage->nr + current_lno <= img->nr) {
+ if (preimage->line_nr + current_lno <= img->line_nr) {
/*
* The hunk falls within the boundaries of img.
*/
- preimage_limit = preimage->nr;
- if (match_end && (preimage->nr + current_lno != img->nr)) {
+ preimage_limit = preimage->line_nr;
+ if (match_end && (preimage->line_nr + current_lno != img->line_nr)) {
ret = 0;
goto out;
}
@@ -2521,7 +2511,7 @@ static int match_fragment(struct apply_state *state,
* match with img, and the remainder of the preimage
* must be blank.
*/
- preimage_limit = img->nr - current_lno;
+ preimage_limit = img->line_nr - current_lno;
} else {
/*
* The hunk extends beyond the end of the img and
@@ -2546,7 +2536,7 @@ static int match_fragment(struct apply_state *state,
}
}
- if (preimage_limit == preimage->nr) {
+ if (preimage_limit == preimage->line_nr) {
/*
* Do we have an exact match? If we were told to match
* at the end, size must be exactly at current+fragsize,
@@ -2555,9 +2545,9 @@ static int match_fragment(struct apply_state *state,
* exactly.
*/
if ((match_end
- ? (current + preimage->len == img->len)
- : (current + preimage->len <= img->len)) &&
- !memcmp(img->buf + current, preimage->buf, preimage->len)) {
+ ? (current + preimage->buf.len == img->buf.len)
+ : (current + preimage->buf.len <= img->buf.len)) &&
+ !memcmp(img->buf.buf + current, preimage->buf.buf, preimage->buf.len)) {
ret = 1;
goto out;
}
@@ -2571,7 +2561,7 @@ static int match_fragment(struct apply_state *state,
*/
const char *buf, *buf_end;
- buf = preimage->buf;
+ buf = preimage->buf.buf;
buf_end = buf;
for (i = 0; i < preimage_limit; i++)
buf_end += preimage->line[i].len;
@@ -2616,21 +2606,14 @@ static int match_fragment(struct apply_state *state,
* fixed.
*/
- /* First count added lines in postimage */
- postlen = 0;
- for (i = 0; i < postimage->nr; i++) {
- if (!(postimage->line[i].flag & LINE_COMMON))
- postlen += postimage->line[i].len;
- }
-
/*
* The preimage may extend beyond the end of the file,
* but in this loop we will only handle the part of the
* preimage that falls within the file.
*/
- strbuf_grow(&fixed, preimage->len + 1);
- orig = preimage->buf;
- target = img->buf + current;
+ strbuf_grow(&fixed, preimage->buf.len + 1);
+ orig = preimage->buf.buf;
+ target = img->buf.buf + current;
for (i = 0; i < preimage_limit; i++) {
size_t oldlen = preimage->line[i].len;
size_t tgtlen = img->line[current_lno + i].len;
@@ -2659,10 +2642,6 @@ static int match_fragment(struct apply_state *state,
!memcmp(tgtfix.buf, fixed.buf + fixstart,
fixed.len - fixstart));
- /* Add the length if this is common with the postimage */
- if (preimage->line[i].flag & LINE_COMMON)
- postlen += tgtfix.len;
-
strbuf_release(&tgtfix);
if (!match) {
ret = 0;
@@ -2680,7 +2659,7 @@ static int match_fragment(struct apply_state *state,
* empty or only contain whitespace (if WS_BLANK_AT_EOL is
* false).
*/
- for ( ; i < preimage->nr; i++) {
+ for ( ; i < preimage->line_nr; i++) {
size_t fixstart = fixed.len; /* start of the fixed preimage */
size_t oldlen = preimage->line[i].len;
int j;
@@ -2704,10 +2683,9 @@ static int match_fragment(struct apply_state *state,
* has whitespace breakages unfixed, and fixing them makes the
* hunk match. Update the context lines in the postimage.
*/
- if (postlen < postimage->len)
- postlen = 0;
+ fixed_buf = strbuf_detach(&fixed, &fixed_len);
update_pre_post_images(preimage, postimage,
- fixed.buf, fixed.len, postlen);
+ fixed_buf, fixed_len);
ret = 1;
@@ -2735,7 +2713,7 @@ static int find_pos(struct apply_state *state,
* than `match_beginning`.
*/
if (state->allow_overlap && match_beginning && match_end &&
- img->nr - preimage->nr != 0)
+ img->line_nr - preimage->line_nr != 0)
match_beginning = 0;
/*
@@ -2746,15 +2724,15 @@ static int find_pos(struct apply_state *state,
if (match_beginning)
line = 0;
else if (match_end)
- line = img->nr - preimage->nr;
+ line = img->line_nr - preimage->line_nr;
/*
* Because the comparison is unsigned, the following test
* will also take care of a negative line number that can
* result when match_end and preimage is larger than the target.
*/
- if ((size_t) line > img->nr)
- line = img->nr;
+ if ((size_t) line > img->line_nr)
+ line = img->line_nr;
current = 0;
for (i = 0; i < line; i++)
@@ -2777,7 +2755,7 @@ static int find_pos(struct apply_state *state,
return current_lno;
again:
- if (backwards_lno == 0 && forwards_lno == img->nr)
+ if (backwards_lno == 0 && forwards_lno == img->line_nr)
break;
if (i & 1) {
@@ -2790,7 +2768,7 @@ static int find_pos(struct apply_state *state,
current = backwards;
current_lno = backwards_lno;
} else {
- if (forwards_lno == img->nr) {
+ if (forwards_lno == img->line_nr) {
i++;
goto again;
}
@@ -2804,19 +2782,6 @@ static int find_pos(struct apply_state *state,
return -1;
}
-static void remove_first_line(struct image *img)
-{
- img->buf += img->line[0].len;
- img->len -= img->line[0].len;
- img->line++;
- img->nr--;
-}
-
-static void remove_last_line(struct image *img)
-{
- img->len -= img->line[--img->nr].len;
-}
-
/*
* The change from "preimage" and "postimage" has been found to
* apply at applied_pos (counts in line numbers) in "img".
@@ -2834,6 +2799,7 @@ static void update_image(struct apply_state *state,
*/
int i, nr;
size_t remove_count, insert_count, applied_at = 0;
+ size_t result_alloc;
char *result;
int preimage_limit;
@@ -2846,9 +2812,9 @@ static void update_image(struct apply_state *state,
* to the number of lines in the preimage that falls
* within the boundaries.
*/
- preimage_limit = preimage->nr;
- if (preimage_limit > img->nr - applied_pos)
- preimage_limit = img->nr - applied_pos;
+ preimage_limit = preimage->line_nr;
+ if (preimage_limit > img->line_nr - applied_pos)
+ preimage_limit = img->line_nr - applied_pos;
for (i = 0; i < applied_pos; i++)
applied_at += img->line[i].len;
@@ -2856,39 +2822,36 @@ static void update_image(struct apply_state *state,
remove_count = 0;
for (i = 0; i < preimage_limit; i++)
remove_count += img->line[applied_pos + i].len;
- insert_count = postimage->len;
+ insert_count = postimage->buf.len;
/* Adjust the contents */
- result = xmalloc(st_add3(st_sub(img->len, remove_count), insert_count, 1));
- memcpy(result, img->buf, applied_at);
- memcpy(result + applied_at, postimage->buf, postimage->len);
- memcpy(result + applied_at + postimage->len,
- img->buf + (applied_at + remove_count),
- img->len - (applied_at + remove_count));
- free(img->buf);
- img->buf = result;
- img->len += insert_count - remove_count;
- result[img->len] = '\0';
+ result_alloc = st_add3(st_sub(img->buf.len, remove_count), insert_count, 1);
+ result = xmalloc(result_alloc);
+ memcpy(result, img->buf.buf, applied_at);
+ memcpy(result + applied_at, postimage->buf.buf, postimage->buf.len);
+ memcpy(result + applied_at + postimage->buf.len,
+ img->buf.buf + (applied_at + remove_count),
+ img->buf.len - (applied_at + remove_count));
+ strbuf_attach(&img->buf, result, postimage->buf.len + img->buf.len - remove_count,
+ result_alloc);
/* Adjust the line table */
- nr = img->nr + postimage->nr - preimage_limit;
- if (preimage_limit < postimage->nr) {
+ nr = img->line_nr + postimage->line_nr - preimage_limit;
+ if (preimage_limit < postimage->line_nr)
/*
- * NOTE: this knows that we never call remove_first_line()
+ * NOTE: this knows that we never call image_remove_first_line()
* on anything other than pre/post image.
*/
REALLOC_ARRAY(img->line, nr);
- img->line_allocated = img->line;
- }
- if (preimage_limit != postimage->nr)
- MOVE_ARRAY(img->line + applied_pos + postimage->nr,
+ if (preimage_limit != postimage->line_nr)
+ MOVE_ARRAY(img->line + applied_pos + postimage->line_nr,
img->line + applied_pos + preimage_limit,
- img->nr - (applied_pos + preimage_limit));
- COPY_ARRAY(img->line + applied_pos, postimage->line, postimage->nr);
+ img->line_nr - (applied_pos + preimage_limit));
+ COPY_ARRAY(img->line + applied_pos, postimage->line, postimage->line_nr);
if (!state->allow_overlap)
- for (i = 0; i < postimage->nr; i++)
+ for (i = 0; i < postimage->line_nr; i++)
img->line[applied_pos + i].flag |= LINE_PATCHED;
- img->nr = nr;
+ img->line_nr = nr;
}
/*
@@ -2911,11 +2874,9 @@ static int apply_one_fragment(struct apply_state *state,
int hunk_linenr = frag->linenr;
unsigned long leading, trailing;
int pos, applied_pos;
- struct image preimage;
- struct image postimage;
+ struct image preimage = IMAGE_INIT;
+ struct image postimage = IMAGE_INIT;
- memset(&preimage, 0, sizeof(preimage));
- memset(&postimage, 0, sizeof(postimage));
oldlines = xmalloc(size);
strbuf_init(&newlines, size);
@@ -2957,8 +2918,8 @@ static int apply_one_fragment(struct apply_state *state,
break;
*old++ = '\n';
strbuf_addch(&newlines, '\n');
- add_line_info(&preimage, "\n", 1, LINE_COMMON);
- add_line_info(&postimage, "\n", 1, LINE_COMMON);
+ image_add_line(&preimage, "\n", 1, LINE_COMMON);
+ image_add_line(&postimage, "\n", 1, LINE_COMMON);
is_blank_context = 1;
break;
case ' ':
@@ -2968,7 +2929,7 @@ static int apply_one_fragment(struct apply_state *state,
/* fallthrough */
case '-':
memcpy(old, patch + 1, plen);
- add_line_info(&preimage, old, plen,
+ image_add_line(&preimage, old, plen,
(first == ' ' ? LINE_COMMON : 0));
old += plen;
if (first == '-')
@@ -2988,7 +2949,7 @@ static int apply_one_fragment(struct apply_state *state,
else {
ws_fix_copy(&newlines, patch + 1, plen, ws_rule, &state->applied_after_fixing_ws);
}
- add_line_info(&postimage, newlines.buf + start, newlines.len - start,
+ image_add_line(&postimage, newlines.buf + start, newlines.len - start,
(first == '+' ? 0 : LINE_COMMON));
if (first == '+' &&
(ws_rule & WS_BLANK_AT_EOF) &&
@@ -3022,8 +2983,8 @@ static int apply_one_fragment(struct apply_state *state,
newlines.len > 0 && newlines.buf[newlines.len - 1] == '\n') {
old--;
strbuf_setlen(&newlines, newlines.len - 1);
- preimage.line_allocated[preimage.nr - 1].len--;
- postimage.line_allocated[postimage.nr - 1].len--;
+ preimage.line[preimage.line_nr - 1].len--;
+ postimage.line[postimage.line_nr - 1].len--;
}
leading = frag->leading;
@@ -3053,12 +3014,8 @@ static int apply_one_fragment(struct apply_state *state,
match_end = !state->unidiff_zero && !trailing;
pos = frag->newpos ? (frag->newpos - 1) : 0;
- preimage.buf = oldlines;
- preimage.len = old - oldlines;
- postimage.buf = newlines.buf;
- postimage.len = newlines.len;
- preimage.line = preimage.line_allocated;
- postimage.line = postimage.line_allocated;
+ strbuf_add(&preimage.buf, oldlines, old - oldlines);
+ strbuf_swap(&postimage.buf, &newlines);
for (;;) {
@@ -3082,28 +3039,28 @@ static int apply_one_fragment(struct apply_state *state,
* just reduce the larger context.
*/
if (leading >= trailing) {
- remove_first_line(&preimage);
- remove_first_line(&postimage);
+ image_remove_first_line(&preimage);
+ image_remove_first_line(&postimage);
pos--;
leading--;
}
if (trailing > leading) {
- remove_last_line(&preimage);
- remove_last_line(&postimage);
+ image_remove_last_line(&preimage);
+ image_remove_last_line(&postimage);
trailing--;
}
}
if (applied_pos >= 0) {
if (new_blank_lines_at_end &&
- preimage.nr + applied_pos >= img->nr &&
+ preimage.line_nr + applied_pos >= img->line_nr &&
(ws_rule & WS_BLANK_AT_EOF) &&
state->ws_error_action != nowarn_ws_error) {
record_ws_error(state, WS_BLANK_AT_EOF, "+", 1,
found_new_blank_lines_at_end);
if (state->ws_error_action == correct_ws_error) {
while (new_blank_lines_at_end--)
- remove_last_line(&postimage);
+ image_remove_last_line(&postimage);
}
/*
* We would want to prevent write_out_results()
@@ -3146,8 +3103,8 @@ static int apply_one_fragment(struct apply_state *state,
out:
free(oldlines);
strbuf_release(&newlines);
- free(preimage.line_allocated);
- free(postimage.line_allocated);
+ image_clear(&preimage);
+ image_clear(&postimage);
return (applied_pos < 0);
}
@@ -3177,18 +3134,16 @@ static int apply_binary_fragment(struct apply_state *state,
}
switch (fragment->binary_patch_method) {
case BINARY_DELTA_DEFLATED:
- dst = patch_delta(img->buf, img->len, fragment->patch,
+ dst = patch_delta(img->buf.buf, img->buf.len, fragment->patch,
fragment->size, &len);
if (!dst)
return -1;
- clear_image(img);
- img->buf = dst;
- img->len = len;
+ image_clear(img);
+ strbuf_attach(&img->buf, dst, len, len + 1);
return 0;
case BINARY_LITERAL_DEFLATED:
- clear_image(img);
- img->len = fragment->size;
- img->buf = xmemdupz(fragment->patch, img->len);
+ image_clear(img);
+ strbuf_add(&img->buf, fragment->patch, fragment->size);
return 0;
}
return -1;
@@ -3224,8 +3179,8 @@ static int apply_binary(struct apply_state *state,
* See if the old one matches what the patch
* applies to.
*/
- hash_object_file(the_hash_algo, img->buf, img->len, OBJ_BLOB,
- &oid);
+ hash_object_file(the_hash_algo, img->buf.buf, img->buf.len,
+ OBJ_BLOB, &oid);
if (strcmp(oid_to_hex(&oid), patch->old_oid_prefix))
return error(_("the patch applies to '%s' (%s), "
"which does not match the "
@@ -3234,14 +3189,14 @@ static int apply_binary(struct apply_state *state,
}
else {
/* Otherwise, the old one must be empty. */
- if (img->len)
+ if (img->buf.len)
return error(_("the patch applies to an empty "
"'%s' but it is not empty"), name);
}
get_oid_hex(patch->new_oid_prefix, &oid);
if (is_null_oid(&oid)) {
- clear_image(img);
+ image_clear(img);
return 0; /* deletion patch */
}
@@ -3257,9 +3212,8 @@ static int apply_binary(struct apply_state *state,
return error(_("the necessary postimage %s for "
"'%s' cannot be read"),
patch->new_oid_prefix, name);
- clear_image(img);
- img->buf = result;
- img->len = size;
+ image_clear(img);
+ strbuf_attach(&img->buf, result, size, size + 1);
} else {
/*
* We have verified buf matches the preimage;
@@ -3271,7 +3225,7 @@ static int apply_binary(struct apply_state *state,
name);
/* verify that the result matches */
- hash_object_file(the_hash_algo, img->buf, img->len, OBJ_BLOB,
+ hash_object_file(the_hash_algo, img->buf.buf, img->buf.len, OBJ_BLOB,
&oid);
if (strcmp(oid_to_hex(&oid), patch->new_oid_prefix))
return error(_("binary patch to '%s' creates incorrect result (expecting %s, got %s)"),
@@ -3533,7 +3487,7 @@ static int load_preimage(struct apply_state *state,
}
img = strbuf_detach(&buf, &len);
- prepare_image(image, img, len, !patch->is_binary);
+ image_prepare(image, img, len, !patch->is_binary);
return 0;
}
@@ -3541,14 +3495,14 @@ static int resolve_to(struct image *image, const struct object_id *result_id)
{
unsigned long size;
enum object_type type;
+ char *data;
- clear_image(image);
+ image_clear(image);
- image->buf = repo_read_object_file(the_repository, result_id, &type,
- &size);
- if (!image->buf || type != OBJ_BLOB)
+ data = repo_read_object_file(the_repository, result_id, &type, &size);
+ if (!data || type != OBJ_BLOB)
die("unable to read blob object %s", oid_to_hex(result_id));
- image->len = size;
+ strbuf_attach(&image->buf, data, size, size + 1);
return 0;
}
@@ -3561,6 +3515,7 @@ static int three_way_merge(struct apply_state *state,
const struct object_id *theirs)
{
mmfile_t base_file, our_file, their_file;
+ struct ll_merge_options merge_opts = LL_MERGE_OPTIONS_INIT;
mmbuffer_t result = { NULL };
enum ll_merge_result status;
@@ -3573,12 +3528,13 @@ static int three_way_merge(struct apply_state *state,
read_mmblob(&base_file, base);
read_mmblob(&our_file, ours);
read_mmblob(&their_file, theirs);
+ merge_opts.variant = state->merge_variant;
status = ll_merge(&result, path,
&base_file, "base",
&our_file, "ours",
&their_file, "theirs",
state->repo->index,
- NULL);
+ &merge_opts);
if (status == LL_MERGE_BINARY_CONFLICT)
warning("Cannot merge binary files: %s (%s vs. %s)",
path, "ours", "theirs");
@@ -3589,9 +3545,8 @@ static int three_way_merge(struct apply_state *state,
free(result.ptr);
return -1;
}
- clear_image(image);
- image->buf = result.ptr;
- image->len = result.size;
+ image_clear(image);
+ strbuf_attach(&image->buf, result.ptr, result.size, result.size);
return status;
}
@@ -3636,7 +3591,7 @@ static int load_current(struct apply_state *state,
else if (status)
return -1;
img = strbuf_detach(&buf, &len);
- prepare_image(image, img, len, !patch->is_binary);
+ image_prepare(image, img, len, !patch->is_binary);
return 0;
}
@@ -3651,7 +3606,7 @@ static int try_threeway(struct apply_state *state,
size_t len;
int status;
char *img;
- struct image tmp_image;
+ struct image tmp_image = IMAGE_INIT;
/* No point falling back to 3-way merge in these cases */
if (patch->is_delete ||
@@ -3671,15 +3626,15 @@ static int try_threeway(struct apply_state *state,
fprintf(stderr, _("Performing three-way merge...\n"));
img = strbuf_detach(&buf, &len);
- prepare_image(&tmp_image, img, len, 1);
+ image_prepare(&tmp_image, img, len, 1);
/* Apply the patch to get the post image */
if (apply_fragments(state, &tmp_image, patch) < 0) {
- clear_image(&tmp_image);
+ image_clear(&tmp_image);
return -1;
}
/* post_oid is theirs */
- write_object_file(tmp_image.buf, tmp_image.len, OBJ_BLOB, &post_oid);
- clear_image(&tmp_image);
+ write_object_file(tmp_image.buf.buf, tmp_image.buf.len, OBJ_BLOB, &post_oid);
+ image_clear(&tmp_image);
/* our_oid is ours */
if (patch->is_new) {
@@ -3691,8 +3646,8 @@ static int try_threeway(struct apply_state *state,
return error(_("cannot read the current contents of '%s'"),
patch->old_name);
}
- write_object_file(tmp_image.buf, tmp_image.len, OBJ_BLOB, &our_oid);
- clear_image(&tmp_image);
+ write_object_file(tmp_image.buf.buf, tmp_image.buf.len, OBJ_BLOB, &our_oid);
+ image_clear(&tmp_image);
/* in-core three-way merge between post and our using pre as base */
status = three_way_merge(state, image, patch->new_name,
@@ -3728,7 +3683,7 @@ static int try_threeway(struct apply_state *state,
static int apply_data(struct apply_state *state, struct patch *patch,
struct stat *st, const struct cache_entry *ce)
{
- struct image image;
+ struct image image = IMAGE_INIT;
if (load_preimage(state, &image, patch, st, ce) < 0)
return -1;
@@ -3740,14 +3695,13 @@ static int apply_data(struct apply_state *state, struct patch *patch,
/* Note: with --reject, apply_fragments() returns 0 */
if (patch->direct_to_threeway || apply_fragments(state, &image, patch) < 0) {
- clear_image(&image);
+ image_clear(&image);
return -1;
}
}
- patch->result = image.buf;
- patch->resultsize = image.len;
+ patch->result = strbuf_detach(&image.buf, &patch->resultsize);
add_to_fn_table(state, patch);
- free(image.line_allocated);
+ free(image.line);
if (0 < patch->is_delete && patch->resultsize)
return error(_("removal patch leaves file contents"));
@@ -4111,7 +4065,7 @@ static int read_apply_cache(struct apply_state *state)
{
if (state->index_file)
return read_index_from(state->repo->index, state->index_file,
- get_git_dir());
+ repo_get_git_dir(the_repository));
else
return repo_read_index(state->repo);
}
@@ -5151,6 +5105,15 @@ int apply_parse_options(int argc, const char **argv,
N_("also apply the patch (use with --stat/--summary/--check)")),
OPT_BOOL('3', "3way", &state->threeway,
N_( "attempt three-way merge, fall back on normal patch if that fails")),
+ OPT_SET_INT_F(0, "ours", &state->merge_variant,
+ N_("for conflicts, use our version"),
+ XDL_MERGE_FAVOR_OURS, PARSE_OPT_NONEG),
+ OPT_SET_INT_F(0, "theirs", &state->merge_variant,
+ N_("for conflicts, use their version"),
+ XDL_MERGE_FAVOR_THEIRS, PARSE_OPT_NONEG),
+ OPT_SET_INT_F(0, "union", &state->merge_variant,
+ N_("for conflicts, use a union version"),
+ XDL_MERGE_FAVOR_UNION, PARSE_OPT_NONEG),
OPT_FILENAME(0, "build-fake-ancestor", &state->fake_ancestor,
N_("build a temporary index based on embedded index information")),
/* Think twice before adding "--nul" synonym to this */
@@ -5190,5 +5153,10 @@ int apply_parse_options(int argc, const char **argv,
OPT_END()
};
- return parse_options(argc, argv, state->prefix, builtin_apply_options, apply_usage, 0);
+ argc = parse_options(argc, argv, state->prefix, builtin_apply_options, apply_usage, 0);
+
+ if (state->merge_variant && !state->threeway)
+ die(_("--ours, --theirs, and --union require --3way"));
+
+ return argc;
}
diff --git a/apply.h b/apply.h
index cd25d24cc4..90e887ec0e 100644
--- a/apply.h
+++ b/apply.h
@@ -59,6 +59,7 @@ struct apply_state {
struct repository *repo;
const char *index_file;
enum apply_verbosity apply_verbosity;
+ int merge_variant;
char *fake_ancestor;
const char *patch_input_file;
int line_termination;
diff --git a/archive.c b/archive.c
index 9ba96aae4f..58f86bf75c 100644
--- a/archive.c
+++ b/archive.c
@@ -304,8 +304,6 @@ int write_archive_entries(struct archiver_args *args,
write_archive_entry_fn_t write_entry)
{
struct archiver_context context;
- struct unpack_trees_options opts;
- struct tree_desc t;
int err;
struct strbuf path_in_archive = STRBUF_INIT;
struct strbuf content = STRBUF_INIT;
@@ -331,23 +329,6 @@ int write_archive_entries(struct archiver_args *args,
context.args = args;
context.write_entry = write_entry;
- /*
- * Setup index and instruct attr to read index only
- */
- if (!args->worktree_attributes) {
- memset(&opts, 0, sizeof(opts));
- opts.index_only = 1;
- opts.head_idx = -1;
- opts.src_index = args->repo->index;
- opts.dst_index = args->repo->index;
- opts.fn = oneway_merge;
- init_tree_desc(&t, &args->tree->object.oid,
- args->tree->buffer, args->tree->size);
- if (unpack_trees(1, &t, &opts))
- return -1;
- git_attr_set_direction(GIT_ATTR_INDEX);
- }
-
err = read_tree(args->repo, args->tree,
&args->pathspec,
queue_or_write_archive_entry,
@@ -540,6 +521,26 @@ static void parse_treeish_arg(const char **argv,
if (!tree)
die(_("not a tree object: %s"), oid_to_hex(&oid));
+ /*
+ * Setup index and instruct attr to read index only
+ */
+ if (!ar_args->worktree_attributes) {
+ struct unpack_trees_options opts;
+ struct tree_desc t;
+
+ memset(&opts, 0, sizeof(opts));
+ opts.index_only = 1;
+ opts.head_idx = -1;
+ opts.src_index = ar_args->repo->index;
+ opts.dst_index = ar_args->repo->index;
+ opts.fn = oneway_merge;
+ init_tree_desc(&t, &tree->object.oid, tree->buffer, tree->size);
+ if (unpack_trees(1, &t, &opts))
+ die(_("unable to checkout working tree"));
+
+ git_attr_set_direction(GIT_ATTR_INDEX);
+ }
+
ar_args->refname = ref;
ar_args->tree = tree;
ar_args->commit_oid = commit_oid;
diff --git a/attr.c b/attr.c
index 06b5b5e55e..c605d2c170 100644
--- a/attr.c
+++ b/attr.c
@@ -187,7 +187,7 @@ static void all_attrs_init(struct attr_hashmap *map, struct attr_check *check)
}
/*
- * Atribute name cannot begin with "builtin_" which
+ * Attribute name cannot begin with "builtin_" which
* is a reserved namespace for built in attributes values.
*/
static int attr_name_reserved(const char *name)
diff --git a/bloom.h b/bloom.h
index d20e64bfbb..6e46489a20 100644
--- a/bloom.h
+++ b/bloom.h
@@ -18,7 +18,7 @@ struct bloom_filter_settings {
/*
* The number of times a path is hashed, i.e. the
- * number of bit positions tht cumulatively
+ * number of bit positions that cumulatively
* determine whether a path is present in the
* Bloom filter.
*/
diff --git a/branch.c b/branch.c
index c887ea2151..08fa4094d2 100644
--- a/branch.c
+++ b/branch.c
@@ -601,6 +601,7 @@ void create_branch(struct repository *r,
int forcing = 0;
struct ref_transaction *transaction;
struct strbuf err = STRBUF_INIT;
+ int flags = 0;
char *msg;
if (track == BRANCH_TRACK_OVERRIDE)
@@ -619,7 +620,7 @@ void create_branch(struct repository *r,
goto cleanup;
if (reflog)
- log_all_ref_updates = LOG_REFS_NORMAL;
+ flags |= REF_FORCE_CREATE_REFLOG;
if (forcing)
msg = xstrfmt("branch: Reset to %s", start_name);
@@ -630,7 +631,7 @@ void create_branch(struct repository *r,
if (!transaction ||
ref_transaction_update(transaction, ref.buf,
&oid, forcing ? NULL : null_oid(),
- NULL, NULL, 0, msg, &err) ||
+ NULL, NULL, flags, msg, &err) ||
ref_transaction_commit(transaction, &err))
die("%s", err.buf);
ref_transaction_free(transaction);
diff --git a/builtin.h b/builtin.h
index 14fa017160..f7b166b334 100644
--- a/builtin.h
+++ b/builtin.h
@@ -1,15 +1,8 @@
#ifndef BUILTIN_H
#define BUILTIN_H
-/*
- * TODO: Almost all of our builtins access `the_repository` by necessity
- * because they do not get passed a pointer to it. We should adapt the function
- * signature of those main functions to accept a `struct repository *` and then
- * remove the macro here.
- */
-#define USE_THE_REPOSITORY_VARIABLE
-
#include "git-compat-util.h"
+#include "repository.h"
/*
* builtin API
@@ -122,143 +115,143 @@ int is_builtin(const char *s);
BUG("unexpected prefix in builtin: %s", (prefix)); \
} while (0)
-int cmd_add(int argc, const char **argv, const char *prefix);
-int cmd_am(int argc, const char **argv, const char *prefix);
-int cmd_annotate(int argc, const char **argv, const char *prefix);
-int cmd_apply(int argc, const char **argv, const char *prefix);
-int cmd_archive(int argc, const char **argv, const char *prefix);
-int cmd_bisect(int argc, const char **argv, const char *prefix);
-int cmd_blame(int argc, const char **argv, const char *prefix);
-int cmd_branch(int argc, const char **argv, const char *prefix);
-int cmd_bugreport(int argc, const char **argv, const char *prefix);
-int cmd_bundle(int argc, const char **argv, const char *prefix);
-int cmd_cat_file(int argc, const char **argv, const char *prefix);
-int cmd_checkout(int argc, const char **argv, const char *prefix);
-int cmd_checkout__worker(int argc, const char **argv, const char *prefix);
-int cmd_checkout_index(int argc, const char **argv, const char *prefix);
-int cmd_check_attr(int argc, const char **argv, const char *prefix);
-int cmd_check_ignore(int argc, const char **argv, const char *prefix);
-int cmd_check_mailmap(int argc, const char **argv, const char *prefix);
-int cmd_check_ref_format(int argc, const char **argv, const char *prefix);
-int cmd_cherry(int argc, const char **argv, const char *prefix);
-int cmd_cherry_pick(int argc, const char **argv, const char *prefix);
-int cmd_clone(int argc, const char **argv, const char *prefix);
-int cmd_clean(int argc, const char **argv, const char *prefix);
-int cmd_column(int argc, const char **argv, const char *prefix);
-int cmd_commit(int argc, const char **argv, const char *prefix);
-int cmd_commit_graph(int argc, const char **argv, const char *prefix);
-int cmd_commit_tree(int argc, const char **argv, const char *prefix);
-int cmd_config(int argc, const char **argv, const char *prefix);
-int cmd_count_objects(int argc, const char **argv, const char *prefix);
-int cmd_credential(int argc, const char **argv, const char *prefix);
-int cmd_credential_cache(int argc, const char **argv, const char *prefix);
-int cmd_credential_cache_daemon(int argc, const char **argv, const char *prefix);
-int cmd_credential_store(int argc, const char **argv, const char *prefix);
-int cmd_describe(int argc, const char **argv, const char *prefix);
-int cmd_diagnose(int argc, const char **argv, const char *prefix);
-int cmd_diff_files(int argc, const char **argv, const char *prefix);
-int cmd_diff_index(int argc, const char **argv, const char *prefix);
-int cmd_diff(int argc, const char **argv, const char *prefix);
-int cmd_diff_tree(int argc, const char **argv, const char *prefix);
-int cmd_difftool(int argc, const char **argv, const char *prefix);
-int cmd_env__helper(int argc, const char **argv, const char *prefix);
-int cmd_fast_export(int argc, const char **argv, const char *prefix);
-int cmd_fast_import(int argc, const char **argv, const char *prefix);
-int cmd_fetch(int argc, const char **argv, const char *prefix);
-int cmd_fetch_pack(int argc, const char **argv, const char *prefix);
-int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix);
-int cmd_for_each_ref(int argc, const char **argv, const char *prefix);
-int cmd_for_each_repo(int argc, const char **argv, const char *prefix);
-int cmd_format_patch(int argc, const char **argv, const char *prefix);
-int cmd_fsck(int argc, const char **argv, const char *prefix);
-int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix);
-int cmd_gc(int argc, const char **argv, const char *prefix);
-int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix);
-int cmd_grep(int argc, const char **argv, const char *prefix);
-int cmd_hash_object(int argc, const char **argv, const char *prefix);
-int cmd_help(int argc, const char **argv, const char *prefix);
-int cmd_hook(int argc, const char **argv, const char *prefix);
-int cmd_index_pack(int argc, const char **argv, const char *prefix);
-int cmd_init_db(int argc, const char **argv, const char *prefix);
-int cmd_interpret_trailers(int argc, const char **argv, const char *prefix);
-int cmd_log(int argc, const char **argv, const char *prefix);
-int cmd_log_reflog(int argc, const char **argv, const char *prefix);
-int cmd_ls_files(int argc, const char **argv, const char *prefix);
-int cmd_ls_tree(int argc, const char **argv, const char *prefix);
-int cmd_ls_remote(int argc, const char **argv, const char *prefix);
-int cmd_mailinfo(int argc, const char **argv, const char *prefix);
-int cmd_mailsplit(int argc, const char **argv, const char *prefix);
-int cmd_maintenance(int argc, const char **argv, const char *prefix);
-int cmd_merge(int argc, const char **argv, const char *prefix);
-int cmd_merge_base(int argc, const char **argv, const char *prefix);
-int cmd_merge_index(int argc, const char **argv, const char *prefix);
-int cmd_merge_ours(int argc, const char **argv, const char *prefix);
-int cmd_merge_file(int argc, const char **argv, const char *prefix);
-int cmd_merge_recursive(int argc, const char **argv, const char *prefix);
-int cmd_merge_tree(int argc, const char **argv, const char *prefix);
-int cmd_mktag(int argc, const char **argv, const char *prefix);
-int cmd_mktree(int argc, const char **argv, const char *prefix);
-int cmd_multi_pack_index(int argc, const char **argv, const char *prefix);
-int cmd_mv(int argc, const char **argv, const char *prefix);
-int cmd_name_rev(int argc, const char **argv, const char *prefix);
-int cmd_notes(int argc, const char **argv, const char *prefix);
-int cmd_pack_objects(int argc, const char **argv, const char *prefix);
-int cmd_pack_redundant(int argc, const char **argv, const char *prefix);
-int cmd_patch_id(int argc, const char **argv, const char *prefix);
-int cmd_prune(int argc, const char **argv, const char *prefix);
-int cmd_prune_packed(int argc, const char **argv, const char *prefix);
-int cmd_pull(int argc, const char **argv, const char *prefix);
-int cmd_push(int argc, const char **argv, const char *prefix);
-int cmd_range_diff(int argc, const char **argv, const char *prefix);
-int cmd_read_tree(int argc, const char **argv, const char *prefix);
-int cmd_rebase(int argc, const char **argv, const char *prefix);
-int cmd_rebase__interactive(int argc, const char **argv, const char *prefix);
-int cmd_receive_pack(int argc, const char **argv, const char *prefix);
-int cmd_reflog(int argc, const char **argv, const char *prefix);
-int cmd_refs(int argc, const char **argv, const char *prefix);
-int cmd_remote(int argc, const char **argv, const char *prefix);
-int cmd_remote_ext(int argc, const char **argv, const char *prefix);
-int cmd_remote_fd(int argc, const char **argv, const char *prefix);
-int cmd_repack(int argc, const char **argv, const char *prefix);
-int cmd_replay(int argc, const char **argv, const char *prefix);
-int cmd_rerere(int argc, const char **argv, const char *prefix);
-int cmd_reset(int argc, const char **argv, const char *prefix);
-int cmd_restore(int argc, const char **argv, const char *prefix);
-int cmd_rev_list(int argc, const char **argv, const char *prefix);
-int cmd_rev_parse(int argc, const char **argv, const char *prefix);
-int cmd_revert(int argc, const char **argv, const char *prefix);
-int cmd_rm(int argc, const char **argv, const char *prefix);
-int cmd_send_pack(int argc, const char **argv, const char *prefix);
-int cmd_shortlog(int argc, const char **argv, const char *prefix);
-int cmd_show(int argc, const char **argv, const char *prefix);
-int cmd_show_branch(int argc, const char **argv, const char *prefix);
-int cmd_show_index(int argc, const char **argv, const char *prefix);
-int cmd_sparse_checkout(int argc, const char **argv, const char *prefix);
-int cmd_status(int argc, const char **argv, const char *prefix);
-int cmd_stash(int argc, const char **argv, const char *prefix);
-int cmd_stripspace(int argc, const char **argv, const char *prefix);
-int cmd_submodule__helper(int argc, const char **argv, const char *prefix);
-int cmd_switch(int argc, const char **argv, const char *prefix);
-int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
-int cmd_tag(int argc, const char **argv, const char *prefix);
-int cmd_unpack_file(int argc, const char **argv, const char *prefix);
-int cmd_unpack_objects(int argc, const char **argv, const char *prefix);
-int cmd_update_index(int argc, const char **argv, const char *prefix);
-int cmd_update_ref(int argc, const char **argv, const char *prefix);
-int cmd_update_server_info(int argc, const char **argv, const char *prefix);
-int cmd_upload_archive(int argc, const char **argv, const char *prefix);
-int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix);
-int cmd_upload_pack(int argc, const char **argv, const char *prefix);
-int cmd_var(int argc, const char **argv, const char *prefix);
-int cmd_verify_commit(int argc, const char **argv, const char *prefix);
-int cmd_verify_tag(int argc, const char **argv, const char *prefix);
-int cmd_version(int argc, const char **argv, const char *prefix);
-int cmd_whatchanged(int argc, const char **argv, const char *prefix);
-int cmd_worktree(int argc, const char **argv, const char *prefix);
-int cmd_write_tree(int argc, const char **argv, const char *prefix);
-int cmd_verify_pack(int argc, const char **argv, const char *prefix);
-int cmd_show_ref(int argc, const char **argv, const char *prefix);
-int cmd_pack_refs(int argc, const char **argv, const char *prefix);
-int cmd_replace(int argc, const char **argv, const char *prefix);
+int cmd_add(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_am(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_annotate(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_apply(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_archive(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_bisect(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_blame(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_branch(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_bugreport(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_bundle(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_cat_file(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_checkout(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_checkout__worker(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_checkout_index(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_check_attr(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_check_ignore(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_check_mailmap(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_check_ref_format(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_cherry(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_cherry_pick(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_clone(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_clean(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_column(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_commit(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_commit_graph(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_commit_tree(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_config(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_count_objects(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_credential(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_credential_cache(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_credential_cache_daemon(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_credential_store(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_describe(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_diagnose(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_diff_files(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_diff_index(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_diff(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_diff_tree(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_difftool(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_env__helper(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_fast_export(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_fast_import(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_fetch(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_fetch_pack(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_for_each_ref(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_for_each_repo(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_format_patch(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_fsck(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_gc(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_grep(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_hash_object(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_help(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_hook(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_index_pack(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_init_db(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_interpret_trailers(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_log_reflog(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_log(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_ls_files(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_ls_tree(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_ls_remote(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_mailinfo(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_mailsplit(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_maintenance(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_merge(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_merge_base(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_merge_index(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_merge_ours(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_merge_file(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_merge_recursive(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_merge_tree(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_mktag(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_mktree(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_multi_pack_index(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_mv(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_name_rev(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_notes(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_pack_objects(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_pack_redundant(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_patch_id(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_prune(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_prune_packed(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_pull(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_push(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_range_diff(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_read_tree(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_rebase(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_rebase__interactive(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_receive_pack(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_reflog(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_refs(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_remote(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_remote_ext(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_remote_fd(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_repack(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_replay(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_rerere(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_reset(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_restore(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_rev_list(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_rev_parse(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_revert(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_rm(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_send_pack(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_shortlog(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_show(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_show_branch(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_show_index(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_sparse_checkout(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_status(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_stash(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_stripspace(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_submodule__helper(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_switch(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_symbolic_ref(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_tag(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_unpack_file(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_unpack_objects(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_update_index(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_update_ref(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_update_server_info(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_upload_archive(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_upload_pack(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_var(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_verify_commit(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_verify_tag(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_version(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_whatchanged(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_worktree(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_write_tree(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_verify_pack(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_show_ref(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_pack_refs(int argc, const char **argv, const char *prefix, struct repository *repo);
+int cmd_replace(int argc, const char **argv, const char *prefix, struct repository *repo);
#endif
diff --git a/builtin/add.c b/builtin/add.c
index 40b61ef90d..773b7224a4 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -3,7 +3,6 @@
*
* Copyright (C) 2006 Linus Torvalds
*/
-
#include "builtin.h"
#include "advice.h"
#include "config.h"
@@ -18,7 +17,6 @@
#include "preload-index.h"
#include "diff.h"
#include "read-cache.h"
-#include "repository.h"
#include "revision.h"
#include "bulk-checkin.h"
#include "strvec.h"
@@ -36,24 +34,27 @@ static int pathspec_file_nul;
static int include_sparse;
static const char *pathspec_from_file;
-static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only)
+static int chmod_pathspec(struct repository *repo,
+ struct pathspec *pathspec,
+ char flip,
+ int show_only)
{
int i, ret = 0;
- for (i = 0; i < the_repository->index->cache_nr; i++) {
- struct cache_entry *ce = the_repository->index->cache[i];
+ for (i = 0; i < repo->index->cache_nr; i++) {
+ struct cache_entry *ce = repo->index->cache[i];
int err;
if (!include_sparse &&
(ce_skip_worktree(ce) ||
- !path_in_sparse_checkout(ce->name, the_repository->index)))
+ !path_in_sparse_checkout(ce->name, repo->index)))
continue;
- if (pathspec && !ce_path_match(the_repository->index, ce, pathspec, NULL))
+ if (pathspec && !ce_path_match(repo->index, ce, pathspec, NULL))
continue;
if (!show_only)
- err = chmod_index_entry(the_repository->index, ce, flip);
+ err = chmod_index_entry(repo->index, ce, flip);
else
err = S_ISREG(ce->ce_mode) ? 0 : -1;
@@ -64,31 +65,36 @@ static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only)
return ret;
}
-static int renormalize_tracked_files(const struct pathspec *pathspec, int flags)
+static int renormalize_tracked_files(struct repository *repo,
+ const struct pathspec *pathspec,
+ int flags)
{
int i, retval = 0;
- for (i = 0; i < the_repository->index->cache_nr; i++) {
- struct cache_entry *ce = the_repository->index->cache[i];
+ for (i = 0; i < repo->index->cache_nr; i++) {
+ struct cache_entry *ce = repo->index->cache[i];
if (!include_sparse &&
(ce_skip_worktree(ce) ||
- !path_in_sparse_checkout(ce->name, the_repository->index)))
+ !path_in_sparse_checkout(ce->name, repo->index)))
continue;
if (ce_stage(ce))
continue; /* do not touch unmerged paths */
if (!S_ISREG(ce->ce_mode) && !S_ISLNK(ce->ce_mode))
continue; /* do not touch non blobs */
- if (pathspec && !ce_path_match(the_repository->index, ce, pathspec, NULL))
+ if (pathspec && !ce_path_match(repo->index, ce, pathspec, NULL))
continue;
- retval |= add_file_to_index(the_repository->index, ce->name,
+ retval |= add_file_to_index(repo->index, ce->name,
flags | ADD_CACHE_RENORMALIZE);
}
return retval;
}
-static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec, int prefix)
+static char *prune_directory(struct repository *repo,
+ struct dir_struct *dir,
+ struct pathspec *pathspec,
+ int prefix)
{
char *seen;
int i;
@@ -100,16 +106,16 @@ static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec,
i = dir->nr;
while (--i >= 0) {
struct dir_entry *entry = *src++;
- if (dir_path_match(the_repository->index, entry, pathspec, prefix, seen))
+ if (dir_path_match(repo->index, entry, pathspec, prefix, seen))
*dst++ = entry;
}
dir->nr = dst - dir->entries;
- add_pathspec_matches_against_index(pathspec, the_repository->index, seen,
+ add_pathspec_matches_against_index(pathspec, repo->index, seen,
PS_IGNORE_SKIP_WORKTREE);
return seen;
}
-static int refresh(int verbose, const struct pathspec *pathspec)
+static int refresh(struct repository *repo, int verbose, const struct pathspec *pathspec)
{
char *seen;
int i, ret = 0;
@@ -119,14 +125,14 @@ static int refresh(int verbose, const struct pathspec *pathspec)
(verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET);
seen = xcalloc(pathspec->nr, 1);
- refresh_index(the_repository->index, flags, pathspec, seen,
+ refresh_index(repo->index, flags, pathspec, seen,
_("Unstaged changes after refreshing the index:"));
for (i = 0; i < pathspec->nr; i++) {
if (!seen[i]) {
const char *path = pathspec->items[i].original;
if (matches_skip_worktree(pathspec, i, &skip_worktree_seen) ||
- !path_in_sparse_checkout(path, the_repository->index)) {
+ !path_in_sparse_checkout(path, repo->index)) {
string_list_append(&only_match_skip_worktree,
pathspec->items[i].original);
} else {
@@ -147,7 +153,10 @@ static int refresh(int verbose, const struct pathspec *pathspec)
return ret;
}
-int interactive_add(const char **argv, const char *prefix, int patch)
+int interactive_add(struct repository *repo,
+ const char **argv,
+ const char *prefix,
+ int patch)
{
struct pathspec pathspec;
int ret;
@@ -159,28 +168,31 @@ int interactive_add(const char **argv, const char *prefix, int patch)
prefix, argv);
if (patch)
- ret = !!run_add_p(the_repository, ADD_P_ADD, NULL, &pathspec);
+ ret = !!run_add_p(repo, ADD_P_ADD, NULL, &pathspec);
else
- ret = !!run_add_i(the_repository, &pathspec);
+ ret = !!run_add_i(repo, &pathspec);
clear_pathspec(&pathspec);
return ret;
}
-static int edit_patch(int argc, const char **argv, const char *prefix)
+static int edit_patch(struct repository *repo,
+ int argc,
+ const char **argv,
+ const char *prefix)
{
- char *file = git_pathdup("ADD_EDIT.patch");
+ char *file = repo_git_path(repo, "ADD_EDIT.patch");
struct child_process child = CHILD_PROCESS_INIT;
struct rev_info rev;
int out;
struct stat st;
- git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
+ repo_config(repo, git_diff_basic_config, NULL);
- if (repo_read_index(the_repository) < 0)
+ if (repo_read_index(repo) < 0)
die(_("could not read the index"));
- repo_init_revisions(the_repository, &rev, prefix);
+ repo_init_revisions(repo, &rev, prefix);
rev.diffopt.context = 7;
argc = setup_revisions(argc, argv, &rev, NULL);
@@ -318,7 +330,7 @@ static void check_embedded_repo(const char *path)
strbuf_release(&name);
}
-static int add_files(struct dir_struct *dir, int flags)
+static int add_files(struct repository *repo, struct dir_struct *dir, int flags)
{
int i, exit_status = 0;
struct string_list matched_sparse_paths = STRING_LIST_INIT_NODUP;
@@ -334,12 +346,12 @@ static int add_files(struct dir_struct *dir, int flags)
for (i = 0; i < dir->nr; i++) {
if (!include_sparse &&
- !path_in_sparse_checkout(dir->entries[i]->name, the_repository->index)) {
+ !path_in_sparse_checkout(dir->entries[i]->name, repo->index)) {
string_list_append(&matched_sparse_paths,
dir->entries[i]->name);
continue;
}
- if (add_file_to_index(the_repository->index, dir->entries[i]->name, flags)) {
+ if (add_file_to_index(repo->index, dir->entries[i]->name, flags)) {
if (!ignore_add_errors)
die(_("adding files failed"));
exit_status = 1;
@@ -358,7 +370,10 @@ static int add_files(struct dir_struct *dir, int flags)
return exit_status;
}
-int cmd_add(int argc, const char **argv, const char *prefix)
+int cmd_add(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo)
{
int exit_status = 0;
struct pathspec pathspec;
@@ -370,7 +385,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
char *ps_matched = NULL;
struct lock_file lock_file = LOCK_INIT;
- git_config(add_config, NULL);
+ repo_config(repo, add_config, NULL);
argc = parse_options(argc, argv, prefix, builtin_add_options,
builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
@@ -381,13 +396,13 @@ int cmd_add(int argc, const char **argv, const char *prefix)
die(_("options '%s' and '%s' cannot be used together"), "--dry-run", "--interactive/--patch");
if (pathspec_from_file)
die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--interactive/--patch");
- exit(interactive_add(argv + 1, prefix, patch_interactive));
+ exit(interactive_add(repo, argv + 1, prefix, patch_interactive));
}
if (edit_interactive) {
if (pathspec_from_file)
die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--edit");
- return(edit_patch(argc, argv, prefix));
+ return(edit_patch(repo, argc, argv, prefix));
}
argc--;
argv++;
@@ -410,10 +425,10 @@ int cmd_add(int argc, const char **argv, const char *prefix)
add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize;
require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
- prepare_repo_settings(the_repository);
- the_repository->settings.command_requires_full_index = 0;
+ prepare_repo_settings(repo);
+ repo->settings.command_requires_full_index = 0;
- repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
+ repo_hold_locked_index(repo, &lock_file, LOCK_DIE_ON_ERROR);
/*
* Check the "pathspec '%s' did not match any files" block
@@ -454,11 +469,11 @@ int cmd_add(int argc, const char **argv, const char *prefix)
(!(addremove || take_worktree_changes)
? ADD_CACHE_IGNORE_REMOVAL : 0));
- if (repo_read_index_preload(the_repository, &pathspec, 0) < 0)
+ if (repo_read_index_preload(repo, &pathspec, 0) < 0)
die(_("index file corrupt"));
- die_in_unpopulated_submodule(the_repository->index, prefix);
- die_path_inside_submodule(the_repository->index, &pathspec);
+ die_in_unpopulated_submodule(repo->index, prefix);
+ die_path_inside_submodule(repo->index, &pathspec);
if (add_new_files) {
int baselen;
@@ -470,13 +485,13 @@ int cmd_add(int argc, const char **argv, const char *prefix)
}
/* This picks up the paths that are not tracked */
- baselen = fill_directory(&dir, the_repository->index, &pathspec);
+ baselen = fill_directory(&dir, repo->index, &pathspec);
if (pathspec.nr)
- seen = prune_directory(&dir, &pathspec, baselen);
+ seen = prune_directory(repo, &dir, &pathspec, baselen);
}
if (refresh_only) {
- exit_status |= refresh(verbose, &pathspec);
+ exit_status |= refresh(repo, verbose, &pathspec);
goto finish;
}
@@ -487,7 +502,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
if (!seen)
seen = find_pathspecs_matching_against_index(&pathspec,
- the_repository->index, PS_IGNORE_SKIP_WORKTREE);
+ repo->index, PS_IGNORE_SKIP_WORKTREE);
/*
* file_exists() assumes exact match
@@ -523,8 +538,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)
!file_exists(path)) {
if (ignore_missing) {
int dtype = DT_UNKNOWN;
- if (is_excluded(&dir, the_repository->index, path, &dtype))
- dir_add_ignored(&dir, the_repository->index,
+ if (is_excluded(&dir, repo->index, path, &dtype))
+ dir_add_ignored(&dir, repo->index,
path, pathspec.items[i].len);
} else
die(_("pathspec '%s' did not match any files"),
@@ -547,9 +562,9 @@ int cmd_add(int argc, const char **argv, const char *prefix)
ps_matched = xcalloc(pathspec.nr, 1);
if (add_renormalize)
- exit_status |= renormalize_tracked_files(&pathspec, flags);
+ exit_status |= renormalize_tracked_files(repo, &pathspec, flags);
else
- exit_status |= add_files_to_cache(the_repository, prefix,
+ exit_status |= add_files_to_cache(repo, prefix,
&pathspec, ps_matched,
include_sparse, flags);
@@ -558,14 +573,14 @@ int cmd_add(int argc, const char **argv, const char *prefix)
exit(128);
if (add_new_files)
- exit_status |= add_files(&dir, flags);
+ exit_status |= add_files(repo, &dir, flags);
if (chmod_arg && pathspec.nr)
- exit_status |= chmod_pathspec(&pathspec, chmod_arg[0], show_only);
+ exit_status |= chmod_pathspec(repo, &pathspec, chmod_arg[0], show_only);
end_odb_transaction();
finish:
- if (write_locked_index(the_repository->index, &lock_file,
+ if (write_locked_index(repo->index, &lock_file,
COMMIT_LOCK | SKIP_IF_UNCHANGED))
die(_("unable to write new index file"));
diff --git a/builtin/am.c b/builtin/am.c
index d8875ad402..bfa95147cf 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -4,6 +4,7 @@
* Based on git-am.sh by Junio C Hamano.
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "advice.h"
@@ -38,7 +39,6 @@
#include "string-list.h"
#include "pager.h"
#include "path.h"
-#include "repository.h"
#include "pretty.h"
/**
@@ -1544,7 +1544,8 @@ static int run_apply(const struct am_state *state, const char *index_file)
if (index_file) {
/* Reload index as apply_all_patches() will have modified it. */
discard_index(the_repository->index);
- read_index_from(the_repository->index, index_file, get_git_dir());
+ read_index_from(the_repository->index, index_file,
+ repo_get_git_dir(the_repository));
}
return 0;
@@ -1587,7 +1588,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
return error("could not build fake ancestor");
discard_index(the_repository->index);
- read_index_from(the_repository->index, index_path, get_git_dir());
+ read_index_from(the_repository->index, index_path, repo_get_git_dir(the_repository));
if (write_index_as_tree(&bases[0], the_repository->index, index_path, 0, NULL))
return error(_("Repository lacks necessary blobs to fall back on 3-way merge."));
@@ -1667,7 +1668,9 @@ static void do_commit(const struct am_state *state)
if (!state->no_verify && run_hooks(the_repository, "pre-applypatch"))
exit(1);
- if (write_index_as_tree(&tree, the_repository->index, get_index_file(), 0, NULL))
+ if (write_index_as_tree(&tree, the_repository->index,
+ repo_get_index_file(the_repository),
+ 0, NULL))
die(_("git write-tree failed to write a tree"));
if (!repo_get_oid_commit(the_repository, "HEAD", &parent)) {
@@ -2077,7 +2080,9 @@ static int clean_index(const struct object_id *head, const struct object_id *rem
if (fast_forward_to(head_tree, head_tree, 1))
return -1;
- if (write_index_as_tree(&index, the_repository->index, get_index_file(), 0, NULL))
+ if (write_index_as_tree(&index, the_repository->index,
+ repo_get_index_file(the_repository),
+ 0, NULL))
return -1;
index_tree = parse_tree_indirect(&index);
@@ -2298,7 +2303,10 @@ static int parse_opt_show_current_patch(const struct option *opt, const char *ar
return 0;
}
-int cmd_am(int argc, const char **argv, const char *prefix)
+int cmd_am(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct am_state state;
int binary = -1;
diff --git a/builtin/annotate.c b/builtin/annotate.c
index 58ff977a23..a99179fe4d 100644
--- a/builtin/annotate.c
+++ b/builtin/annotate.c
@@ -3,11 +3,16 @@
*
* Copyright (C) 2006 Ryan Anderson
*/
+
+#define USE_THE_REPOSITORY_VARIABLE
#include "git-compat-util.h"
#include "builtin.h"
#include "strvec.h"
-int cmd_annotate(int argc, const char **argv, const char *prefix)
+int cmd_annotate(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct strvec args = STRVEC_INIT;
int i;
@@ -18,5 +23,5 @@ int cmd_annotate(int argc, const char **argv, const char *prefix)
strvec_push(&args, argv[i]);
}
- return cmd_blame(args.nr, args.v, prefix);
+ return cmd_blame(args.nr, args.v, prefix, the_repository);
}
diff --git a/builtin/apply.c b/builtin/apply.c
index d623c52f78..84f1863d3a 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -1,6 +1,6 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "gettext.h"
-#include "repository.h"
#include "hash.h"
#include "apply.h"
@@ -9,7 +9,10 @@ static const char * const apply_usage[] = {
NULL
};
-int cmd_apply(int argc, const char **argv, const char *prefix)
+int cmd_apply(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int force_apply = 0;
int options = 0;
diff --git a/builtin/archive.c b/builtin/archive.c
index 63f02990d1..dc926d1a3d 100644
--- a/builtin/archive.c
+++ b/builtin/archive.c
@@ -2,13 +2,13 @@
* Copyright (c) 2006 Franck Bui-Huu
* Copyright (c) 2006 Rene Scharfe
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "archive.h"
#include "gettext.h"
#include "transport.h"
#include "parse-options.h"
#include "pkt-line.h"
-#include "repository.h"
static void create_output_file(const char *output_file)
{
@@ -76,7 +76,10 @@ static int run_remote_archiver(int argc, const char **argv,
PARSE_OPT_KEEP_UNKNOWN_OPT | \
PARSE_OPT_NO_INTERNAL_HELP )
-int cmd_archive(int argc, const char **argv, const char *prefix)
+int cmd_archive(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
const char *exec = "git-upload-archive";
char *output = NULL;
diff --git a/builtin/bisect.c b/builtin/bisect.c
index c8aa92b19d..21d17a6c1a 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "copy.h"
#include "environment.h"
@@ -1411,7 +1412,10 @@ static int cmd_bisect__run(int argc, const char **argv, const char *prefix UNUSE
return res;
}
-int cmd_bisect(int argc, const char **argv, const char *prefix)
+int cmd_bisect(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int res = 0;
parse_opt_subcommand_fn *fn = NULL;
diff --git a/builtin/blame.c b/builtin/blame.c
index 35e975fb13..e407a22da3 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -4,7 +4,7 @@
* Copyright (c) 2006, 2014 by its authors
* See COPYING for licensing conditions
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "color.h"
@@ -12,7 +12,6 @@
#include "environment.h"
#include "gettext.h"
#include "hex.h"
-#include "repository.h"
#include "commit.h"
#include "diff.h"
#include "revision.h"
@@ -864,7 +863,10 @@ static void build_ignorelist(struct blame_scoreboard *sb,
}
}
-int cmd_blame(int argc, const char **argv, const char *prefix)
+int cmd_blame(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct rev_info revs;
char *path = NULL;
@@ -1081,7 +1083,7 @@ parse_done:
path = add_prefix(prefix, argv[1]);
argv[1] = argv[2];
} else { /* (2a) */
- if (argc == 2 && is_a_rev(argv[1]) && !get_git_work_tree())
+ if (argc == 2 && is_a_rev(argv[1]) && !repo_get_work_tree(the_repository))
die("missing <path> to blame");
path = add_prefix(prefix, argv[argc - 1]);
}
diff --git a/builtin/branch.c b/builtin/branch.c
index 3f870741bf..fd1611ebf5 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -4,7 +4,7 @@
* Copyright (c) 2006 Kristian Høgsberg <krh@redhat.com>
* Based on git-branch.sh by Junio C Hamano.
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "color.h"
@@ -704,7 +704,10 @@ static int edit_branch_description(const char *branch_name)
return 0;
}
-int cmd_branch(int argc, const char **argv, const char *prefix)
+int cmd_branch(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
/* possible actions */
int delete = 0, rename = 0, copy = 0, list = 0,
@@ -878,6 +881,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
string_list_clear(&output, 0);
ref_sorting_release(sorting);
ref_filter_clear(&filter);
+ ref_format_clear(&format);
return 0;
} else if (edit_description) {
const char *branch_name;
diff --git a/builtin/bugreport.c b/builtin/bugreport.c
index bdfed3d8f1..7c2df035c9 100644
--- a/builtin/bugreport.c
+++ b/builtin/bugreport.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "editor.h"
@@ -98,7 +99,10 @@ static void get_header(struct strbuf *buf, const char *title)
strbuf_addf(buf, "\n\n[%s]\n", title);
}
-int cmd_bugreport(int argc, const char **argv, const char *prefix)
+int cmd_bugreport(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct strbuf buffer = STRBUF_INIT;
struct strbuf report_path = STRBUF_INIT;
diff --git a/builtin/bundle.c b/builtin/bundle.c
index b858552ee6..127518c2a8 100644
--- a/builtin/bundle.c
+++ b/builtin/bundle.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "gettext.h"
@@ -5,7 +6,6 @@
#include "strvec.h"
#include "parse-options.h"
#include "pkt-line.h"
-#include "repository.h"
#include "bundle.h"
/*
@@ -228,7 +228,10 @@ cleanup:
return ret;
}
-int cmd_bundle(int argc, const char **argv, const char *prefix)
+int cmd_bundle(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
parse_opt_subcommand_fn *fn = NULL;
struct option options[] = {
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 1afdfb5cba..bfdfb51c7c 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -3,7 +3,7 @@
*
* Copyright (C) Linus Torvalds, 2005
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "convert.h"
@@ -191,7 +191,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
const char *ls_args[3] = { NULL };
ls_args[0] = "ls-tree";
ls_args[1] = obj_name;
- ret = cmd_ls_tree(2, ls_args, NULL);
+ ret = cmd_ls_tree(2, ls_args, NULL, the_repository);
goto cleanup;
}
@@ -923,7 +923,10 @@ static int batch_option_callback(const struct option *opt,
return 0;
}
-int cmd_cat_file(int argc, const char **argv, const char *prefix)
+int cmd_cat_file(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int opt = 0;
int opt_cw = 0;
diff --git a/builtin/check-attr.c b/builtin/check-attr.c
index 9376810710..7cf275b893 100644
--- a/builtin/check-attr.c
+++ b/builtin/check-attr.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "attr.h"
@@ -5,7 +6,6 @@
#include "gettext.h"
#include "object-name.h"
#include "quote.h"
-#include "repository.h"
#include "setup.h"
#include "parse-options.h"
#include "write-or-die.h"
@@ -107,7 +107,10 @@ static NORETURN void error_with_usage(const char *msg)
usage_with_options(check_attr_usage, check_attr_options);
}
-int cmd_check_attr(int argc, const char **argv, const char *prefix)
+int cmd_check_attr(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct attr_check *check;
struct object_id initialized_oid;
diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c
index 2bda6a1d46..7b7831d13a 100644
--- a/builtin/check-ignore.c
+++ b/builtin/check-ignore.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "dir.h"
@@ -5,7 +6,6 @@
#include "quote.h"
#include "pathspec.h"
#include "parse-options.h"
-#include "repository.h"
#include "submodule.h"
#include "write-or-die.h"
@@ -151,7 +151,10 @@ static int check_ignore_stdin_paths(struct dir_struct *dir, const char *prefix)
return num_ignored;
}
-int cmd_check_ignore(int argc, const char **argv, const char *prefix)
+int cmd_check_ignore(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int num_ignored;
struct dir_struct dir = DIR_INIT;
diff --git a/builtin/check-mailmap.c b/builtin/check-mailmap.c
index 2334b57222..df00b5ee13 100644
--- a/builtin/check-mailmap.c
+++ b/builtin/check-mailmap.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -47,7 +48,10 @@ static void check_mailmap(struct string_list *mailmap, const char *contact)
printf("<%.*s>\n", (int)maillen, mail);
}
-int cmd_check_mailmap(int argc, const char **argv, const char *prefix)
+int cmd_check_mailmap(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int i;
struct string_list mailmap = STRING_LIST_INIT_NODUP;
diff --git a/builtin/check-ref-format.c b/builtin/check-ref-format.c
index 5eb6bdc3f6..e86d8ef980 100644
--- a/builtin/check-ref-format.c
+++ b/builtin/check-ref-format.c
@@ -1,7 +1,6 @@
/*
* GIT - The information manager from hell
*/
-
#include "builtin.h"
#include "refs.h"
#include "setup.h"
@@ -51,7 +50,10 @@ static int check_ref_format_branch(const char *arg)
return 0;
}
-int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
+int cmd_check_ref_format(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int i;
int normalize = 0;
diff --git a/builtin/checkout--worker.c b/builtin/checkout--worker.c
index 6b62b5375b..ff6cdccc21 100644
--- a/builtin/checkout--worker.c
+++ b/builtin/checkout--worker.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "entry.h"
@@ -113,7 +114,10 @@ static const char * const checkout_worker_usage[] = {
NULL
};
-int cmd_checkout__worker(int argc, const char **argv, const char *prefix)
+int cmd_checkout__worker(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct checkout state = CHECKOUT_INIT;
struct option checkout_worker_options[] = {
diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c
index 29e744d11b..6dd38eb05d 100644
--- a/builtin/checkout-index.c
+++ b/builtin/checkout-index.c
@@ -4,13 +4,12 @@
* Copyright (C) 2005 Linus Torvalds
*
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
#include "lockfile.h"
#include "quote.h"
-#include "repository.h"
#include "cache-tree.h"
#include "parse-options.h"
#include "entry.h"
@@ -208,7 +207,10 @@ static int option_parse_stage(const struct option *opt,
return 0;
}
-int cmd_checkout_index(int argc, const char **argv, const char *prefix)
+int cmd_checkout_index(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int i;
struct lock_file lock_file = LOCK_INIT;
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 4cfe6fab50..9c30000d3a 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "advice.h"
#include "branch.h"
@@ -23,6 +24,7 @@
#include "read-cache.h"
#include "refs.h"
#include "remote.h"
+#include "repo-settings.h"
#include "resolve-undo.h"
#include "revision.h"
#include "setup.h"
@@ -950,11 +952,13 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
const char *old_desc, *reflog_msg;
if (opts->new_branch) {
if (opts->new_orphan_branch) {
+ enum log_refs_config log_all_ref_updates =
+ repo_settings_get_log_all_ref_updates(the_repository);
char *refname;
refname = mkpathdup("refs/heads/%s", opts->new_orphan_branch);
if (opts->new_branch_log &&
- !should_autocreate_reflog(refname)) {
+ !should_autocreate_reflog(log_all_ref_updates, refname)) {
int ret;
struct strbuf err = STRBUF_INIT;
@@ -1953,7 +1957,10 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
return ret;
}
-int cmd_checkout(int argc, const char **argv, const char *prefix)
+int cmd_checkout(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct checkout_opts opts = CHECKOUT_OPTS_INIT;
struct option *options;
@@ -2000,7 +2007,10 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
checkout_usage);
}
-int cmd_switch(int argc, const char **argv, const char *prefix)
+int cmd_switch(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct checkout_opts opts = CHECKOUT_OPTS_INIT;
struct option *options = NULL;
@@ -2036,7 +2046,10 @@ int cmd_switch(int argc, const char **argv, const char *prefix)
switch_branch_usage);
}
-int cmd_restore(int argc, const char **argv, const char *prefix)
+int cmd_restore(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct checkout_opts opts = CHECKOUT_OPTS_INIT;
struct option *options;
diff --git a/builtin/clean.c b/builtin/clean.c
index ded5a91534..9c48dd0271 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -5,7 +5,7 @@
*
* Based on git-clean.sh by Pavel Roskin
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "config.h"
@@ -14,7 +14,6 @@
#include "parse-options.h"
#include "path.h"
#include "read-cache-ll.h"
-#include "repository.h"
#include "setup.h"
#include "string-list.h"
#include "quote.h"
@@ -915,7 +914,10 @@ static void correct_untracked_entries(struct dir_struct *dir)
dir->nr = dst;
}
-int cmd_clean(int argc, const char **argv, const char *prefix)
+int cmd_clean(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int i, res;
int dry_run = 0, remove_directories = 0, quiet = 0, ignored = 0;
diff --git a/builtin/clone.c b/builtin/clone.c
index 269b6e18a4..e77339c847 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -7,8 +7,9 @@
*
* Clone a repository into a different directory that does not yet exist.
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
+
#include "abspath.h"
#include "advice.h"
#include "config.h"
@@ -956,7 +957,10 @@ static int path_exists(const char *path)
return !stat(path, &sb);
}
-int cmd_clone(int argc, const char **argv, const char *prefix)
+int cmd_clone(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repository UNUSED)
{
int is_bundle = 0, is_local;
int reject_shallow = 0;
diff --git a/builtin/column.c b/builtin/column.c
index 10ff7e0166..50314cc255 100644
--- a/builtin/column.c
+++ b/builtin/column.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -18,7 +19,10 @@ static int column_config(const char *var, const char *value,
return git_column_config(var, value, cb, &colopts);
}
-int cmd_column(int argc, const char **argv, const char *prefix)
+int cmd_column(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct string_list list = STRING_LIST_INIT_DUP;
struct strbuf sb = STRBUF_INIT;
diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index 7102ee90a0..7c991db6eb 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -1,11 +1,10 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "commit.h"
#include "config.h"
-#include "environment.h"
#include "gettext.h"
#include "hex.h"
#include "parse-options.h"
-#include "repository.h"
#include "commit-graph.h"
#include "object-store-ll.h"
#include "progress.h"
@@ -95,7 +94,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
usage_with_options(builtin_commit_graph_verify_usage, options);
if (!opts.obj_dir)
- opts.obj_dir = get_object_directory();
+ opts.obj_dir = repo_get_object_directory(the_repository);
if (opts.shallow)
flags |= COMMIT_GRAPH_VERIFY_SHALLOW;
if (opts.progress)
@@ -275,7 +274,7 @@ static int graph_write(int argc, const char **argv, const char *prefix)
if (opts.reachable + opts.stdin_packs + opts.stdin_commits > 1)
die(_("use at most one of --reachable, --stdin-commits, or --stdin-packs"));
if (!opts.obj_dir)
- opts.obj_dir = get_object_directory();
+ opts.obj_dir = repo_get_object_directory(the_repository);
if (opts.append)
flags |= COMMIT_GRAPH_WRITE_APPEND;
if (opts.split)
@@ -331,7 +330,10 @@ cleanup:
return result;
}
-int cmd_commit_graph(int argc, const char **argv, const char *prefix)
+int cmd_commit_graph(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
parse_opt_subcommand_fn *fn = NULL;
struct option builtin_commit_graph_options[] = {
diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c
index 84bb450222..2ca1a57ebb 100644
--- a/builtin/commit-tree.c
+++ b/builtin/commit-tree.c
@@ -3,13 +3,14 @@
*
* Copyright (C) Linus Torvalds, 2005
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
#include "hex.h"
#include "object-name.h"
#include "object-store-ll.h"
-#include "repository.h"
+
#include "commit.h"
#include "parse-options.h"
@@ -90,7 +91,10 @@ static int parse_file_arg_callback(const struct option *opt,
return 0;
}
-int cmd_commit_tree(int argc, const char **argv, const char *prefix)
+int cmd_commit_tree(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
static struct strbuf buffer = STRBUF_INIT;
struct commit_list *parents = NULL;
diff --git a/builtin/commit.c b/builtin/commit.c
index b2033c4887..8db4e9df0c 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -4,7 +4,7 @@
* Copyright (c) 2007 Kristian Høgsberg <krh@redhat.com>
* Based on git-commit.sh by Junio C Hamano and Linus Torvalds
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "advice.h"
#include "config.h"
@@ -26,6 +26,7 @@
#include "path.h"
#include "preload-index.h"
#include "read-cache.h"
+#include "repository.h"
#include "string-list.h"
#include "rerere.h"
#include "unpack-trees.h"
@@ -395,7 +396,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT));
setenv(INDEX_ENVIRONMENT, the_repository->index_file, 1);
- if (interactive_add(argv, prefix, patch_interactive) != 0)
+ if (interactive_add(the_repository, argv, prefix, patch_interactive) != 0)
die(_("interactive add failed"));
the_repository->index_file = old_repo_index_file;
@@ -407,7 +408,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
discard_index(the_repository->index);
read_index_from(the_repository->index, get_lock_file_path(&index_lock),
- get_git_dir());
+ repo_get_git_dir(the_repository));
if (cache_tree_update(the_repository->index, WRITE_TREE_SILENT) == 0) {
if (reopen_lock_file(&index_lock) < 0)
die(_("unable to write index file"));
@@ -472,7 +473,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
COMMIT_LOCK | SKIP_IF_UNCHANGED))
die(_("unable to write new index file"));
commit_style = COMMIT_AS_IS;
- ret = get_index_file();
+ ret = repo_get_index_file(the_repository);
goto out;
}
@@ -534,7 +535,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
discard_index(the_repository->index);
ret = get_lock_file_path(&false_lock);
- read_index_from(the_repository->index, ret, get_git_dir());
+ read_index_from(the_repository->index, ret, repo_get_git_dir(the_repository));
out:
string_list_clear(&partial, 0);
clear_pathspec(&pathspec);
@@ -1072,7 +1073,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
*/
discard_index(the_repository->index);
}
- read_index_from(the_repository->index, index_file, get_git_dir());
+ read_index_from(the_repository->index, index_file, repo_get_git_dir(the_repository));
if (cache_tree_update(the_repository->index, 0)) {
error(_("Error building trees"));
@@ -1502,7 +1503,10 @@ static int git_status_config(const char *k, const char *v,
return git_diff_ui_config(k, v, ctx, NULL);
}
-int cmd_status(int argc, const char **argv, const char *prefix)
+int cmd_status(int argc,
+const char **argv,
+const char *prefix,
+struct repository *repo UNUSED)
{
static int no_renames = -1;
static const char *rename_score_arg = (const char *)-1;
@@ -1641,7 +1645,10 @@ static int git_commit_config(const char *k, const char *v,
return git_status_config(k, v, ctx, s);
}
-int cmd_commit(int argc, const char **argv, const char *prefix)
+int cmd_commit(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
static struct wt_status s;
static struct option builtin_commit_options[] = {
@@ -1873,8 +1880,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
repo_rerere(the_repository, 0);
run_auto_maintenance(quiet);
- run_commit_hook(use_editor, get_index_file(), NULL, "post-commit",
- NULL);
+ run_commit_hook(use_editor, repo_get_index_file(the_repository),
+ NULL, "post-commit", NULL);
if (amend && !no_post_rewrite) {
commit_post_rewrite(the_repository, current_head, &oid);
}
diff --git a/builtin/config.c b/builtin/config.c
index 95c8a00915..d8fd3def0e 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -1,10 +1,10 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "config.h"
#include "color.h"
#include "editor.h"
#include "environment.h"
-#include "repository.h"
#include "gettext.h"
#include "ident.h"
#include "parse-options.h"
@@ -807,8 +807,8 @@ static void location_options_init(struct config_location_options *opts,
else
opts->options.respect_includes = opts->respect_includes_opt;
if (startup_info->have_repository) {
- opts->options.commondir = get_git_common_dir();
- opts->options.git_dir = get_git_dir();
+ opts->options.commondir = repo_get_common_dir(the_repository);
+ opts->options.git_dir = repo_get_git_dir(the_repository);
}
}
@@ -1392,7 +1392,10 @@ out:
return ret;
}
-int cmd_config(int argc, const char **argv, const char *prefix)
+int cmd_config(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
parse_opt_subcommand_fn *subcommand = NULL;
struct option subcommand_opts[] = {
diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index ec6098a149..04d80887e0 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -3,14 +3,12 @@
*
* Copyright (c) 2006 Junio C Hamano
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "dir.h"
-#include "environment.h"
#include "gettext.h"
#include "path.h"
-#include "repository.h"
#include "parse-options.h"
#include "quote.h"
#include "packfile.h"
@@ -95,7 +93,10 @@ static char const * const count_objects_usage[] = {
NULL
};
-int cmd_count_objects(int argc, const char **argv, const char *prefix)
+int cmd_count_objects(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int human_readable = 0;
struct option opts[] = {
@@ -116,7 +117,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
report_linked_checkout_garbage(the_repository);
}
- for_each_loose_file_in_objdir(get_object_directory(),
+ for_each_loose_file_in_objdir(repo_get_object_directory(the_repository),
count_loose, count_cruft, NULL, NULL);
if (verbose) {
diff --git a/builtin/credential-cache--daemon.c b/builtin/credential-cache--daemon.c
index 4952b22547..bc22f5c6d2 100644
--- a/builtin/credential-cache--daemon.c
+++ b/builtin/credential-cache--daemon.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "gettext.h"
@@ -287,7 +288,10 @@ static void init_socket_directory(const char *path)
free(path_copy);
}
-int cmd_credential_cache_daemon(int argc, const char **argv, const char *prefix)
+int cmd_credential_cache_daemon(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct tempfile *socket_file;
const char *socket_path;
@@ -330,7 +334,10 @@ int cmd_credential_cache_daemon(int argc, const char **argv, const char *prefix)
#else
-int cmd_credential_cache_daemon(int argc, const char **argv, const char *prefix)
+int cmd_credential_cache_daemon(int argc,
+const char **argv,
+const char *prefix,
+struct repository *repo UNUSED)
{
const char * const usage[] = {
"git credential-cache--daemon [--debug] <socket-path>",
diff --git a/builtin/credential-cache.c b/builtin/credential-cache.c
index aaf2f8438b..5de8b9123b 100644
--- a/builtin/credential-cache.c
+++ b/builtin/credential-cache.c
@@ -137,7 +137,10 @@ static void announce_capabilities(void)
credential_announce_capabilities(&c, stdout);
}
-int cmd_credential_cache(int argc, const char **argv, const char *prefix)
+int cmd_credential_cache(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
const char *socket_path_arg = NULL;
char *socket_path;
diff --git a/builtin/credential-store.c b/builtin/credential-store.c
index 97968bfa1c..e669e99dbf 100644
--- a/builtin/credential-store.c
+++ b/builtin/credential-store.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -170,7 +171,10 @@ static void lookup_credential(const struct string_list *fns, struct credential *
return; /* Found credential */
}
-int cmd_credential_store(int argc, const char **argv, const char *prefix)
+int cmd_credential_store(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
const char * const usage[] = {
"git credential-store [<options>] <action>",
diff --git a/builtin/credential.c b/builtin/credential.c
index b72e76dd9a..14c8c6608b 100644
--- a/builtin/credential.c
+++ b/builtin/credential.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
#include "credential.h"
#include "builtin.h"
@@ -6,7 +8,10 @@
static const char usage_msg[] =
"git credential (fill|approve|reject)";
-int cmd_credential(int argc, const char **argv, const char *prefix UNUSED)
+int cmd_credential(int argc,
+ const char **argv,
+ const char *prefix UNUSED,
+ struct repository *repo UNUSED)
{
const char *op;
struct credential c = CREDENTIAL_INIT;
diff --git a/builtin/describe.c b/builtin/describe.c
index b43093c099..7330a77b38 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "environment.h"
@@ -571,7 +572,10 @@ static int option_parse_exact_match(const struct option *opt, const char *arg,
return 0;
}
-int cmd_describe(int argc, const char **argv, const char *prefix)
+int cmd_describe(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED )
{
int contains = 0;
struct option options[] = {
@@ -650,7 +654,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
argv_copy[i] = args.v[i];
argv_copy[args.nr] = NULL;
- ret = cmd_name_rev(args.nr, argv_copy, prefix);
+ ret = cmd_name_rev(args.nr, argv_copy, prefix, the_repository);
strvec_clear(&args);
free(argv_copy);
@@ -716,7 +720,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
BUG("malformed internal diff-index command line");
run_diff_index(&revs, 0);
- if (!diff_result_code(&revs.diffopt))
+ if (!diff_result_code(&revs))
suffix = NULL;
else
suffix = dirty;
diff --git a/builtin/diagnose.c b/builtin/diagnose.c
index 4857a4395b..66a22d918e 100644
--- a/builtin/diagnose.c
+++ b/builtin/diagnose.c
@@ -11,7 +11,10 @@ static const char * const diagnose_usage[] = {
NULL
};
-int cmd_diagnose(int argc, const char **argv, const char *prefix)
+int cmd_diagnose(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct strbuf zip_path = STRBUF_INIT;
time_t now = time(NULL);
diff --git a/builtin/diff-files.c b/builtin/diff-files.c
index 018011f29e..e0e0ccec23 100644
--- a/builtin/diff-files.c
+++ b/builtin/diff-files.c
@@ -3,13 +3,13 @@
*
* Copyright (C) Linus Torvalds, 2005
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "diff.h"
#include "diff-merges.h"
#include "commit.h"
#include "preload-index.h"
-#include "repository.h"
#include "revision.h"
static const char diff_files_usage[] =
@@ -17,7 +17,10 @@ static const char diff_files_usage[] =
"\n"
COMMON_DIFF_OPTIONS_HELP;
-int cmd_diff_files(int argc, const char **argv, const char *prefix)
+int cmd_diff_files(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct rev_info rev;
int result;
@@ -82,7 +85,7 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix)
if (repo_read_index_preload(the_repository, &rev.diffopt.pathspec, 0) < 0)
die_errno("repo_read_index_preload");
run_diff_files(&rev, options);
- result = diff_result_code(&rev.diffopt);
+ result = diff_result_code(&rev);
release_revisions(&rev);
return result;
}
diff --git a/builtin/diff-index.c b/builtin/diff-index.c
index 685b60284f..ad503624c0 100644
--- a/builtin/diff-index.c
+++ b/builtin/diff-index.c
@@ -1,10 +1,10 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "diff.h"
#include "diff-merges.h"
#include "commit.h"
#include "preload-index.h"
-#include "repository.h"
#include "revision.h"
#include "setup.h"
@@ -14,7 +14,10 @@ static const char diff_cache_usage[] =
"\n"
COMMON_DIFF_OPTIONS_HELP;
-int cmd_diff_index(int argc, const char **argv, const char *prefix)
+int cmd_diff_index(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct rev_info rev;
unsigned int option = 0;
@@ -75,7 +78,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix)
return -1;
}
run_diff_index(&rev, option);
- result = diff_result_code(&rev.diffopt);
+ result = diff_result_code(&rev);
release_revisions(&rev);
return result;
}
diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c
index b8df1d4b79..4b6656bb9f 100644
--- a/builtin/diff-tree.c
+++ b/builtin/diff-tree.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "diff.h"
@@ -6,7 +7,6 @@
#include "hex.h"
#include "log-tree.h"
#include "read-cache-ll.h"
-#include "repository.h"
#include "revision.h"
#include "tmp-objdir.h"
#include "tree.h"
@@ -108,7 +108,10 @@ static void diff_tree_tweak_rev(struct rev_info *rev)
}
}
-int cmd_diff_tree(int argc, const char **argv, const char *prefix)
+int cmd_diff_tree(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
char line[1000];
struct object *tree1, *tree2;
@@ -167,13 +170,6 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
opt->diffopt.rotate_to_strict = 1;
- if (opt->remerge_diff) {
- opt->remerge_objdir = tmp_objdir_create("remerge-diff");
- if (!opt->remerge_objdir)
- die(_("unable to create temporary object directory"));
- tmp_objdir_replace_primary_odb(opt->remerge_objdir, 1);
- }
-
/*
* NOTE! We expect "a..b" to expand to "^a b" but it is
* perfectly valid for revision range parser to yield "b ^a",
@@ -238,10 +234,5 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
diff_free(&opt->diffopt);
}
- if (opt->remerge_diff) {
- tmp_objdir_destroy(opt->remerge_objdir);
- opt->remerge_objdir = NULL;
- }
-
- return diff_result_code(&opt->diffopt);
+ return diff_result_code(opt);
}
diff --git a/builtin/diff.c b/builtin/diff.c
index 6eac445579..dca52d4221 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -3,7 +3,7 @@
*
* Copyright (c) 2006 Junio C Hamano
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "ewah/ewok.h"
@@ -393,7 +393,10 @@ static void symdiff_release(struct symdiff *sdiff)
bitmap_free(sdiff->skip);
}
-int cmd_diff(int argc, const char **argv, const char *prefix)
+int cmd_diff(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int i;
struct rev_info rev;
@@ -619,7 +622,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
builtin_diff_combined(&rev, argc, argv,
ent.objects, ent.nr,
first_non_parent);
- result = diff_result_code(&rev.diffopt);
+ result = diff_result_code(&rev);
if (1 < rev.diffopt.skip_stat_unmatch)
refresh_index_quietly();
release_revisions(&rev);
diff --git a/builtin/difftool.c b/builtin/difftool.c
index 1a68ab6699..5772e82106 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -11,8 +11,9 @@
*
* Copyright (C) 2016 Johannes Schindelin
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
+
#include "abspath.h"
#include "config.h"
#include "copy.h"
@@ -22,6 +23,7 @@
#include "hex.h"
#include "parse-options.h"
#include "read-cache-ll.h"
+#include "repository.h"
#include "sparse-index.h"
#include "strvec.h"
#include "strbuf.h"
@@ -214,7 +216,7 @@ static void changed_files(struct hashmap *result, const char *index_path,
struct child_process update_index = CHILD_PROCESS_INIT;
struct child_process diff_files = CHILD_PROCESS_INIT;
struct strbuf buf = STRBUF_INIT;
- const char *git_dir = absolute_path(get_git_dir());
+ const char *git_dir = absolute_path(repo_get_git_dir(the_repository));
FILE *fp;
strvec_pushl(&update_index.args,
@@ -377,7 +379,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
struct hashmap wt_modified, tmp_modified;
int indices_loaded = 0;
- workdir = get_git_work_tree();
+ workdir = repo_get_work_tree(the_repository);
/* Setup temp directories */
tmp = getenv("TMPDIR");
@@ -696,7 +698,10 @@ static int run_file_diff(int prompt, const char *prefix,
return run_command(child);
}
-int cmd_difftool(int argc, const char **argv, const char *prefix)
+int cmd_difftool(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int use_gui_tool = -1, dir_diff = 0, prompt = -1, symlinks = 0,
tool_help = 0, no_index = 0;
@@ -743,8 +748,8 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
if (!no_index){
setup_work_tree();
- setenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1);
- setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);
+ setenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(the_repository)), 1);
+ setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(repo_get_work_tree(the_repository)), 1);
} else if (dir_diff)
die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index");
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index f253b79322..e17f262e8e 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2007 Johannes E. Schindelin
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -1180,7 +1181,10 @@ static int parse_opt_anonymize_map(const struct option *opt,
return 0;
}
-int cmd_fast_export(int argc, const char **argv, const char *prefix)
+int cmd_fast_export(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct rev_info revs;
struct commit *commit;
diff --git a/builtin/fast-import.c b/builtin/fast-import.c
index 2214c105f1..1e7ab67f6e 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
@@ -1,9 +1,9 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
-#include "repository.h"
#include "config.h"
#include "lockfile.h"
#include "object.h"
@@ -3537,7 +3537,10 @@ static void parse_argv(void)
build_mark_map(&sub_marks_from, &sub_marks_to);
}
-int cmd_fast_import(int argc, const char **argv, const char *prefix)
+int cmd_fast_import(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
unsigned int i;
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index fe404d1305..49222a36fa 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "gettext.h"
#include "hex.h"
@@ -43,7 +44,10 @@ static void add_sought_entry(struct ref ***sought, int *nr, int *alloc,
(*sought)[*nr - 1] = ref;
}
-int cmd_fetch_pack(int argc, const char **argv, const char *prefix UNUSED)
+int cmd_fetch_pack(int argc,
+ const char **argv,
+ const char *prefix UNUSED,
+ struct repository *repo UNUSED)
{
int i, ret;
struct ref *fetched_refs = NULL, *remote_refs = NULL;
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 55f97134aa..c900f57721 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -1,13 +1,13 @@
/*
* "git fetch"
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "advice.h"
#include "config.h"
#include "gettext.h"
#include "environment.h"
#include "hex.h"
-#include "repository.h"
#include "refs.h"
#include "refspec.h"
#include "object-name.h"
@@ -2138,7 +2138,10 @@ static int fetch_one(struct remote *remote, int argc, const char **argv,
return exit_code;
}
-int cmd_fetch(int argc, const char **argv, const char *prefix)
+int cmd_fetch(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct fetch_config config = {
.display_format = DISPLAY_FORMAT_FULL,
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 0b162f8fab..189cd1096a 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "fmt-merge-msg.h"
@@ -9,7 +10,10 @@ static const char * const fmt_merge_msg_usage[] = {
NULL
};
-int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
+int cmd_fmt_merge_msg(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
char *inpath = NULL;
const char *message = NULL;
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 5517a4a1c0..715745a262 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "commit.h"
#include "config.h"
@@ -16,7 +17,10 @@ static char const * const for_each_ref_usage[] = {
NULL
};
-int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
+int cmd_for_each_ref(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct ref_sorting *sorting;
struct string_list sorting_options = STRING_LIST_INIT_DUP;
@@ -104,6 +108,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
filter_and_format_refs(&filter, flags, sorting, &format);
ref_filter_clear(&filter);
+ ref_format_clear(&format);
ref_sorting_release(sorting);
strvec_clear(&vec);
return 0;
diff --git a/builtin/for-each-repo.c b/builtin/for-each-repo.c
index c4fa41fda9..fae7f91cf1 100644
--- a/builtin/for-each-repo.c
+++ b/builtin/for-each-repo.c
@@ -1,9 +1,9 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
#include "parse-options.h"
#include "path.h"
-#include "repository.h"
#include "run-command.h"
#include "string-list.h"
@@ -29,7 +29,10 @@ static int run_command_on_repo(const char *path, int argc, const char ** argv)
return run_command(&child);
}
-int cmd_for_each_repo(int argc, const char **argv, const char *prefix)
+int cmd_for_each_repo(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
static const char *config_key = NULL;
int keep_going = 0;
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 60f4e6fad9..7f4e2f0414 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -1,7 +1,7 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "gettext.h"
#include "hex.h"
-#include "repository.h"
#include "config.h"
#include "commit.h"
#include "tree.h"
@@ -925,7 +925,10 @@ static struct option fsck_opts[] = {
OPT_END(),
};
-int cmd_fsck(int argc, const char **argv, const char *prefix)
+int cmd_fsck(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int i;
struct object_directory *odb;
diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c
index 1593713f4c..dce8a3b248 100644
--- a/builtin/fsmonitor--daemon.c
+++ b/builtin/fsmonitor--daemon.c
@@ -1,8 +1,8 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "config.h"
#include "dir.h"
-#include "environment.h"
#include "gettext.h"
#include "parse-options.h"
#include "fsmonitor-ll.h"
@@ -11,7 +11,7 @@
#include "compat/fsmonitor/fsm-health.h"
#include "compat/fsmonitor/fsm-listen.h"
#include "fsmonitor--daemon.h"
-#include "repository.h"
+
#include "simple-ipc.h"
#include "khash.h"
#include "run-command.h"
@@ -1291,7 +1291,8 @@ static int fsmonitor_run_daemon(void)
/* Prepare to (recursively) watch the <worktree-root> directory. */
strbuf_init(&state.path_worktree_watch, 0);
- strbuf_addstr(&state.path_worktree_watch, absolute_path(get_git_work_tree()));
+ strbuf_addstr(&state.path_worktree_watch,
+ absolute_path(repo_get_work_tree(the_repository)));
state.nr_paths_watching = 1;
strbuf_init(&state.alias.alias, 0);
@@ -1311,7 +1312,8 @@ static int fsmonitor_run_daemon(void)
strbuf_addstr(&state.path_gitdir_watch, "/.git");
if (!is_directory(state.path_gitdir_watch.buf)) {
strbuf_reset(&state.path_gitdir_watch);
- strbuf_addstr(&state.path_gitdir_watch, absolute_path(get_git_dir()));
+ strbuf_addstr(&state.path_gitdir_watch,
+ absolute_path(repo_get_git_dir(the_repository)));
state.nr_paths_watching = 2;
}
@@ -1521,7 +1523,10 @@ static int try_to_start_background_daemon(void)
}
}
-int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix)
+int cmd_fsmonitor__daemon(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
const char *subcmd;
enum fsmonitor_reason reason;
@@ -1584,7 +1589,7 @@ int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix)
}
#else
-int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix UNUSED)
+int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix UNUSED, struct repository *repo UNUSED)
{
struct option options[] = {
OPT_END()
diff --git a/builtin/gc.c b/builtin/gc.c
index b68a0be62c..6a7a2da006 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -9,13 +9,12 @@
*
* Copyright (c) 2006 Shawn O. Pearce
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "date.h"
#include "environment.h"
#include "hex.h"
-#include "repository.h"
#include "config.h"
#include "tempfile.h"
#include "lockfile.h"
@@ -657,7 +656,10 @@ static void gc_before_repack(struct maintenance_run_opts *opts,
}
}
-int cmd_gc(int argc, const char **argv, const char *prefix)
+int cmd_gc(int argc,
+const char **argv,
+const char *prefix,
+struct repository *repo UNUSED)
{
int aggressive = 0;
int quiet = 0;
@@ -1766,6 +1768,42 @@ static const char *get_frequency(enum schedule_priority schedule)
}
}
+static const char *extraconfig[] = {
+ "credential.interactive=false",
+ "core.askPass=true", /* 'true' returns success, but no output. */
+ NULL
+};
+
+static const char *get_extra_config_parameters(void) {
+ static const char *result = NULL;
+ struct strbuf builder = STRBUF_INIT;
+
+ if (result)
+ return result;
+
+ for (const char **s = extraconfig; s && *s; s++)
+ strbuf_addf(&builder, "-c %s ", *s);
+
+ result = strbuf_detach(&builder, NULL);
+ return result;
+}
+
+static const char *get_extra_launchctl_strings(void) {
+ static const char *result = NULL;
+ struct strbuf builder = STRBUF_INIT;
+
+ if (result)
+ return result;
+
+ for (const char **s = extraconfig; s && *s; s++) {
+ strbuf_addstr(&builder, "<string>-c</string>\n");
+ strbuf_addf(&builder, "<string>%s</string>\n", *s);
+ }
+
+ result = strbuf_detach(&builder, NULL);
+ return result;
+}
+
/*
* get_schedule_cmd` reads the GIT_TEST_MAINT_SCHEDULER environment variable
* to mock the schedulers that `git maintenance start` rely on.
@@ -1979,6 +2017,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit
"<array>\n"
"<string>%s/git</string>\n"
"<string>--exec-path=%s</string>\n"
+ "%s" /* For extra config parameters. */
"<string>for-each-repo</string>\n"
"<string>--keep-going</string>\n"
"<string>--config=maintenance.repo</string>\n"
@@ -1988,7 +2027,8 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit
"</array>\n"
"<key>StartCalendarInterval</key>\n"
"<array>\n";
- strbuf_addf(&plist, preamble, name, exec_path, exec_path, frequency);
+ strbuf_addf(&plist, preamble, name, exec_path, exec_path,
+ get_extra_launchctl_strings(), frequency);
switch (schedule) {
case SCHEDULE_HOURLY:
@@ -2140,7 +2180,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority
get_schedule_cmd("schtasks", NULL, &cmd);
strbuf_addf(&tfilename, "%s/schedule_%s_XXXXXX",
- get_git_common_dir(), frequency);
+ repo_get_common_dir(the_repository), frequency);
tfile = xmks_tempfile(tfilename.buf);
strbuf_release(&tfilename);
@@ -2224,11 +2264,12 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority
"<Actions Context=\"Author\">\n"
"<Exec>\n"
"<Command>\"%s\\headless-git.exe\"</Command>\n"
- "<Arguments>--exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%s</Arguments>\n"
+ "<Arguments>--exec-path=\"%s\" %s for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%s</Arguments>\n"
"</Exec>\n"
"</Actions>\n"
"</Task>\n";
- fprintf(tfile->fp, xml, exec_path, exec_path, frequency);
+ fprintf(tfile->fp, xml, exec_path, exec_path,
+ get_extra_config_parameters(), frequency);
strvec_split(&child.args, cmd);
strvec_pushl(&child.args, "/create", "/tn", name, "/f", "/xml",
get_tempfile_path(tfile), NULL);
@@ -2379,8 +2420,8 @@ static int crontab_update_schedule(int run_maintenance, int fd)
"# replaced in the future by a Git command.\n\n");
strbuf_addf(&line_format,
- "%%d %%s * * %%s \"%s/git\" --exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%s\n",
- exec_path, exec_path);
+ "%%d %%s * * %%s \"%s/git\" --exec-path=\"%s\" %s for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%s\n",
+ exec_path, exec_path, get_extra_config_parameters());
fprintf(cron_in, line_format.buf, minute, "1-23", "*", "hourly");
fprintf(cron_in, line_format.buf, minute, "0", "1-6", "daily");
fprintf(cron_in, line_format.buf, minute, "0", "0", "weekly");
@@ -2581,7 +2622,7 @@ static int systemd_timer_write_service_template(const char *exec_path)
"\n"
"[Service]\n"
"Type=oneshot\n"
- "ExecStart=\"%s/git\" --exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%i\n"
+ "ExecStart=\"%s/git\" --exec-path=\"%s\" %s for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%i\n"
"LockPersonality=yes\n"
"MemoryDenyWriteExecute=yes\n"
"NoNewPrivileges=yes\n"
@@ -2591,7 +2632,7 @@ static int systemd_timer_write_service_template(const char *exec_path)
"RestrictSUIDSGID=yes\n"
"SystemCallArchitectures=native\n"
"SystemCallFilter=@system-service\n";
- if (fprintf(file, unit, exec_path, exec_path) < 0) {
+ if (fprintf(file, unit, exec_path, exec_path, get_extra_config_parameters()) < 0) {
error(_("failed to write to '%s'"), filename);
fclose(file);
goto error;
@@ -2923,7 +2964,10 @@ static const char * const builtin_maintenance_usage[] = {
NULL,
};
-int cmd_maintenance(int argc, const char **argv, const char *prefix)
+int cmd_maintenance(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
parse_opt_subcommand_fn *fn = NULL;
struct option builtin_maintenance_options[] = {
diff --git a/builtin/get-tar-commit-id.c b/builtin/get-tar-commit-id.c
index 7195a072ed..6bec0d1854 100644
--- a/builtin/get-tar-commit-id.c
+++ b/builtin/get-tar-commit-id.c
@@ -12,7 +12,10 @@ static const char builtin_get_tar_commit_id_usage[] =
#define RECORDSIZE (512)
#define HEADERSIZE (2 * RECORDSIZE)
-int cmd_get_tar_commit_id(int argc, const char **argv UNUSED, const char *prefix)
+int cmd_get_tar_commit_id(int argc,
+ const char **argv UNUSED,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
char buffer[HEADERSIZE];
struct ustar_header *header = (struct ustar_header *)buffer;
diff --git a/builtin/grep.c b/builtin/grep.c
index dda4582d64..f17d46a06e 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -3,11 +3,11 @@
*
* Copyright (c) 2006 Junio C Hamano
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "gettext.h"
#include "hex.h"
-#include "repository.h"
#include "config.h"
#include "tag.h"
#include "tree-walk.h"
@@ -888,7 +888,10 @@ static int pattern_callback(const struct option *opt, const char *arg,
return 0;
}
-int cmd_grep(int argc, const char **argv, const char *prefix)
+int cmd_grep(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int hit = 0;
int cached = 0, untracked = 0, opt_exclude = -1;
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index c767414a0c..a25f0403f4 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -4,6 +4,7 @@
* Copyright (C) Linus Torvalds, 2005
* Copyright (C) Junio C Hamano, 2005
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "config.h"
@@ -84,7 +85,10 @@ static void hash_stdin_paths(const char *type, int no_filters, unsigned flags,
strbuf_release(&unquoted);
}
-int cmd_hash_object(int argc, const char **argv, const char *prefix)
+int cmd_hash_object(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
static const char * const hash_object_usage[] = {
N_("git hash-object [-t <type>] [-w] [--path=<file> | --no-filters]\n"
diff --git a/builtin/help.c b/builtin/help.c
index 2c249cbca4..4a5a079070 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -1,6 +1,8 @@
+
/*
* Builtin help command
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "exec-cmd.h"
@@ -542,7 +544,7 @@ static void open_html(const char *path)
static void show_html_page(const char *page)
{
- struct strbuf page_path; /* it leaks but we exec bellow */
+ struct strbuf page_path; /* it leaks but we exec below */
get_html_page_path(&page_path, page);
@@ -633,7 +635,10 @@ static void opt_mode_usage(int argc, const char *opt_mode,
no_help_format(opt_mode, fmt);
}
-int cmd_help(int argc, const char **argv, const char *prefix)
+int cmd_help(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int nongit;
enum help_format parsed_help_format;
diff --git a/builtin/hook.c b/builtin/hook.c
index cc37438fde..367ef3e0b8 100644
--- a/builtin/hook.c
+++ b/builtin/hook.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -66,7 +67,10 @@ usage:
usage_with_options(builtin_hook_run_usage, run_options);
}
-int cmd_hook(int argc, const char **argv, const char *prefix)
+int cmd_hook(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
parse_opt_subcommand_fn *fn = NULL;
struct option builtin_hook_options[] = {
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 763b01372a..e228c56ff2 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "delta.h"
@@ -1718,7 +1719,10 @@ static void show_pack_info(int stat_only)
free(chain_histogram);
}
-int cmd_index_pack(int argc, const char **argv, const char *prefix)
+int cmd_index_pack(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index;
const char *curr_index;
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 582dcf20f8..7e00d57d65 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -3,6 +3,7 @@
*
* Copyright (C) Linus Torvalds, 2005
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "environment.h"
@@ -11,7 +12,6 @@
#include "parse-options.h"
#include "path.h"
#include "refs.h"
-#include "repository.h"
#include "setup.h"
#include "strbuf.h"
@@ -70,7 +70,10 @@ static const char *const init_db_usage[] = {
* On the other hand, it might just make lookup slower and messier. You
* be the judge. The default case is to have one DB per managed directory.
*/
-int cmd_init_db(int argc, const char **argv, const char *prefix)
+int cmd_init_db(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
const char *git_dir;
const char *real_git_dir = NULL;
@@ -231,9 +234,9 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
set_git_work_tree(work_tree);
else
set_git_work_tree(git_work_tree_cfg);
- if (access(get_git_work_tree(), X_OK))
+ if (access(repo_get_work_tree(the_repository), X_OK))
die_errno (_("Cannot access work tree '%s'"),
- get_git_work_tree());
+ repo_get_work_tree(the_repository));
}
else {
if (real_git_dir)
diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c
index e6f22459f1..c5e56e2cd3 100644
--- a/builtin/interpret-trailers.c
+++ b/builtin/interpret-trailers.c
@@ -4,7 +4,7 @@
* Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org>
*
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "gettext.h"
#include "parse-options.h"
@@ -189,7 +189,10 @@ static void interpret_trailers(const struct process_trailer_options *opts,
strbuf_release(&sb);
}
-int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
+int cmd_interpret_trailers(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
LIST_HEAD(trailers);
diff --git a/builtin/log.c b/builtin/log.c
index 36769bab3b..368f6580a6 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -4,6 +4,7 @@
* (C) Copyright 2006 Linus Torvalds
* 2006 Junio Hamano
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "config.h"
@@ -37,7 +38,7 @@
#include "mailmap.h"
#include "progress.h"
#include "commit-slab.h"
-#include "repository.h"
+
#include "commit-reach.h"
#include "range-diff.h"
#include "tmp-objdir.h"
@@ -504,13 +505,7 @@ static int cmd_log_walk_no_free(struct rev_info *rev)
struct commit *commit;
int saved_nrl = 0;
int saved_dcctc = 0;
-
- if (rev->remerge_diff) {
- rev->remerge_objdir = tmp_objdir_create("remerge-diff");
- if (!rev->remerge_objdir)
- die(_("unable to create temporary object directory"));
- tmp_objdir_replace_primary_odb(rev->remerge_objdir, 1);
- }
+ int result;
if (rev->early_output)
setup_early_output();
@@ -551,16 +546,12 @@ static int cmd_log_walk_no_free(struct rev_info *rev)
rev->diffopt.degraded_cc_to_c = saved_dcctc;
rev->diffopt.needed_rename_limit = saved_nrl;
- if (rev->remerge_diff) {
- tmp_objdir_destroy(rev->remerge_objdir);
- rev->remerge_objdir = NULL;
- }
-
+ result = diff_result_code(rev);
if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF &&
rev->diffopt.flags.check_failed) {
- return 02;
+ result = 02;
}
- return diff_result_code(&rev->diffopt);
+ return result;
}
static int cmd_log_walk(struct rev_info *rev)
@@ -637,7 +628,10 @@ static int git_log_config(const char *var, const char *value,
return git_diff_ui_config(var, value, ctx, cb);
}
-int cmd_whatchanged(int argc, const char **argv, const char *prefix)
+int cmd_whatchanged(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct log_config cfg;
struct rev_info rev;
@@ -758,7 +752,10 @@ static void show_setup_revisions_tweak(struct rev_info *rev)
rev->diffopt.output_format = DIFF_FORMAT_PATCH;
}
-int cmd_show(int argc, const char **argv, const char *prefix)
+int cmd_show(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct log_config cfg;
struct rev_info rev;
@@ -874,7 +871,10 @@ int cmd_show(int argc, const char **argv, const char *prefix)
/*
* This is equivalent to "git log -g --abbrev-commit --pretty=oneline"
*/
-int cmd_log_reflog(int argc, const char **argv, const char *prefix)
+int cmd_log_reflog(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct log_config cfg;
struct rev_info rev;
@@ -916,7 +916,10 @@ static void log_setup_revisions_tweak(struct rev_info *rev)
diff_merges_default_to_first_parent(rev);
}
-int cmd_log(int argc, const char **argv, const char *prefix)
+int cmd_log(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct log_config cfg;
struct rev_info rev;
@@ -1986,7 +1989,10 @@ static void infer_range_diff_ranges(struct strbuf *r1,
}
}
-int cmd_format_patch(int argc, const char **argv, const char *prefix)
+int cmd_format_patch(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct format_config cfg;
struct commit *commit;
@@ -2619,7 +2625,10 @@ static void print_commit(char sign, struct commit *commit, int verbose,
}
}
-int cmd_cherry(int argc, const char **argv, const char *prefix)
+int cmd_cherry(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct rev_info revs;
struct patch_ids ids;
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 6eeb5cba78..e016b0415d 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -5,8 +5,8 @@
*
* Copyright (C) Linus Torvalds, 2005
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
-#include "repository.h"
#include "config.h"
#include "convert.h"
#include "quote.h"
@@ -507,7 +507,7 @@ static int get_common_prefix_len(const char *common_prefix)
common_prefix_len = strlen(common_prefix);
/*
- * If the prefix has a trailing slash, strip it so that submodules wont
+ * If the prefix has a trailing slash, strip it so that submodules won't
* be pruned from the index.
*/
if (common_prefix[common_prefix_len - 1] == '/')
@@ -561,7 +561,10 @@ static int option_parse_exclude_standard(const struct option *opt,
return 0;
}
-int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
+int cmd_ls_files(int argc,
+ const char **argv,
+ const char *cmd_prefix,
+ struct repository *repo UNUSED)
{
int require_work_tree = 0, show_tag = 0, i;
char *max_prefix;
diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
index 0a491595ca..f723b3bf3b 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "gettext.h"
#include "hex.h"
@@ -37,7 +38,10 @@ static int tail_match(const struct strvec *pattern, const char *path)
return 0;
}
-int cmd_ls_remote(int argc, const char **argv, const char *prefix)
+int cmd_ls_remote(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
const char *dest = NULL;
unsigned flags = 0;
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index bf372c67d7..8542b5d53e 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -3,7 +3,9 @@
*
* Copyright (C) Linus Torvalds, 2005
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
+
#include "config.h"
#include "gettext.h"
#include "hex.h"
@@ -329,7 +331,10 @@ static struct ls_tree_cmdmode_to_fmt ls_tree_cmdmode_format[] = {
},
};
-int cmd_ls_tree(int argc, const char **argv, const char *prefix)
+int cmd_ls_tree(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct object_id oid;
struct tree *tree;
diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c
index 53a22645da..e17dec27b1 100644
--- a/builtin/mailinfo.c
+++ b/builtin/mailinfo.c
@@ -2,6 +2,7 @@
* Another stupid program, this one parsing the headers of an
* email to figure out authorship and subject
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "environment.h"
@@ -48,7 +49,10 @@ static int parse_opt_quoted_cr(const struct option *opt, const char *arg, int un
return 0;
}
-int cmd_mailinfo(int argc, const char **argv, const char *prefix)
+int cmd_mailinfo(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct metainfo_charset meta_charset;
struct mailinfo mi;
diff --git a/builtin/mailsplit.c b/builtin/mailsplit.c
index fe6dbc5d05..b8f7150ce9 100644
--- a/builtin/mailsplit.c
+++ b/builtin/mailsplit.c
@@ -269,7 +269,10 @@ out:
return ret;
}
-int cmd_mailsplit(int argc, const char **argv, const char *prefix)
+int cmd_mailsplit(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int nr = 0, nr_prec = 4, num = 0;
int allow_bare = 0;
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index 5a8e729502..a20c93b11a 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "commit.h"
@@ -5,7 +6,6 @@
#include "hex.h"
#include "object-name.h"
#include "parse-options.h"
-#include "repository.h"
#include "commit-reach.h"
static int show_merge_base(struct commit **rev, int rev_nr, int show_all)
@@ -143,7 +143,10 @@ static int handle_fork_point(int argc, const char **argv)
return 0;
}
-int cmd_merge_base(int argc, const char **argv, const char *prefix)
+int cmd_merge_base(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct commit **rev;
int rev_nr = 0;
diff --git a/builtin/merge-file.c b/builtin/merge-file.c
index 1f987334a3..cb42865eb5 100644
--- a/builtin/merge-file.c
+++ b/builtin/merge-file.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "diff.h"
@@ -53,7 +54,10 @@ static int diff_algorithm_cb(const struct option *opt,
return 0;
}
-int cmd_merge_file(int argc, const char **argv, const char *prefix)
+int cmd_merge_file(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
const char *names[3] = { 0 };
mmfile_t mmfs[3] = { 0 };
diff --git a/builtin/merge-index.c b/builtin/merge-index.c
index 0fabe3f6bb..a5b87ee3c5 100644
--- a/builtin/merge-index.c
+++ b/builtin/merge-index.c
@@ -1,7 +1,7 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "hex.h"
#include "read-cache-ll.h"
-#include "repository.h"
#include "run-command.h"
#include "sparse-index.h"
@@ -73,7 +73,10 @@ static void merge_all(void)
}
}
-int cmd_merge_index(int argc, const char **argv, const char *prefix UNUSED)
+int cmd_merge_index(int argc,
+ const char **argv,
+ const char *prefix UNUSED,
+ struct repository *repo UNUSED)
{
int i, force_file = 0;
diff --git a/builtin/merge-ours.c b/builtin/merge-ours.c
index 932924e5d0..1fcf53f005 100644
--- a/builtin/merge-ours.c
+++ b/builtin/merge-ours.c
@@ -7,15 +7,19 @@
*
* Pretend we resolved the heads, but declare our tree trumps everybody else.
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "git-compat-util.h"
#include "builtin.h"
#include "diff.h"
-#include "repository.h"
+
static const char builtin_merge_ours_usage[] =
"git merge-ours <base>... -- HEAD <remote>...";
-int cmd_merge_ours(int argc, const char **argv, const char *prefix UNUSED)
+int cmd_merge_ours(int argc,
+ const char **argv,
+ const char *prefix UNUSED,
+ struct repository *repo UNUSED)
{
if (argc == 2 && !strcmp(argv[1], "-h"))
usage(builtin_merge_ours_usage);
diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c
index e951b09805..1dd295558b 100644
--- a/builtin/merge-recursive.c
+++ b/builtin/merge-recursive.c
@@ -1,10 +1,10 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "advice.h"
#include "gettext.h"
#include "hash.h"
#include "merge-recursive.h"
#include "object-name.h"
-#include "repository.h"
static const char builtin_merge_recursive_usage[] =
"git %s <base>... -- <head> <remote> ...";
@@ -21,7 +21,10 @@ static char *better_branch_name(const char *branch)
return xstrdup(name ? name : branch);
}
-int cmd_merge_recursive(int argc, const char **argv, const char *prefix UNUSED)
+int cmd_merge_recursive(int argc,
+ const char **argv,
+ const char *prefix UNUSED,
+ struct repository *repo UNUSED)
{
struct object_id bases[21];
unsigned bases_count = 0;
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index c00469ed3d..c5ed472967 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "tree-walk.h"
#include "xdiff-interface.h"
@@ -10,7 +11,6 @@
#include "object-name.h"
#include "object-store-ll.h"
#include "parse-options.h"
-#include "repository.h"
#include "blob.h"
#include "merge-blobs.h"
#include "quote.h"
@@ -526,7 +526,10 @@ static int real_merge(struct merge_tree_options *o,
return !result.clean; /* result.clean < 0 handled above */
}
-int cmd_merge_tree(int argc, const char **argv, const char *prefix)
+int cmd_merge_tree(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct merge_tree_options o = { .show_messages = -1 };
struct strvec xopts = STRVEC_INIT;
diff --git a/builtin/merge.c b/builtin/merge.c
index 662a49a0e8..84d0f3604b 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -5,8 +5,9 @@
*
* Based on git-merge.sh by Junio C Hamano.
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
+
#include "abspath.h"
#include "advice.h"
#include "config.h"
@@ -17,6 +18,7 @@
#include "object-name.h"
#include "parse-options.h"
#include "lockfile.h"
+#include "repository.h"
#include "run-command.h"
#include "hook.h"
#include "diff.h"
@@ -695,7 +697,9 @@ static int read_tree_trivial(struct object_id *common, struct object_id *head,
static void write_tree_trivial(struct object_id *oid)
{
- if (write_index_as_tree(oid, the_repository->index, get_index_file(), 0, NULL))
+ if (write_index_as_tree(oid, the_repository->index,
+ repo_get_index_file(the_repository),
+ 0, NULL))
die(_("git write-tree failed to write a tree"));
}
@@ -757,7 +761,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
}
if (write_locked_index(the_repository->index, &lock,
COMMIT_LOCK | SKIP_IF_UNCHANGED))
- die(_("unable to write %s"), get_index_file());
+ die(_("unable to write %s"), repo_get_index_file(the_repository));
return clean ? 0 : 1;
} else {
return try_merge_command(the_repository,
@@ -839,7 +843,7 @@ static void write_merge_heads(struct commit_list *);
static void prepare_to_commit(struct commit_list *remoteheads)
{
struct strbuf msg = STRBUF_INIT;
- const char *index_file = get_index_file();
+ const char *index_file = repo_get_index_file(the_repository);
if (!no_verify) {
int invoked_hook;
@@ -855,7 +859,8 @@ static void prepare_to_commit(struct commit_list *remoteheads)
if (invoked_hook)
discard_index(the_repository->index);
}
- read_index_from(the_repository->index, index_file, get_git_dir());
+ read_index_from(the_repository->index, index_file,
+ repo_get_git_dir(the_repository));
strbuf_addbuf(&msg, &merge_msg);
if (squash)
BUG("the control must not reach here under --squash");
@@ -878,8 +883,8 @@ static void prepare_to_commit(struct commit_list *remoteheads)
append_signoff(&msg, ignored_log_message_bytes(msg.buf, msg.len), 0);
write_merge_heads(remoteheads);
write_file_buf(git_path_merge_msg(the_repository), msg.buf, msg.len);
- if (run_commit_hook(0 < option_edit, get_index_file(), NULL,
- "prepare-commit-msg",
+ if (run_commit_hook(0 < option_edit, repo_get_index_file(the_repository),
+ NULL, "prepare-commit-msg",
git_path_merge_msg(the_repository), "merge", NULL))
abort_commit(remoteheads, NULL);
if (0 < option_edit) {
@@ -887,7 +892,7 @@ static void prepare_to_commit(struct commit_list *remoteheads)
abort_commit(remoteheads, NULL);
}
- if (!no_verify && run_commit_hook(0 < option_edit, get_index_file(),
+ if (!no_verify && run_commit_hook(0 < option_edit, repo_get_index_file(the_repository),
NULL, "commit-msg",
git_path_merge_msg(the_repository), NULL))
abort_commit(remoteheads, NULL);
@@ -1275,7 +1280,10 @@ static int merging_a_throwaway_tag(struct commit *commit)
return is_throwaway_tag;
}
-int cmd_merge(int argc, const char **argv, const char *prefix)
+int cmd_merge(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct object_id result_tree, stash, head_oid;
struct commit *head_commit;
@@ -1347,7 +1355,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
REF_NO_DEREF);
/* Invoke 'git reset --merge' */
- ret = cmd_reset(nargc, nargv, prefix);
+ ret = cmd_reset(nargc, nargv, prefix, the_repository);
if (!is_null_oid(&stash_oid)) {
oid_to_hex_r(stash_oid_hex, &stash_oid);
@@ -1379,7 +1387,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
die(_("There is no merge in progress (MERGE_HEAD missing)."));
/* Invoke 'git commit' */
- ret = cmd_commit(nargc, nargv, prefix);
+ ret = cmd_commit(nargc, nargv, prefix, the_repository);
goto done;
}
diff --git a/builtin/mktag.c b/builtin/mktag.c
index c6b644219f..6e188dce50 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "gettext.h"
#include "hex.h"
@@ -71,7 +72,10 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
return ret;
}
-int cmd_mktag(int argc, const char **argv, const char *prefix)
+int cmd_mktag(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
static struct option builtin_mktag_options[] = {
OPT_BOOL(0, "strict", &option_strict,
diff --git a/builtin/mktree.c b/builtin/mktree.c
index 9a22d4e277..3c16faa40e 100644
--- a/builtin/mktree.c
+++ b/builtin/mktree.c
@@ -3,6 +3,7 @@
*
* Copyright (c) Junio C Hamano, 2006, 2009
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "gettext.h"
#include "hex.h"
@@ -150,7 +151,10 @@ static void mktree_line(char *buf, int nul_term_line, int allow_missing)
free(to_free);
}
-int cmd_mktree(int ac, const char **av, const char *prefix)
+int cmd_mktree(int ac,
+ const char **av,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct strbuf sb = STRBUF_INIT;
struct object_id oid;
@@ -199,5 +203,6 @@ int cmd_mktree(int ac, const char **av, const char *prefix)
used=0; /* reset tree entry buffer for re-use in batch mode */
}
strbuf_release(&sb);
+
return 0;
}
diff --git a/builtin/multi-pack-index.c b/builtin/multi-pack-index.c
index 8805cbbeb3..d159ed1314 100644
--- a/builtin/multi-pack-index.c
+++ b/builtin/multi-pack-index.c
@@ -1,7 +1,7 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "config.h"
-#include "environment.h"
#include "gettext.h"
#include "parse-options.h"
#include "midx.h"
@@ -9,6 +9,7 @@
#include "trace2.h"
#include "object-store-ll.h"
#include "replace-object.h"
+#include "repository.h"
#define BUILTIN_MIDX_WRITE_USAGE \
N_("git multi-pack-index [<options>] write [--preferred-pack=<pack>]" \
@@ -63,7 +64,7 @@ static int parse_object_dir(const struct option *opt, const char *arg,
char **value = opt->value;
free(*value);
if (unset)
- *value = xstrdup(get_object_directory());
+ *value = xstrdup(repo_get_object_directory(the_repository));
else
*value = real_pathdup(arg, 1);
return 0;
@@ -267,8 +268,10 @@ static int cmd_multi_pack_index_repack(int argc, const char **argv,
(size_t)opts.batch_size, opts.flags);
}
-int cmd_multi_pack_index(int argc, const char **argv,
- const char *prefix)
+int cmd_multi_pack_index(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int res;
parse_opt_subcommand_fn *fn = NULL;
diff --git a/builtin/mv.c b/builtin/mv.c
index 6c69033c5f..472a278737 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2006 Johannes Schindelin
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
@@ -18,7 +19,7 @@
#include "string-list.h"
#include "parse-options.h"
#include "read-cache-ll.h"
-#include "repository.h"
+
#include "setup.h"
#include "strvec.h"
#include "submodule.h"
@@ -178,7 +179,10 @@ static void remove_empty_src_dirs(const char **src_dir, size_t src_dir_nr)
strbuf_release(&a_src_dir);
}
-int cmd_mv(int argc, const char **argv, const char *prefix)
+int cmd_mv(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int i, flags, gitmodules_modified = 0;
int verbose = 0, show_only = 0, force = 0, ignore_errors = 0, ignore_sparse = 0;
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index a468ef84c3..765eb20a93 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -1,8 +1,8 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
-#include "repository.h"
#include "config.h"
#include "commit.h"
#include "tag.h"
@@ -65,7 +65,7 @@ static void set_commit_cutoff(struct commit *commit)
static void adjust_cutoff_timestamp_for_slop(void)
{
if (cutoff) {
- /* check for undeflow */
+ /* check for underflow */
if (cutoff > TIME_MIN + CUTOFF_DATE_SLOP)
cutoff = cutoff - CUTOFF_DATE_SLOP;
else
@@ -558,7 +558,10 @@ static void name_rev_line(char *p, struct name_ref_data *data)
strbuf_release(&buf);
}
-int cmd_name_rev(int argc, const char **argv, const char *prefix)
+int cmd_name_rev(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct mem_pool string_pool;
struct object_array revs = OBJECT_ARRAY_INIT;
diff --git a/builtin/notes.c b/builtin/notes.c
index 04f9dfb7fb..8c26e45526 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -6,7 +6,7 @@
* Based on git-notes.sh by Johannes Schindelin,
* and builtin/tag.c by Kristian Høgsberg and Carlos Rica.
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "editor.h"
@@ -17,7 +17,7 @@
#include "object-name.h"
#include "object-store-ll.h"
#include "path.h"
-#include "repository.h"
+
#include "pretty.h"
#include "refs.h"
#include "exec-cmd.h"
@@ -897,6 +897,7 @@ static int merge(int argc, const char **argv, const char *prefix)
1, PARSE_OPT_NONEG),
OPT_END()
};
+ char *notes_ref;
argc = parse_options(argc, argv, prefix, options,
git_notes_merge_usage, 0);
@@ -924,7 +925,8 @@ static int merge(int argc, const char **argv, const char *prefix)
if (do_commit)
return merge_commit(&o);
- o.local_ref = default_notes_ref();
+ notes_ref = default_notes_ref(the_repository);
+ o.local_ref = notes_ref;
strbuf_addstr(&remote_ref, argv[0]);
expand_loose_notes_ref(&remote_ref);
o.remote_ref = remote_ref.buf;
@@ -953,7 +955,7 @@ static int merge(int argc, const char **argv, const char *prefix)
}
strbuf_addf(&msg, "notes: Merged notes from %s into %s",
- remote_ref.buf, default_notes_ref());
+ remote_ref.buf, notes_ref);
strbuf_add(&(o.commit_msg), msg.buf + 7, msg.len - 7); /* skip "notes: " */
result = notes_merge(&o, t, &result_oid);
@@ -961,7 +963,7 @@ static int merge(int argc, const char **argv, const char *prefix)
if (result >= 0) /* Merge resulted (trivially) in result_oid */
/* Update default notes ref with new commit */
refs_update_ref(get_main_ref_store(the_repository), msg.buf,
- default_notes_ref(), &result_oid, NULL, 0,
+ notes_ref, &result_oid, NULL, 0,
UPDATE_REFS_DIE_ON_ERR);
else { /* Merge has unresolved conflicts */
struct worktree **worktrees;
@@ -973,14 +975,14 @@ static int merge(int argc, const char **argv, const char *prefix)
/* Store ref-to-be-updated into .git/NOTES_MERGE_REF */
worktrees = get_worktrees();
wt = find_shared_symref(worktrees, "NOTES_MERGE_REF",
- default_notes_ref());
+ notes_ref);
if (wt)
die(_("a notes merge into %s is already in-progress at %s"),
- default_notes_ref(), wt->path);
+ notes_ref, wt->path);
free_worktrees(worktrees);
- if (refs_update_symref(get_main_ref_store(the_repository), "NOTES_MERGE_REF", default_notes_ref(), NULL))
+ if (refs_update_symref(get_main_ref_store(the_repository), "NOTES_MERGE_REF", notes_ref, NULL))
die(_("failed to store link to current notes ref (%s)"),
- default_notes_ref());
+ notes_ref);
fprintf(stderr, _("Automatic notes merge failed. Fix conflicts in %s "
"and commit the result with 'git notes merge --commit', "
"or abort the merge with 'git notes merge --abort'.\n"),
@@ -988,6 +990,7 @@ static int merge(int argc, const char **argv, const char *prefix)
}
free_notes(t);
+ free(notes_ref);
strbuf_release(&remote_ref);
strbuf_release(&msg);
return result < 0; /* return non-zero on conflicts */
@@ -1084,6 +1087,7 @@ static int prune(int argc, const char **argv, const char *prefix)
static int get_ref(int argc, const char **argv, const char *prefix)
{
struct option options[] = { OPT_END() };
+ char *notes_ref;
argc = parse_options(argc, argv, prefix, options,
git_notes_get_ref_usage, 0);
@@ -1092,11 +1096,16 @@ static int get_ref(int argc, const char **argv, const char *prefix)
usage_with_options(git_notes_get_ref_usage, options);
}
- puts(default_notes_ref());
+ notes_ref = default_notes_ref(the_repository);
+ puts(notes_ref);
+ free(notes_ref);
return 0;
}
-int cmd_notes(int argc, const char **argv, const char *prefix)
+int cmd_notes(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
const char *override_notes_ref = NULL;
parse_opt_subcommand_fn *fn = NULL;
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 01479a9ccc..0fc0680b40 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -1,8 +1,8 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
-#include "repository.h"
#include "config.h"
#include "attr.h"
#include "object.h"
@@ -3968,7 +3968,7 @@ static int add_loose_object(const struct object_id *oid, const char *path,
*/
static void add_unreachable_loose_objects(void)
{
- for_each_loose_file_in_objdir(get_object_directory(),
+ for_each_loose_file_in_objdir(repo_get_object_directory(the_repository),
add_loose_object,
NULL, NULL, NULL);
}
@@ -4312,7 +4312,10 @@ static int option_parse_cruft_expiration(const struct option *opt UNUSED,
return 0;
}
-int cmd_pack_objects(int argc, const char **argv, const char *prefix)
+int cmd_pack_objects(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int use_internal_rev_list = 0;
int shallow = 0;
diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c
index dd9bf35f5b..81f4494d46 100644
--- a/builtin/pack-redundant.c
+++ b/builtin/pack-redundant.c
@@ -5,11 +5,12 @@
* This file is licensed under the GPL v2.
*
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "gettext.h"
#include "hex.h"
-#include "repository.h"
+
#include "packfile.h"
#include "object-store-ll.h"
@@ -561,11 +562,8 @@ static void load_all(void)
}
}
-int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED)
-{
- int i;
- int i_still_use_this = 0;
- struct pack_list *min = NULL, *red, *pl;
+int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, struct repository *repo UNUSED) {
+ int i; int i_still_use_this = 0; struct pack_list *min = NULL, *red, *pl;
struct llist *ignore;
struct object_id *oid;
char buf[GIT_MAX_HEXSZ + 2]; /* hex hash + \n + \0 */
diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c
index db40825666..2d83c1ed2a 100644
--- a/builtin/pack-refs.c
+++ b/builtin/pack-refs.c
@@ -1,9 +1,9 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
#include "parse-options.h"
#include "refs.h"
-#include "repository.h"
#include "revision.h"
static char const * const pack_refs_usage[] = {
@@ -11,7 +11,10 @@ static char const * const pack_refs_usage[] = {
NULL
};
-int cmd_pack_refs(int argc, const char **argv, const char *prefix)
+int cmd_pack_refs(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct ref_exclusions excludes = REF_EXCLUSIONS_INIT;
struct string_list included_refs = STRING_LIST_INIT_NODUP;
diff --git a/builtin/patch-id.c b/builtin/patch-id.c
index 35c1179f7e..93b398e391 100644
--- a/builtin/patch-id.c
+++ b/builtin/patch-id.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "diff.h"
@@ -7,9 +8,10 @@
#include "parse-options.h"
#include "setup.h"
-static void flush_current_id(struct object_id *id, struct object_id *result)
+static void flush_current_id(int patchlen, struct object_id *id, struct object_id *result)
{
- printf("%s %s\n", oid_to_hex(result), oid_to_hex(id));
+ if (patchlen)
+ printf("%s %s\n", oid_to_hex(result), oid_to_hex(id));
}
static int remove_space(char *line)
@@ -59,27 +61,9 @@ static int scan_hunk_header(const char *p, int *p_before, int *p_after)
return 1;
}
-/*
- * flag bits to control get_one_patchid()'s behaviour.
- *
- * STABLE/VERBATIM are given from the command line option as
- * --stable/--verbatim. FIND_HEADER conveys the internal state
- * maintained by the caller to allow the function to avoid mistaking
- * lines of log message before seeing the "diff" part as the beginning
- * of the next patch.
- */
-enum {
- GOPID_STABLE = (1<<0), /* --stable */
- GOPID_VERBATIM = (1<<1), /* --verbatim */
- GOPID_FIND_HEADER = (1<<2), /* stop at the beginning of patch message */
-};
-
static int get_one_patchid(struct object_id *next_oid, struct object_id *result,
- struct strbuf *line_buf, unsigned flags)
+ struct strbuf *line_buf, int stable, int verbatim)
{
- int stable = flags & GOPID_STABLE;
- int verbatim = flags & GOPID_VERBATIM;
- int find_header = flags & GOPID_FIND_HEADER;
int patchlen = 0, found_next = 0;
int before = -1, after = -1;
int diff_is_binary = 0;
@@ -94,40 +78,24 @@ static int get_one_patchid(struct object_id *next_oid, struct object_id *result,
const char *p = line;
int len;
- /*
- * The caller hasn't seen us find a patch header and
- * return to it, or we have started processing patch
- * and may encounter the beginning of the next patch.
- */
- if (find_header) {
- /*
- * If we see a line that begins with "<object name>",
- * "commit <object name>" or "From <object name>", it is
- * the beginning of a patch. Return to the caller, as
- * we are done with the one we have been processing.
- */
- if (skip_prefix(line, "commit ", &p))
- ;
- else if (skip_prefix(line, "From ", &p))
- ;
- if (!get_oid_hex(p, next_oid)) {
- if (verbatim)
- the_hash_algo->update_fn(&ctx, line, strlen(line));
- found_next = 1;
- break;
- }
+ /* Possibly skip over the prefix added by "log" or "format-patch" */
+ if (!skip_prefix(line, "commit ", &p) &&
+ !skip_prefix(line, "From ", &p) &&
+ starts_with(line, "\\ ") && 12 < strlen(line)) {
+ if (verbatim)
+ the_hash_algo->update_fn(&ctx, line, strlen(line));
+ continue;
+ }
+
+ if (!get_oid_hex(p, next_oid)) {
+ found_next = 1;
+ break;
}
/* Ignore commit comments */
if (!patchlen && !starts_with(line, "diff "))
continue;
- /*
- * We are past the commit log message. Prepare to
- * stop at the beginning of the next patch header.
- */
- find_header = 1;
-
/* Parsing diff header? */
if (before == -1) {
if (starts_with(line, "GIT binary patch") ||
@@ -160,16 +128,6 @@ static int get_one_patchid(struct object_id *next_oid, struct object_id *result,
break;
}
- /*
- * A hunk about an incomplete line may have this
- * marker at the end, which should just be ignored.
- */
- if (starts_with(line, "\\ ") && 12 < strlen(line)) {
- if (verbatim)
- the_hash_algo->update_fn(&ctx, line, strlen(line));
- continue;
- }
-
if (diff_is_binary) {
if (starts_with(line, "diff ")) {
diff_is_binary = 0;
@@ -216,20 +174,17 @@ static int get_one_patchid(struct object_id *next_oid, struct object_id *result,
return patchlen;
}
-static void generate_id_list(unsigned flags)
+static void generate_id_list(int stable, int verbatim)
{
struct object_id oid, n, result;
int patchlen;
struct strbuf line_buf = STRBUF_INIT;
oidclr(&oid, the_repository->hash_algo);
- flags |= GOPID_FIND_HEADER;
while (!feof(stdin)) {
- patchlen = get_one_patchid(&n, &result, &line_buf, flags);
- if (patchlen)
- flush_current_id(&oid, &result);
+ patchlen = get_one_patchid(&n, &result, &line_buf, stable, verbatim);
+ flush_current_id(patchlen, &oid, &result);
oidcpy(&oid, &n);
- flags &= ~GOPID_FIND_HEADER;
}
strbuf_release(&line_buf);
}
@@ -260,12 +215,14 @@ static int git_patch_id_config(const char *var, const char *value,
return git_default_config(var, value, ctx, cb);
}
-int cmd_patch_id(int argc, const char **argv, const char *prefix)
+int cmd_patch_id(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
/* if nothing is set, default to unstable */
struct patch_id_opts config = {0, 0};
int opts = 0;
- unsigned flags = 0;
struct option builtin_patch_id_options[] = {
OPT_CMDMODE(0, "unstable", &opts,
N_("use the unstable patch-id algorithm"), 1),
@@ -297,11 +254,7 @@ int cmd_patch_id(int argc, const char **argv, const char *prefix)
if (!the_hash_algo)
repo_set_hash_algo(the_repository, GIT_HASH_SHA1);
- if (opts ? opts > 1 : config.stable)
- flags |= GOPID_STABLE;
- if (opts ? opts == 3 : config.verbatim)
- flags |= GOPID_VERBATIM;
- generate_id_list(flags);
-
+ generate_id_list(opts ? opts > 1 : config.stable,
+ opts ? opts == 3 : config.verbatim);
return 0;
}
diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
index ca3578e158..4d63f26b0a 100644
--- a/builtin/prune-packed.c
+++ b/builtin/prune-packed.c
@@ -8,7 +8,10 @@ static const char * const prune_packed_usage[] = {
NULL
};
-int cmd_prune_packed(int argc, const char **argv, const char *prefix)
+int cmd_prune_packed(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int opts = isatty(2) ? PRUNE_PACKED_VERBOSE : 0;
const struct option prune_packed_options[] = {
diff --git a/builtin/prune.c b/builtin/prune.c
index 57fe31467f..2b1de01339 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "commit.h"
#include "diff.h"
@@ -147,7 +148,10 @@ static void remove_temporary_files(const char *path)
closedir(dir);
}
-int cmd_prune(int argc, const char **argv, const char *prefix)
+int cmd_prune(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct rev_info revs;
int exclude_promisor_objects = 0;
@@ -193,12 +197,12 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
revs.exclude_promisor_objects = 1;
}
- for_each_loose_file_in_objdir(get_object_directory(), prune_object,
- prune_cruft, prune_subdir, &revs);
+ for_each_loose_file_in_objdir(repo_get_object_directory(the_repository),
+ prune_object, prune_cruft, prune_subdir, &revs);
prune_packed_objects(show_only ? PRUNE_PACKED_DRY_RUN : 0);
- remove_temporary_files(get_object_directory());
- s = mkpathdup("%s/pack", get_object_directory());
+ remove_temporary_files(repo_get_object_directory(the_repository));
+ s = mkpathdup("%s/pack", repo_get_object_directory(the_repository));
remove_temporary_files(s);
free(s);
diff --git a/builtin/pull.c b/builtin/pull.c
index 5d9d9e467e..388ef3d130 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -6,6 +6,7 @@
* Fetch one or more remote refs and merge it/them into the current HEAD.
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "advice.h"
#include "config.h"
@@ -977,7 +978,10 @@ static void show_advice_pull_non_ff(void)
"invocation.\n"));
}
-int cmd_pull(int argc, const char **argv, const char *prefix)
+int cmd_pull(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repository UNUSED)
{
const char *repo, **refspecs;
struct oid_array merge_heads = OID_ARRAY_INIT;
diff --git a/builtin/push.c b/builtin/push.c
index 0b123eb9c1..e6f48969b8 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -1,6 +1,7 @@
/*
* "git push"
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "advice.h"
#include "branch.h"
@@ -13,7 +14,6 @@
#include "transport.h"
#include "parse-options.h"
#include "pkt-line.h"
-#include "repository.h"
#include "submodule.h"
#include "submodule-config.h"
#include "send-pack.h"
@@ -548,7 +548,10 @@ static int git_push_config(const char *k, const char *v,
return git_default_config(k, v, ctx, NULL);
}
-int cmd_push(int argc, const char **argv, const char *prefix)
+int cmd_push(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repository UNUSED)
{
int flags = 0;
int tags = 0;
diff --git a/builtin/range-diff.c b/builtin/range-diff.c
index f02cbac087..1b33ab66a7 100644
--- a/builtin/range-diff.c
+++ b/builtin/range-diff.c
@@ -1,10 +1,11 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "gettext.h"
#include "object-name.h"
#include "parse-options.h"
#include "range-diff.h"
#include "config.h"
-#include "repository.h"
+
static const char * const builtin_range_diff_usage[] = {
N_("git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>"),
@@ -13,7 +14,10 @@ N_("git range-diff [<options>] <base> <old-tip> <new-tip>"),
NULL
};
-int cmd_range_diff(int argc, const char **argv, const char *prefix)
+int cmd_range_diff(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct diff_options diffopt = { NULL };
struct strvec other_arg = STRVEC_INIT;
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index a8cf8504b8..d2a807a828 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -3,7 +3,7 @@
*
* Copyright (C) Linus Torvalds, 2005
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -16,7 +16,6 @@
#include "cache-tree.h"
#include "unpack-trees.h"
#include "parse-options.h"
-#include "repository.h"
#include "resolve-undo.h"
#include "setup.h"
#include "sparse-index.h"
@@ -108,7 +107,10 @@ static int git_read_tree_config(const char *var, const char *value,
return git_default_config(var, value, ctx, cb);
}
-int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
+int cmd_read_tree(int argc,
+ const char **argv,
+ const char *cmd_prefix,
+ struct repository *repo UNUSED)
{
int i, stage = 0;
struct object_id oid;
diff --git a/builtin/rebase.c b/builtin/rebase.c
index a2c96c080e..bbaca3c5d5 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -3,8 +3,9 @@
*
* Copyright (c) 2018 Pratik Karki
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
+
#include "abspath.h"
#include "environment.h"
#include "gettext.h"
@@ -527,6 +528,23 @@ static int rebase_write_basic_state(struct rebase_options *opts)
return 0;
}
+static int cleanup_autostash(struct rebase_options *opts)
+{
+ int ret;
+ struct strbuf dir = STRBUF_INIT;
+ const char *path = state_dir_path("autostash", opts);
+
+ if (!file_exists(path))
+ return 0;
+ ret = apply_autostash(path);
+ strbuf_addstr(&dir, opts->state_dir);
+ if (remove_dir_recursively(&dir, 0))
+ ret = error_errno(_("could not remove '%s'"), opts->state_dir);
+ strbuf_release(&dir);
+
+ return ret;
+}
+
static int finish_rebase(struct rebase_options *opts)
{
struct strbuf dir = STRBUF_INIT;
@@ -1063,7 +1081,10 @@ static int check_exec_cmd(const char *cmd)
return 0;
}
-int cmd_rebase(int argc, const char **argv, const char *prefix)
+int cmd_rebase(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct rebase_options options = REBASE_OPTIONS_INIT;
const char *branch_name;
@@ -1727,7 +1748,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if (require_clean_work_tree(the_repository, "rebase",
_("Please commit or stash them."), 1, 1)) {
ret = -1;
- goto cleanup;
+ goto cleanup_autostash;
}
/*
@@ -1750,7 +1771,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if (options.switch_to) {
ret = checkout_up_to_date(&options);
if (ret)
- goto cleanup;
+ goto cleanup_autostash;
}
if (!(options.flags & REBASE_NO_QUIET))
@@ -1776,8 +1797,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
/* If a hook exists, give it a chance to interrupt*/
if (!ok_to_skip_pre_rebase &&
run_hooks_l(the_repository, "pre-rebase", options.upstream_arg,
- argc ? argv[0] : NULL, NULL))
- die(_("The pre-rebase hook refused to rebase."));
+ argc ? argv[0] : NULL, NULL)) {
+ ret = error(_("The pre-rebase hook refused to rebase."));
+ goto cleanup_autostash;
+ }
if (options.flags & REBASE_DIFFSTAT) {
struct diff_options opts;
@@ -1822,9 +1845,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
ropts.head_msg = msg.buf;
ropts.default_reflog_action = options.reflog_action;
- if (reset_head(the_repository, &ropts))
- die(_("Could not detach HEAD"));
- strbuf_release(&msg);
+ if (reset_head(the_repository, &ropts)) {
+ ret = error(_("Could not detach HEAD"));
+ goto cleanup_autostash;
+ }
/*
* If the onto is a proper descendant of the tip of the branch, then
@@ -1852,9 +1876,14 @@ run_rebase:
cleanup:
strbuf_release(&buf);
+ strbuf_release(&msg);
strbuf_release(&revisions);
rebase_options_release(&options);
free(squash_onto_name);
free(keep_base_onto_name);
return !!ret;
+
+cleanup_autostash:
+ ret |= !!cleanup_autostash(&options);
+ goto cleanup;
}
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 3f35140e48..536d22761d 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -1,6 +1,7 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
-#include "repository.h"
+
#include "config.h"
#include "environment.h"
#include "gettext.h"
@@ -339,12 +340,26 @@ static void show_one_alternate_ref(const struct object_id *oid,
static void write_head_info(void)
{
static struct oidset seen = OIDSET_INIT;
+ struct strvec excludes_vector = STRVEC_INIT;
+ const char **exclude_patterns;
+
+ /*
+ * We need access to the reference names both with and without their
+ * namespace and thus cannot use `refs_for_each_namespaced_ref()`. We
+ * thus have to adapt exclude patterns to carry the namespace prefix
+ * ourselves.
+ */
+ exclude_patterns = get_namespaced_exclude_patterns(
+ hidden_refs_to_excludes(&hidden_refs),
+ get_git_namespace(), &excludes_vector);
refs_for_each_fullref_in(get_main_ref_store(the_repository), "",
- hidden_refs_to_excludes(&hidden_refs),
- show_ref_cb, &seen);
+ exclude_patterns, show_ref_cb, &seen);
for_each_alternate_ref(show_one_alternate_ref, &seen);
+
oidset_clear(&seen);
+ strvec_clear(&excludes_vector);
+
if (!sent_capabilities)
show_ref("capabilities^{}", null_oid());
@@ -1324,7 +1339,7 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
}
/*
- * NEEDSWORK: we should consolidate various implementions of "are we
+ * NEEDSWORK: we should consolidate various implementations of "are we
* on an unborn branch?" test into one, and make the unified one more
* robust. !get_sha1() based check used here and elsewhere would not
* allow us to tell an unborn branch from corrupt ref, for example.
@@ -2480,7 +2495,10 @@ static int delete_only(struct command *commands)
return 1;
}
-int cmd_receive_pack(int argc, const char **argv, const char *prefix)
+int cmd_receive_pack(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int advertise_refs = 0;
struct command *commands;
diff --git a/builtin/reflog.c b/builtin/reflog.c
index 0d2ff95c6e..22df6834f7 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -1,7 +1,7 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
-#include "repository.h"
#include "revision.h"
#include "reachable.h"
#include "wildmatch.h"
@@ -244,7 +244,7 @@ static int cmd_reflog_show(int argc, const char **argv, const char *prefix)
PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0 |
PARSE_OPT_KEEP_UNKNOWN_OPT);
- return cmd_log_reflog(argc, argv, prefix);
+ return cmd_log_reflog(argc, argv, prefix, the_repository);
}
static int show_reflog(const char *refname, void *cb_data UNUSED)
@@ -447,7 +447,10 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)
* main "reflog"
*/
-int cmd_reflog(int argc, const char **argv, const char *prefix)
+int cmd_reflog(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repository)
{
parse_opt_subcommand_fn *fn = NULL;
struct option options[] = {
@@ -466,5 +469,5 @@ int cmd_reflog(int argc, const char **argv, const char *prefix)
if (fn)
return fn(argc - 1, argv + 1, prefix);
else
- return cmd_log_reflog(argc, argv, prefix);
+ return cmd_log_reflog(argc, argv, prefix, repository);
}
diff --git a/builtin/refs.c b/builtin/refs.c
index 131f98be98..24978a7b7b 100644
--- a/builtin/refs.c
+++ b/builtin/refs.c
@@ -1,9 +1,9 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "fsck.h"
#include "parse-options.h"
#include "refs.h"
-#include "repository.h"
#include "strbuf.h"
#define REFS_MIGRATE_USAGE \
@@ -90,7 +90,10 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix)
return ret;
}
-int cmd_refs(int argc, const char **argv, const char *prefix)
+int cmd_refs(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
const char * const refs_usage[] = {
REFS_MIGRATE_USAGE,
diff --git a/builtin/remote-ext.c b/builtin/remote-ext.c
index 282782eccd..33c8ae0fc7 100644
--- a/builtin/remote-ext.c
+++ b/builtin/remote-ext.c
@@ -195,7 +195,10 @@ static int command_loop(const char *child)
}
}
-int cmd_remote_ext(int argc, const char **argv, const char *prefix)
+int cmd_remote_ext(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
BUG_ON_NON_EMPTY_PREFIX(prefix);
diff --git a/builtin/remote-fd.c b/builtin/remote-fd.c
index 9020fab9c5..ae896eda57 100644
--- a/builtin/remote-fd.c
+++ b/builtin/remote-fd.c
@@ -53,7 +53,10 @@ static void command_loop(int input_fd, int output_fd)
}
}
-int cmd_remote_fd(int argc, const char **argv, const char *prefix)
+int cmd_remote_fd(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int input_fd = -1;
int output_fd = -1;
diff --git a/builtin/remote.c b/builtin/remote.c
index 0acc547d69..76670ddd8b 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -1761,7 +1762,10 @@ out:
return 0;
}
-int cmd_remote(int argc, const char **argv, const char *prefix)
+int cmd_remote(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
parse_opt_subcommand_fn *fn = NULL;
struct option options[] = {
diff --git a/builtin/repack.c b/builtin/repack.c
index c31d5653f1..d6bb37e84a 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "dir.h"
@@ -1153,7 +1154,10 @@ static const char *find_pack_prefix(const char *packdir, const char *packtmp)
return pack_prefix;
}
-int cmd_repack(int argc, const char **argv, const char *prefix)
+int cmd_repack(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct child_process cmd = CHILD_PROCESS_INIT;
struct string_list_item *item;
@@ -1286,7 +1290,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
if (write_midx && write_bitmaps) {
struct strbuf path = STRBUF_INIT;
- strbuf_addf(&path, "%s/%s_XXXXXX", get_object_directory(),
+ strbuf_addf(&path, "%s/%s_XXXXXX", repo_get_object_directory(the_repository),
"bitmap-ref-tips");
refs_snapshot = xmks_tempfile(path.buf);
@@ -1295,7 +1299,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
strbuf_release(&path);
}
- packdir = mkpathdup("%s/pack", get_object_directory());
+ packdir = mkpathdup("%s/pack", repo_get_object_directory(the_repository));
packtmp_name = xstrfmt(".tmp-%d-pack", (int)getpid());
packtmp = mkpathdup("%s/%s", packdir, packtmp_name);
@@ -1565,7 +1569,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
unsigned flags = 0;
if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL, 0))
flags |= MIDX_WRITE_INCREMENTAL;
- write_midx_file(get_object_directory(), NULL, NULL, flags);
+ write_midx_file(repo_get_object_directory(the_repository),
+ NULL, NULL, flags);
}
cleanup:
diff --git a/builtin/replace.c b/builtin/replace.c
index 34cc4672bc..a44f4e7ea9 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -7,11 +7,10 @@
* and Carlos Rica <jasampler@gmail.com> that was itself based on
* git-tag.sh and mktag.c by Linus Torvalds.
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "editor.h"
-#include "environment.h"
#include "gettext.h"
#include "hex.h"
#include "refs.h"
@@ -22,7 +21,6 @@
#include "object-name.h"
#include "object-store-ll.h"
#include "replace-object.h"
-#include "repository.h"
#include "tag.h"
#include "wildmatch.h"
@@ -514,7 +512,7 @@ static int create_graft(int argc, const char **argv, int force, int gentle)
static int convert_graft_file(int force)
{
- const char *graft_file = get_graft_file(the_repository);
+ const char *graft_file = repo_get_graft_file(the_repository);
FILE *fp = fopen_or_warn(graft_file, "r");
struct strbuf buf = STRBUF_INIT, err = STRBUF_INIT;
struct strvec args = STRVEC_INIT;
@@ -545,7 +543,10 @@ static int convert_graft_file(int force)
return -1;
}
-int cmd_replace(int argc, const char **argv, const char *prefix)
+int cmd_replace(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int force = 0;
int raw = 0;
diff --git a/builtin/replay.c b/builtin/replay.c
index 138198ce9c..2d12a4e403 100644
--- a/builtin/replay.c
+++ b/builtin/replay.c
@@ -4,6 +4,7 @@
#include "git-compat-util.h"
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "environment.h"
#include "hex.h"
@@ -274,7 +275,10 @@ static struct commit *pick_regular_commit(struct commit *pickme,
return create_commit(result->tree, pickme, replayed_base);
}
-int cmd_replay(int argc, const char **argv, const char *prefix)
+int cmd_replay(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
const char *advance_name_opt = NULL;
char *advance_name = NULL;
diff --git a/builtin/rerere.c b/builtin/rerere.c
index 81b65ffa39..f7143c3f5d 100644
--- a/builtin/rerere.c
+++ b/builtin/rerere.c
@@ -1,8 +1,9 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
#include "parse-options.h"
-#include "repository.h"
+
#include "string-list.h"
#include "rerere.h"
#include "xdiff/xdiff.h"
@@ -48,7 +49,10 @@ static int diff_two(const char *file1, const char *label1,
return ret;
}
-int cmd_rerere(int argc, const char **argv, const char *prefix)
+int cmd_rerere(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct string_list merge_rr = STRING_LIST_INIT_DUP;
int i, autoupdate = -1, flags = 0;
diff --git a/builtin/reset.c b/builtin/reset.c
index 5f941fb3a2..7154f88826 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -7,7 +7,7 @@
*
* Copyright (c) 2005, 2006 Linus Torvalds and Junio C Hamano
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "advice.h"
#include "config.h"
@@ -26,6 +26,7 @@
#include "object-name.h"
#include "parse-options.h"
#include "path.h"
+#include "repository.h"
#include "unpack-trees.h"
#include "cache-tree.h"
#include "setup.h"
@@ -330,7 +331,10 @@ static int git_reset_config(const char *var, const char *value,
return git_default_config(var, value, ctx, cb);
}
-int cmd_reset(int argc, const char **argv, const char *prefix)
+int cmd_reset(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int reset_type = NONE, update_ref_status = 0, quiet = 0;
int no_refresh = 0;
@@ -441,7 +445,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
else
trace2_cmd_mode(reset_type_names[reset_type]);
- if (reset_type != SOFT && (reset_type != MIXED || get_git_work_tree()))
+ if (reset_type != SOFT && (reset_type != MIXED || repo_get_work_tree(the_repository)))
setup_work_tree();
if (reset_type == MIXED && is_bare_repository())
@@ -474,7 +478,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
goto cleanup;
}
the_repository->index->updated_skipworktree = 1;
- if (!no_refresh && get_git_work_tree()) {
+ if (!no_refresh && repo_get_work_tree(the_repository)) {
uint64_t t_begin, t_delta_in_ms;
t_begin = getnanotime();
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 97d077a994..f62bcbf2b1 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "commit.h"
@@ -513,7 +514,10 @@ static int try_bitmap_disk_usage(struct rev_info *revs,
return 0;
}
-int cmd_rev_list(int argc, const char **argv, const char *prefix)
+int cmd_rev_list(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct rev_info revs;
struct rev_list_info info;
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 4285dc34a7..8401b4d7ab 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -3,8 +3,9 @@
*
* Copyright (C) Linus Torvalds, 2005
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
+
#include "abspath.h"
#include "config.h"
#include "commit.h"
@@ -19,6 +20,8 @@
#include "path.h"
#include "diff.h"
#include "read-cache-ll.h"
+#include "repo-settings.h"
+#include "repository.h"
#include "revision.h"
#include "setup.h"
#include "split-index.h"
@@ -688,7 +691,10 @@ static void print_path(const char *path, const char *prefix, enum format_type fo
free(cwd);
}
-int cmd_rev_parse(int argc, const char **argv, const char *prefix)
+int cmd_rev_parse(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0;
const struct git_hash_algo *output_algo = NULL;
@@ -898,7 +904,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
}
if (opt_with_value(arg, "--abbrev-ref", &arg)) {
abbrev_ref = 1;
- abbrev_ref_strict = warn_ambiguous_refs;
+ abbrev_ref_strict =
+ repo_settings_get_warn_ambiguous_refs(the_repository);
if (arg) {
if (!strcmp(arg, "strict"))
abbrev_ref_strict = 1;
@@ -966,7 +973,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
continue;
}
if (!strcmp(arg, "--show-toplevel")) {
- const char *work_tree = get_git_work_tree();
+ const char *work_tree = repo_get_work_tree(the_repository);
if (work_tree)
print_path(work_tree, prefix, format, DEFAULT_UNMODIFIED);
else
@@ -991,7 +998,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
const char *pfx = prefix;
if (!is_inside_work_tree()) {
const char *work_tree =
- get_git_work_tree();
+ repo_get_work_tree(the_repository);
if (work_tree)
printf("%s\n", work_tree);
continue;
@@ -1042,7 +1049,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
continue;
}
if (!strcmp(arg, "--git-common-dir")) {
- print_path(get_git_common_dir(), prefix, format, DEFAULT_RELATIVE_IF_SHARED);
+ print_path(repo_get_common_dir(the_repository), prefix, format, DEFAULT_RELATIVE_IF_SHARED);
continue;
}
if (!strcmp(arg, "--is-inside-git-dir")) {
diff --git a/builtin/revert.c b/builtin/revert.c
index 7bf2b4e11d..55ba1092c5 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -1,9 +1,9 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "git-compat-util.h"
#include "builtin.h"
#include "parse-options.h"
#include "diff.h"
#include "gettext.h"
-#include "repository.h"
#include "revision.h"
#include "rerere.h"
#include "sequencer.h"
@@ -261,7 +261,10 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
return sequencer_pick_revisions(the_repository, opts);
}
-int cmd_revert(int argc, const char **argv, const char *prefix)
+int cmd_revert(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct replay_opts opts = REPLAY_OPTS_INIT;
int res;
@@ -275,7 +278,10 @@ int cmd_revert(int argc, const char **argv, const char *prefix)
return res;
}
-int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
+int cmd_cherry_pick(int argc,
+const char **argv,
+const char *prefix,
+struct repository *repo UNUSED)
{
struct replay_opts opts = REPLAY_OPTS_INIT;
int res;
diff --git a/builtin/rm.c b/builtin/rm.c
index 0e79cbab62..eaff027258 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -3,7 +3,7 @@
*
* Copyright (C) Linus Torvalds 2006
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "advice.h"
#include "config.h"
@@ -15,7 +15,7 @@
#include "object-name.h"
#include "parse-options.h"
#include "read-cache.h"
-#include "repository.h"
+
#include "string-list.h"
#include "setup.h"
#include "sparse-index.h"
@@ -261,7 +261,10 @@ static struct option builtin_rm_options[] = {
OPT_END(),
};
-int cmd_rm(int argc, const char **argv, const char *prefix)
+int cmd_rm(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct lock_file lock_file = LOCK_INIT;
int i, ret = 0;
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index ef0df80824..81fc96d423 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "hex.h"
@@ -147,7 +148,10 @@ static int send_pack_config(const char *k, const char *v,
return git_default_config(k, v, ctx, cb);
}
-int cmd_send_pack(int argc, const char **argv, const char *prefix)
+int cmd_send_pack(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct refspec rs = REFSPEC_INIT_PUSH;
const char *remote_name = NULL;
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index b529608c92..3ed5c46078 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "commit.h"
@@ -5,7 +6,6 @@
#include "environment.h"
#include "gettext.h"
#include "string-list.h"
-#include "repository.h"
#include "revision.h"
#include "utf8.h"
#include "mailmap.h"
@@ -378,7 +378,10 @@ void shortlog_finish_setup(struct shortlog *log)
string_list_sort(&log->trailers);
}
-int cmd_shortlog(int argc, const char **argv, const char *prefix)
+int cmd_shortlog(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct shortlog log = { STRING_LIST_INIT_NODUP };
struct rev_info rev;
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 29237f653d..cd6bdf63bc 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "environment.h"
@@ -10,7 +11,7 @@
#include "strvec.h"
#include "object-name.h"
#include "parse-options.h"
-#include "repository.h"
+
#include "dir.h"
#include "commit-slab.h"
#include "date.h"
@@ -632,7 +633,10 @@ static int parse_reflog_param(const struct option *opt, const char *arg,
return 0;
}
-int cmd_show_branch(int ac, const char **av, const char *prefix)
+int cmd_show_branch(int ac,
+ const char **av,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct commit *rev[MAX_REVS], *commit;
char *reflog_msg[MAX_REVS] = {0};
diff --git a/builtin/show-index.c b/builtin/show-index.c
index 540dc3dad1..f164c01bbe 100644
--- a/builtin/show-index.c
+++ b/builtin/show-index.c
@@ -1,17 +1,20 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "gettext.h"
#include "hash.h"
#include "hex.h"
#include "pack.h"
#include "parse-options.h"
-#include "repository.h"
static const char *const show_index_usage[] = {
"git show-index [--object-format=<hash-algorithm>]",
NULL
};
-int cmd_show_index(int argc, const char **argv, const char *prefix)
+int cmd_show_index(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int i;
unsigned nr;
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index f5899ce9ff..285cd3e433 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -287,7 +288,10 @@ static int exclude_existing_callback(const struct option *opt, const char *arg,
return 0;
}
-int cmd_show_ref(int argc, const char **argv, const char *prefix)
+int cmd_show_ref(int argc,
+const char **argv,
+const char *prefix,
+struct repository *repo UNUSED)
{
struct exclude_existing_options exclude_existing_opts = {0};
struct patterns_options patterns_opts = {0};
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index 5ccf696862..49aedc1de8 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "dir.h"
@@ -7,7 +8,6 @@
#include "object-name.h"
#include "parse-options.h"
#include "pathspec.h"
-#include "repository.h"
#include "strbuf.h"
#include "string-list.h"
#include "lockfile.h"
@@ -924,6 +924,11 @@ static int sparse_checkout_disable(int argc, const char **argv,
builtin_sparse_checkout_disable_options,
builtin_sparse_checkout_disable_usage, 0);
+ /*
+ * Disable the advice message for expanding a sparse index, as we
+ * are expecting to do that when disabling sparse-checkout.
+ */
+ give_advice_on_expansion = 0;
repo_read_index(the_repository);
memset(&pl, 0, sizeof(pl));
@@ -1029,7 +1034,10 @@ static int sparse_checkout_check_rules(int argc, const char **argv, const char *
return ret;
}
-int cmd_sparse_checkout(int argc, const char **argv, const char *prefix)
+int cmd_sparse_checkout(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
parse_opt_subcommand_fn *fn = NULL;
struct option builtin_sparse_checkout_options[] = {
diff --git a/builtin/stash.c b/builtin/stash.c
index be842258d0..f1acc918d0 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "config.h"
@@ -19,6 +20,7 @@
#include "entry.h"
#include "preload-index.h"
#include "read-cache.h"
+#include "repository.h"
#include "rerere.h"
#include "revision.h"
#include "setup.h"
@@ -539,8 +541,8 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
NULL, NULL, NULL))
return error(_("could not write index"));
- if (write_index_as_tree(&c_tree, the_repository->index, get_index_file(), 0,
- NULL))
+ if (write_index_as_tree(&c_tree, the_repository->index,
+ repo_get_index_file(the_repository), 0, NULL))
return error(_("cannot apply a stash in the middle of a merge"));
if (index) {
@@ -565,7 +567,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
discard_index(the_repository->index);
repo_read_index(the_repository);
if (write_index_as_tree(&index_tree, the_repository->index,
- get_index_file(), 0, NULL))
+ repo_get_index_file(the_repository), 0, NULL))
return error(_("could not save index tree"));
reset_head();
@@ -640,9 +642,9 @@ restore_untracked:
cp.git_cmd = 1;
cp.dir = prefix;
strvec_pushf(&cp.env, GIT_WORK_TREE_ENVIRONMENT"=%s",
- absolute_path(get_git_work_tree()));
+ absolute_path(repo_get_work_tree(the_repository)));
strvec_pushf(&cp.env, GIT_DIR_ENVIRONMENT"=%s",
- absolute_path(get_git_dir()));
+ absolute_path(repo_get_git_dir(the_repository)));
strvec_push(&cp.args, "status");
run_command(&cp);
}
@@ -974,7 +976,7 @@ static int show_stash(int argc, const char **argv, const char *prefix)
}
log_tree_diff_flush(&rev);
- ret = diff_result_code(&rev.diffopt);
+ ret = diff_result_code(&rev);
cleanup:
strvec_clear(&revision_args);
@@ -1126,13 +1128,13 @@ static int check_changes_tracked_files(const struct pathspec *ps)
diff_setup_done(&rev.diffopt);
run_diff_index(&rev, DIFF_INDEX_CACHED);
- if (diff_result_code(&rev.diffopt)) {
+ if (diff_result_code(&rev)) {
ret = 1;
goto done;
}
run_diff_files(&rev, 0);
- if (diff_result_code(&rev.diffopt)) {
+ if (diff_result_code(&rev)) {
ret = 1;
goto done;
}
@@ -1405,8 +1407,8 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
strbuf_addf(&commit_tree_label, "index on %s\n", msg.buf);
commit_list_insert(head_commit, &parents);
- if (write_index_as_tree(&info->i_tree, the_repository->index, get_index_file(), 0,
- NULL) ||
+ if (write_index_as_tree(&info->i_tree, the_repository->index,
+ repo_get_index_file(the_repository), 0, NULL) ||
commit_tree(commit_tree_label.buf, commit_tree_label.len,
&info->i_tree, parents, &info->i_commit, NULL, NULL)) {
if (!quiet)
@@ -1871,7 +1873,10 @@ static int save_stash(int argc, const char **argv, const char *prefix)
return ret;
}
-int cmd_stash(int argc, const char **argv, const char *prefix)
+int cmd_stash(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
pid_t pid = getpid();
const char *index_file;
@@ -1904,7 +1909,7 @@ int cmd_stash(int argc, const char **argv, const char *prefix)
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
- index_file = get_index_file();
+ index_file = repo_get_index_file(the_repository);
strbuf_addf(&stash_index_path, "%s.stash.%" PRIuMAX, index_file,
(uintmax_t)pid);
diff --git a/builtin/stripspace.c b/builtin/stripspace.c
index e5626e5126..e147f3ff92 100644
--- a/builtin/stripspace.c
+++ b/builtin/stripspace.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "environment.h"
@@ -29,7 +30,10 @@ enum stripspace_mode {
COMMENT_LINES
};
-int cmd_stripspace(int argc, const char **argv, const char *prefix)
+int cmd_stripspace(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct strbuf buf = STRBUF_INIT;
enum stripspace_mode mode = STRIP_DEFAULT;
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index a9bd93a785..dc89488a7d 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1,9 +1,10 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
-#include "repository.h"
+
#include "config.h"
#include "parse-options.h"
#include "quote.h"
@@ -676,7 +677,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
setup_revisions(diff_files_args.nr, diff_files_args.v, &rev, &opt);
run_diff_files(&rev, 0);
- if (!diff_result_code(&rev.diffopt)) {
+ if (!diff_result_code(&rev)) {
print_status(flags, ' ', path, ce_oid,
displaypath);
} else if (!(flags & OPT_CACHED)) {
@@ -699,6 +700,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
if (flags & OPT_RECURSIVE) {
struct child_process cpr = CHILD_PROCESS_INIT;
+ int res;
cpr.git_cmd = 1;
cpr.dir = path;
@@ -714,7 +716,10 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
if (flags & OPT_QUIET)
strvec_push(&cpr.args, "--quiet");
- if (run_command(&cpr))
+ res = run_command(&cpr);
+ if (res == SIGPIPE + 128)
+ raise(SIGPIPE);
+ else if (res)
die(_("failed to recurse into submodule '%s'"), path);
}
@@ -1715,7 +1720,7 @@ static int clone_submodule(const struct module_clone_data *clone_data,
exit(128);
if (!is_absolute_path(clone_data->path))
- clone_data_path = to_free = xstrfmt("%s/%s", get_git_work_tree(),
+ clone_data_path = to_free = xstrfmt("%s/%s", repo_get_work_tree(the_repository),
clone_data->path);
if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
@@ -3542,7 +3547,10 @@ cleanup:
return ret;
}
-int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
+int cmd_submodule__helper(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
parse_opt_subcommand_fn *fn = NULL;
const char *const usage[] = {
diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c
index 81abdd170f..299d23d76a 100644
--- a/builtin/symbolic-ref.c
+++ b/builtin/symbolic-ref.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -41,7 +42,10 @@ static int check_symref(const char *HEAD, int quiet, int shorten, int recurse, i
return 0;
}
-int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
+int cmd_symbolic_ref(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int quiet = 0, delete = 0, shorten = 0, recurse = 1, ret = 0;
const char *msg = NULL;
diff --git a/builtin/tag.c b/builtin/tag.c
index ab3b500543..93d10d5915 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -5,7 +5,7 @@
* Carlos Rica <jasampler@gmail.com>
* Based on git-tag.sh and mktag.c by Linus Torvalds.
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "advice.h"
#include "config.h"
@@ -458,7 +458,10 @@ static int strbuf_check_tag_ref(struct strbuf *sb, const char *name)
return check_refname_format(sb->buf, 0);
}
-int cmd_tag(int argc, const char **argv, const char *prefix)
+int cmd_tag(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct strbuf buf = STRBUF_INIT;
struct strbuf ref = STRBUF_INIT;
@@ -703,6 +706,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
cleanup:
ref_sorting_release(sorting);
ref_filter_clear(&filter);
+ ref_format_clear(&format);
strbuf_release(&buf);
strbuf_release(&ref);
strbuf_release(&reflog_msg);
diff --git a/builtin/unpack-file.c b/builtin/unpack-file.c
index c129e2bb6c..6da2825753 100644
--- a/builtin/unpack-file.c
+++ b/builtin/unpack-file.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "hex.h"
@@ -25,7 +26,10 @@ static char *create_temp_file(struct object_id *oid)
return path;
}
-int cmd_unpack_file(int argc, const char **argv, const char *prefix UNUSED)
+int cmd_unpack_file(int argc,
+ const char **argv,
+ const char *prefix UNUSED,
+ struct repository *repo UNUSED)
{
struct object_id oid;
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 08fa2a7a74..02b8d02f63 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "bulk-checkin.h"
#include "config.h"
@@ -601,7 +602,10 @@ static void unpack_all(void)
die("unresolved deltas left after unpacking");
}
-int cmd_unpack_objects(int argc, const char **argv, const char *prefix UNUSED)
+int cmd_unpack_objects(int argc,
+ const char **argv,
+ const char *prefix UNUSED,
+ struct repository *repo UNUSED)
{
int i;
struct object_id oid;
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 35a1f957ad..45b4a8b555 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -3,7 +3,7 @@
*
* Copyright (C) Linus Torvalds, 2005
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "bulk-checkin.h"
#include "config.h"
@@ -22,7 +22,6 @@
#include "pathspec.h"
#include "dir.h"
#include "read-cache.h"
-#include "repository.h"
#include "setup.h"
#include "sparse-index.h"
#include "split-index.h"
@@ -917,7 +916,10 @@ static enum parse_opt_result reupdate_callback(
return 0;
}
-int cmd_update_index(int argc, const char **argv, const char *prefix)
+int cmd_update_index(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int newfd, entries, has_errors = 0, nul_term_line = 0;
enum uc_mode untracked_cache = UC_UNSPECIFIED;
@@ -1194,7 +1196,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
"remove or change it, if you really want to "
"enable the untracked cache"));
add_untracked_cache(the_repository->index);
- report(_("Untracked cache enabled for '%s'"), get_git_work_tree());
+ report(_("Untracked cache enabled for '%s'"), repo_get_work_tree(the_repository));
break;
default:
BUG("bad untracked_cache value: %d", untracked_cache);
@@ -1239,7 +1241,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
if (newfd < 0) {
if (refresh_args.flags & REFRESH_QUIET)
exit(128);
- unable_to_lock_die(get_index_file(), lock_error);
+ unable_to_lock_die(repo_get_index_file(the_repository), lock_error);
}
if (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))
die("Unable to write new index file");
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 8f31da9a4b..8a98615dc8 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -6,7 +7,6 @@
#include "object-name.h"
#include "parse-options.h"
#include "quote.h"
-#include "repository.h"
static const char * const git_update_ref_usage[] = {
N_("git update-ref [<options>] -d <refname> [<old-oid>]"),
@@ -713,7 +713,10 @@ static void update_refs_stdin(void)
strbuf_release(&input);
}
-int cmd_update_ref(int argc, const char **argv, const char *prefix)
+int cmd_update_ref(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
const char *refname, *oldval;
struct object_id oid, oldoid;
diff --git a/builtin/update-server-info.c b/builtin/update-server-info.c
index 1dc3971ede..6769611a02 100644
--- a/builtin/update-server-info.c
+++ b/builtin/update-server-info.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -9,7 +10,10 @@ static const char * const update_server_info_usage[] = {
NULL
};
-int cmd_update_server_info(int argc, const char **argv, const char *prefix)
+int cmd_update_server_info(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int force = 0;
struct option options[] = {
diff --git a/builtin/upload-archive.c b/builtin/upload-archive.c
index 313a8dfa81..9e9343f121 100644
--- a/builtin/upload-archive.c
+++ b/builtin/upload-archive.c
@@ -1,12 +1,12 @@
/*
* Copyright (c) 2006 Franck Bui-Huu
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "archive.h"
#include "path.h"
#include "pkt-line.h"
#include "sideband.h"
-#include "repository.h"
#include "run-command.h"
#include "strvec.h"
@@ -18,7 +18,10 @@ static const char deadchild[] =
#define MAX_ARGS (64)
-int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix)
+int cmd_upload_archive_writer(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
struct strvec sent_argv = STRVEC_INIT;
const char *arg_cmd = "argument ";
@@ -80,7 +83,10 @@ static ssize_t process_input(int child_fd, int band)
return sz;
}
-int cmd_upload_archive(int argc, const char **argv, const char *prefix)
+int cmd_upload_archive(int argc,
+const char **argv,
+const char *prefix,
+struct repository *repo UNUSED)
{
struct child_process writer = CHILD_PROCESS_INIT;
diff --git a/builtin/upload-pack.c b/builtin/upload-pack.c
index 46d93278d9..3b6c83fbce 100644
--- a/builtin/upload-pack.c
+++ b/builtin/upload-pack.c
@@ -17,7 +17,10 @@ static const char * const upload_pack_usage[] = {
NULL
};
-int cmd_upload_pack(int argc, const char **argv, const char *prefix)
+int cmd_upload_pack(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
const char *dir;
int strict = 0;
diff --git a/builtin/var.c b/builtin/var.c
index e30ff45be1..2ecaed51b4 100644
--- a/builtin/var.c
+++ b/builtin/var.c
@@ -3,7 +3,9 @@
*
* Copyright (C) Eric Biederman, 2005
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
+
#include "attr.h"
#include "config.h"
#include "editor.h"
@@ -210,7 +212,10 @@ static int show_config(const char *var, const char *value,
return git_default_config(var, value, ctx, cb);
}
-int cmd_var(int argc, const char **argv, const char *prefix UNUSED)
+int cmd_var(int argc,
+ const char **argv,
+ const char *prefix UNUSED,
+ struct repository *repo UNUSED)
{
const struct git_var *git_var;
char *val;
diff --git a/builtin/verify-commit.c b/builtin/verify-commit.c
index 0d2b9aea2a..779b7988ca 100644
--- a/builtin/verify-commit.c
+++ b/builtin/verify-commit.c
@@ -5,11 +5,11 @@
*
* Based on git-verify-tag
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
#include "object-name.h"
-#include "repository.h"
#include "commit.h"
#include "parse-options.h"
#include "gpg-interface.h"
@@ -51,7 +51,10 @@ static int verify_commit(const char *name, unsigned flags)
return run_gpg_verify((struct commit *)obj, flags);
}
-int cmd_verify_commit(int argc, const char **argv, const char *prefix)
+int cmd_verify_commit(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int i = 1, verbose = 0, had_error = 0;
unsigned flags = 0;
diff --git a/builtin/verify-pack.c b/builtin/verify-pack.c
index 011dddd2dc..34e4ed715f 100644
--- a/builtin/verify-pack.c
+++ b/builtin/verify-pack.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -61,7 +62,10 @@ static const char * const verify_pack_usage[] = {
NULL
};
-int cmd_verify_pack(int argc, const char **argv, const char *prefix)
+int cmd_verify_pack(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int err = 0;
unsigned int flags = 0;
diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c
index c731e2f87b..a7f20618ff 100644
--- a/builtin/verify-tag.c
+++ b/builtin/verify-tag.c
@@ -5,6 +5,7 @@
*
* Based on git-verify-tag.sh
*/
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -19,7 +20,10 @@ static const char * const verify_tag_usage[] = {
NULL
};
-int cmd_verify_tag(int argc, const char **argv, const char *prefix)
+int cmd_verify_tag(int argc,
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int i = 1, verbose = 0, had_error = 0;
unsigned flags = 0;
@@ -65,5 +69,6 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix)
if (format.format)
pretty_print_ref(name, &oid, &format);
}
+ ref_format_clear(&format);
return had_error;
}
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 41e7f6a327..fc31d072a6 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -1,3 +1,4 @@
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "advice.h"
@@ -17,7 +18,6 @@
#include "read-cache-ll.h"
#include "refs.h"
#include "remote.h"
-#include "repository.h"
#include "run-command.h"
#include "hook.h"
#include "sigchain.h"
@@ -219,7 +219,7 @@ static void prune_worktrees(void)
}
closedir(dir);
- strbuf_add_absolute_path(&main_path, get_git_common_dir());
+ strbuf_add_absolute_path(&main_path, repo_get_common_dir(the_repository));
/* massage main worktree absolute path to match 'gitdir' content */
strbuf_strip_suffix(&main_path, "/.");
string_list_append_nodup(&kept, strbuf_detach(&main_path, NULL));
@@ -492,7 +492,7 @@ static int add_worktree(const char *path, const char *refname,
strbuf_addf(&sb, "%s/gitdir", sb_repo.buf);
strbuf_realpath(&realpath, sb_git.buf, 1);
write_file(sb.buf, "%s", realpath.buf);
- strbuf_realpath(&realpath, get_git_common_dir(), 1);
+ strbuf_realpath(&realpath, repo_get_common_dir(the_repository), 1);
write_file(sb_git.buf, "gitdir: %s/worktrees/%s",
realpath.buf, name);
strbuf_reset(&sb);
@@ -1392,7 +1392,10 @@ static int repair(int ac, const char **av, const char *prefix)
return rc;
}
-int cmd_worktree(int ac, const char **av, const char *prefix)
+int cmd_worktree(int ac,
+ const char **av,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
parse_opt_subcommand_fn *fn = NULL;
struct option options[] = {
diff --git a/builtin/write-tree.c b/builtin/write-tree.c
index 8c75b4609b..43f233e69b 100644
--- a/builtin/write-tree.c
+++ b/builtin/write-tree.c
@@ -3,23 +3,24 @@
*
* Copyright (C) Linus Torvalds, 2005
*/
-
+#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
-#include "environment.h"
#include "gettext.h"
#include "hex.h"
#include "tree.h"
#include "cache-tree.h"
#include "parse-options.h"
-#include "repository.h"
static const char * const write_tree_usage[] = {
N_("git write-tree [--missing-ok] [--prefix=<prefix>/]"),
NULL
};
-int cmd_write_tree(int argc, const char **argv, const char *cmd_prefix)
+int cmd_write_tree(int argc,
+ const char **argv,
+ const char *cmd_prefix,
+ struct repository *repo UNUSED)
{
int flags = 0, ret;
const char *tree_prefix = NULL;
@@ -44,7 +45,8 @@ int cmd_write_tree(int argc, const char **argv, const char *cmd_prefix)
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
- ret = write_index_as_tree(&oid, the_repository->index, get_index_file(),
+ ret = write_index_as_tree(&oid, the_repository->index,
+ repo_get_index_file(the_repository),
flags, tree_prefix);
switch (ret) {
case 0:
diff --git a/bulk-checkin.c b/bulk-checkin.c
index 9089c214fa..2753d5bbe4 100644
--- a/bulk-checkin.c
+++ b/bulk-checkin.c
@@ -75,7 +75,7 @@ static void flush_bulk_checkin_packfile(struct bulk_checkin_packfile *state)
close(fd);
}
- strbuf_addf(&packname, "%s/pack/pack-%s.", get_object_directory(),
+ strbuf_addf(&packname, "%s/pack/pack-%s.", repo_get_object_directory(the_repository),
hash_to_hex(hash));
finish_tmp_packfile(&packname, state->pack_tmp_name,
state->written, state->nr_written,
@@ -113,7 +113,7 @@ static void flush_batch_fsync(void)
* to ensure that the data in each new object file is durable before
* the final name is visible.
*/
- strbuf_addf(&temp_path, "%s/bulk_fsync_XXXXXX", get_object_directory());
+ strbuf_addf(&temp_path, "%s/bulk_fsync_XXXXXX", repo_get_object_directory(the_repository));
temp = xmks_tempfile(temp_path.buf);
fsync_or_die(get_tempfile_fd(temp), get_tempfile_path(temp));
delete_tempfile(&temp);
diff --git a/bundle-uri.c b/bundle-uri.c
index dc0c96955b..4b1a2e2937 100644
--- a/bundle-uri.c
+++ b/bundle-uri.c
@@ -4,7 +4,6 @@
#include "bundle-uri.h"
#include "bundle.h"
#include "copy.h"
-#include "environment.h"
#include "gettext.h"
#include "refs.h"
#include "run-command.h"
@@ -14,6 +13,7 @@
#include "fetch-pack.h"
#include "remote.h"
#include "trace2.h"
+#include "object-store-ll.h"
static struct {
enum bundle_list_heuristic heuristic;
diff --git a/cache-tree.c b/cache-tree.c
index 50610c3f3c..b482167a69 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -1,7 +1,6 @@
#define USE_THE_REPOSITORY_VARIABLE
#include "git-compat-util.h"
-#include "environment.h"
#include "hex.h"
#include "lockfile.h"
#include "tree.h"
@@ -12,6 +11,7 @@
#include "object-store-ll.h"
#include "read-cache-ll.h"
#include "replace-object.h"
+#include "repository.h"
#include "promisor-remote.h"
#include "trace.h"
#include "trace2.h"
@@ -725,7 +725,8 @@ int write_index_as_tree(struct object_id *oid, struct index_state *index_state,
hold_lock_file_for_update(&lock_file, index_path, LOCK_DIE_ON_ERROR);
- entries = read_index_from(index_state, index_path, get_git_dir());
+ entries = read_index_from(index_state, index_path,
+ repo_get_git_dir(the_repository));
if (entries < 0) {
ret = WRITE_TREE_UNREADABLE_INDEX;
goto out;
diff --git a/cbtree.c b/cbtree.c
index c1cc30a5dc..cf8cf75b89 100644
--- a/cbtree.c
+++ b/cbtree.c
@@ -12,7 +12,7 @@ static struct cb_node *cb_node_of(const void *p)
return (struct cb_node *)((uintptr_t)p - 1);
}
-/* locate the best match, does not do a final comparision */
+/* locate the best match, does not do a final comparison */
static struct cb_node *cb_internal_best_match(struct cb_node *p,
const uint8_t *k, size_t klen)
{
diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh
index 4781cd20bb..08656a1530 100755
--- a/ci/install-dependencies.sh
+++ b/ci/install-dependencies.sh
@@ -33,37 +33,49 @@ fedora-*)
dnf -yq update >/dev/null &&
dnf -yq install make gcc findutils diffutils perl python3 gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null
;;
-ubuntu-*)
+ubuntu-*|ubuntu32-*)
# Required so that apt doesn't wait for user input on certain packages.
export DEBIAN_FRONTEND=noninteractive
+ case "$distro" in
+ ubuntu-*)
+ SVN='libsvn-perl subversion'
+ ;;
+ *)
+ SVN=
+ ;;
+ esac
+
sudo apt-get -q update
sudo apt-get -q -y install \
- language-pack-is libsvn-perl apache2 cvs cvsps git gnupg subversion \
+ language-pack-is apache2 cvs cvsps git gnupg $SVN \
make libssl-dev libcurl4-openssl-dev libexpat-dev wget sudo default-jre \
tcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl \
libemail-valid-perl libio-pty-perl libio-socket-ssl-perl libnet-smtp-ssl-perl libdbd-sqlite3-perl libcgi-pm-perl \
${CC_PACKAGE:-${CC:-gcc}} $PYTHON_PACKAGE
- mkdir --parents "$CUSTOM_PATH"
- wget --quiet --directory-prefix="$CUSTOM_PATH" \
- "$P4WHENCE/bin.linux26x86_64/p4d" "$P4WHENCE/bin.linux26x86_64/p4"
- chmod a+x "$CUSTOM_PATH/p4d" "$CUSTOM_PATH/p4"
-
- wget --quiet "$LFSWHENCE/git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz"
- tar -xzf "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz" \
- -C "$CUSTOM_PATH" --strip-components=1 "git-lfs-$LINUX_GIT_LFS_VERSION/git-lfs"
- rm "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz"
-
- wget --quiet "$JGITWHENCE" --output-document="$CUSTOM_PATH/jgit"
- chmod a+x "$CUSTOM_PATH/jgit"
- ;;
-ubuntu32-*)
- sudo linux32 --32bit i386 sh -c '
- apt update >/dev/null &&
- apt install -y build-essential libcurl4-openssl-dev \
- libssl-dev libexpat-dev gettext python >/dev/null
- '
+ case "$distro" in
+ ubuntu-16.04)
+ # Does not support JGit, but we also don't really care about
+ # the others. We rather care whether Git still compiles and
+ # runs fine overall.
+ ;;
+ ubuntu-*)
+ mkdir --parents "$CUSTOM_PATH"
+
+ wget --quiet --directory-prefix="$CUSTOM_PATH" \
+ "$P4WHENCE/bin.linux26x86_64/p4d" "$P4WHENCE/bin.linux26x86_64/p4"
+ chmod a+x "$CUSTOM_PATH/p4d" "$CUSTOM_PATH/p4"
+
+ wget --quiet "$LFSWHENCE/git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz"
+ tar -xzf "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz" \
+ -C "$CUSTOM_PATH" --strip-components=1 "git-lfs-$LINUX_GIT_LFS_VERSION/git-lfs"
+ rm "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz"
+
+ wget --quiet "$JGITWHENCE" --output-document="$CUSTOM_PATH/jgit"
+ chmod a+x "$CUSTOM_PATH/jgit"
+ ;;
+ esac
;;
macos-*)
export HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1
diff --git a/ci/lib.sh b/ci/lib.sh
index 51f8f59a29..74b430be23 100755
--- a/ci/lib.sh
+++ b/ci/lib.sh
@@ -336,7 +336,14 @@ ubuntu-*)
fi
MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/$PYTHON_PACKAGE"
- export GIT_TEST_HTTPD=true
+ case "$distro" in
+ ubuntu-16.04)
+ # Apache is too old for HTTP/2.
+ ;;
+ *)
+ export GIT_TEST_HTTPD=true
+ ;;
+ esac
# The Linux build installs the defined dependency versions below.
# The OS X build installs much more recent versions, whichever
diff --git a/ci/run-docker-build.sh b/ci/run-docker-build.sh
deleted file mode 100755
index 6cd832efb9..0000000000
--- a/ci/run-docker-build.sh
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/sh
-#
-# Build and test Git inside container
-#
-# Usage:
-# run-docker-build.sh <host-user-id>
-#
-
-set -ex
-
-if test $# -ne 1 || test -z "$1"
-then
- echo >&2 "usage: run-docker-build.sh <host-user-id>"
- exit 1
-fi
-
-case "$jobname" in
-linux32)
- switch_cmd="linux32 --32bit i386"
- ;;
-linux-musl)
- switch_cmd=
- useradd () { adduser -D "$@"; }
- ;;
-*)
- exit 1
- ;;
-esac
-
-"${0%/*}/install-docker-dependencies.sh"
-
-# If this script runs inside a docker container, then all commands are
-# usually executed as root. Consequently, the host user might not be
-# able to access the test output files.
-# If a non 0 host user id is given, then create a user "ci" with that
-# user id to make everything accessible to the host user.
-HOST_UID=$1
-if test $HOST_UID -eq 0
-then
- # Just in case someone does want to run the test suite as root.
- CI_USER=root
-else
- CI_USER=ci
- if test "$(id -u $CI_USER 2>/dev/null)" = $HOST_UID
- then
- echo "user '$CI_USER' already exists with the requested ID $HOST_UID"
- else
- useradd -u $HOST_UID $CI_USER
- fi
-fi
-
-# Build and test
-command $switch_cmd su -m -l $CI_USER -c "
- set -ex
- export DEVELOPER='$DEVELOPER'
- export DEFAULT_TEST_TARGET='$DEFAULT_TEST_TARGET'
- export GIT_PROVE_OPTS='$GIT_PROVE_OPTS'
- export GIT_TEST_OPTS='$GIT_TEST_OPTS'
- export GIT_TEST_CLONE_2GB='$GIT_TEST_CLONE_2GB'
- export MAKEFLAGS='$MAKEFLAGS'
- export cache_dir='$cache_dir'
- cd /usr/src/git
- test -n '$cache_dir' && ln -s '$cache_dir/.prove' t/.prove
- make
- make test
-"
diff --git a/ci/run-docker.sh b/ci/run-docker.sh
deleted file mode 100755
index af89d1624a..0000000000
--- a/ci/run-docker.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/sh
-#
-# Download and run Docker image to build and test Git
-#
-
-. ${0%/*}/lib.sh
-
-case "$jobname" in
-linux32)
- CI_CONTAINER="daald/ubuntu32:xenial"
- ;;
-linux-musl)
- CI_CONTAINER=alpine
- ;;
-*)
- exit 1
- ;;
-esac
-
-docker pull "$CI_CONTAINER"
-
-# Use the following command to debug the docker build locally:
-# <host-user-id> must be 0 if podman is used as drop-in replacement for docker
-# $ docker run -itv "${PWD}:/usr/src/git" --entrypoint /bin/sh "$CI_CONTAINER"
-# root@container:/# export jobname=<jobname>
-# root@container:/# /usr/src/git/ci/run-docker-build.sh <host-user-id>
-
-container_cache_dir=/tmp/container-cache
-
-docker run \
- --interactive \
- --env DEVELOPER \
- --env DEFAULT_TEST_TARGET \
- --env GIT_PROVE_OPTS \
- --env GIT_TEST_OPTS \
- --env GIT_TEST_CLONE_2GB \
- --env MAKEFLAGS \
- --env jobname \
- --env cache_dir="$container_cache_dir" \
- --volume "${PWD}:/usr/src/git" \
- --volume "$cache_dir:$container_cache_dir" \
- "$CI_CONTAINER" \
- /usr/src/git/ci/run-docker-build.sh $(id -u $USER)
-
-check_unignored_build_artifacts
-
-save_good_tree
diff --git a/commit-graph.c b/commit-graph.c
index aa6e08eb39..5bd89c0acd 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -2055,7 +2055,6 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
}
if (safe_create_leading_directories(ctx->graph_name)) {
- UNLEAK(ctx->graph_name);
error(_("unable to create leading directories of %s"),
ctx->graph_name);
return -1;
diff --git a/commit.c b/commit.c
index 34cac0e302..3a54e4db0d 100644
--- a/commit.c
+++ b/commit.c
@@ -292,14 +292,14 @@ static int read_graft_file(struct repository *r, const char *graft_file)
void prepare_commit_graft(struct repository *r)
{
- char *graft_file;
+ const char *graft_file;
if (r->parsed_objects->commit_graft_prepared)
return;
if (!startup_info->have_repository)
return;
- graft_file = get_graft_file(r);
+ graft_file = repo_get_graft_file(r);
read_graft_file(r, graft_file);
/* make sure shallows are read */
is_repository_shallow(r);
diff --git a/commit.h b/commit.h
index 13098422c5..943e3d74b2 100644
--- a/commit.h
+++ b/commit.h
@@ -254,7 +254,10 @@ struct oid_array;
struct ref;
int for_each_commit_graft(each_commit_graft_fn, void *);
-int interactive_add(const char **argv, const char *prefix, int patch);
+int interactive_add(struct repository *repo,
+ const char **argv,
+ const char *prefix,
+ int patch);
struct commit_extra_header {
struct commit_extra_header *next;
diff --git a/compat/mingw.c b/compat/mingw.c
index eb13c02a76..0e851ecae2 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "../git-compat-util.h"
#include "win32.h"
#include <aclapi.h>
diff --git a/compat/win32/path-utils.c b/compat/win32/path-utils.c
index b658ca3f81..966ef779b9 100644
--- a/compat/win32/path-utils.c
+++ b/compat/win32/path-utils.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "../../git-compat-util.h"
#include "../../environment.h"
diff --git a/config.c b/config.c
index 56b5862e59..a11bb85da3 100644
--- a/config.c
+++ b/config.c
@@ -6,6 +6,8 @@
*
*/
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
#include "abspath.h"
#include "advice.h"
@@ -304,13 +306,16 @@ static int include_by_branch(struct config_include_data *data,
int flags;
int ret;
struct strbuf pattern = STRBUF_INIT;
- const char *refname = (!data->repo || !data->repo->gitdir) ?
- NULL : refs_resolve_ref_unsafe(get_main_ref_store(data->repo),
- "HEAD", 0, NULL, &flags);
- const char *shortname;
+ const char *refname, *shortname;
+
+ if (!data->repo || data->repo->ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN)
+ return 0;
- if (!refname || !(flags & REF_ISSYMREF) ||
- !skip_prefix(refname, "refs/heads/", &shortname))
+ refname = refs_resolve_ref_unsafe(get_main_ref_store(data->repo),
+ "HEAD", 0, NULL, &flags);
+ if (!refname ||
+ !(flags & REF_ISSYMREF) ||
+ !skip_prefix(refname, "refs/heads/", &shortname))
return 0;
strbuf_add(&pattern, cond, cond_len);
@@ -1445,26 +1450,6 @@ static int git_default_core_config(const char *var, const char *value,
return 0;
}
- if (!strcmp(var, "core.prefersymlinkrefs")) {
- prefer_symlink_refs = git_config_bool(var, value);
- return 0;
- }
-
- if (!strcmp(var, "core.logallrefupdates")) {
- if (value && !strcasecmp(value, "always"))
- log_all_ref_updates = LOG_REFS_ALWAYS;
- else if (git_config_bool(var, value))
- log_all_ref_updates = LOG_REFS_NORMAL;
- else
- log_all_ref_updates = LOG_REFS_NONE;
- return 0;
- }
-
- if (!strcmp(var, "core.warnambiguousrefs")) {
- warn_ambiguous_refs = git_config_bool(var, value);
- return 0;
- }
-
if (!strcmp(var, "core.abbrev")) {
if (!value)
return config_error_nonbool(var);
@@ -1573,14 +1558,6 @@ static int git_default_core_config(const char *var, const char *value,
return git_config_string(&check_roundtrip_encoding, var, value);
}
- if (!strcmp(var, "core.notesref")) {
- if (!value)
- return config_error_nonbool(var);
- free(notes_ref_name);
- notes_ref_name = xstrdup(value);
- return 0;
- }
-
if (!strcmp(var, "core.editor")) {
FREE_AND_NULL(editor_program);
return git_config_string(&editor_program, var, value);
@@ -2202,7 +2179,7 @@ static void configset_iter(struct config_set *set, config_fn_t fn, void *data)
}
}
-void read_early_config(config_fn_t cb, void *data)
+void read_early_config(struct repository *repo, config_fn_t cb, void *data)
{
struct config_options opts = {0};
struct strbuf commondir = STRBUF_INIT;
@@ -2210,9 +2187,9 @@ void read_early_config(config_fn_t cb, void *data)
opts.respect_includes = 1;
- if (have_git_dir()) {
- opts.commondir = get_git_common_dir();
- opts.git_dir = get_git_dir();
+ if (repo && repo->gitdir) {
+ opts.commondir = repo_get_common_dir(repo);
+ opts.git_dir = repo_get_git_dir(repo);
/*
* When setup_git_directory() was not yet asked to discover the
* GIT_DIR, we ask discover_git_directory() to figure out whether there
@@ -2232,10 +2209,6 @@ void read_early_config(config_fn_t cb, void *data)
strbuf_release(&gitdir);
}
-/*
- * Read config but only enumerate system and global settings.
- * Omit any repo-local, worktree-local, or command-line settings.
- */
void read_very_early_config(config_fn_t cb, void *data)
{
struct config_options opts = { 0 };
diff --git a/config.h b/config.h
index d0497157c5..5c730c4f89 100644
--- a/config.h
+++ b/config.h
@@ -192,7 +192,18 @@ int git_config_from_blob_oid(config_fn_t fn, const char *name,
void git_config_push_parameter(const char *text);
void git_config_push_env(const char *spec);
int git_config_from_parameters(config_fn_t fn, void *data);
-void read_early_config(config_fn_t cb, void *data);
+
+/*
+ * Read config when the Git directory has not yet been set up. In case
+ * `the_repository` has not yet been set up, try to discover the Git
+ * directory to read the configuration from.
+ */
+void read_early_config(struct repository *repo, config_fn_t cb, void *data);
+
+/*
+ * Read config but only enumerate system and global settings.
+ * Omit any repo-local, worktree-local, or command-line settings.
+ */
void read_very_early_config(config_fn_t cb, void *data);
/**
diff --git a/config.mak.dev b/config.mak.dev
index 50026d1e0e..8eca7fa228 100644
--- a/config.mak.dev
+++ b/config.mak.dev
@@ -69,7 +69,7 @@ DEVELOPER_CFLAGS += -Wno-missing-braces
endif
endif
-# Old versions of clang complain about initializaing a
+# Old versions of clang complain about initializing a
# struct-within-a-struct using just "{0}" rather than "{{0}}". This
# error is considered a false-positive and not worth fixing, because
# new clang versions do not, so just disable it.
diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
index 832f46b316..62af7b33d2 100644
--- a/contrib/buildsystems/CMakeLists.txt
+++ b/contrib/buildsystems/CMakeLists.txt
@@ -970,18 +970,15 @@ if(BUILD_TESTING)
add_executable(test-fake-ssh ${CMAKE_SOURCE_DIR}/t/helper/test-fake-ssh.c)
target_link_libraries(test-fake-ssh common-main)
-#reftable-tests
-parse_makefile_for_sources(test-reftable_SOURCES "REFTABLE_TEST_OBJS")
-list(TRANSFORM test-reftable_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/")
-
#unit-tests
-add_library(unit-test-lib OBJECT ${CMAKE_SOURCE_DIR}/t/unit-tests/test-lib.c)
-add_library(unit-test-lib-oid OBJECT ${CMAKE_SOURCE_DIR}/t/unit-tests/lib-oid.c)
+parse_makefile_for_sources(unit-test_SOURCES "UNIT_TEST_OBJS")
+list(TRANSFORM unit-test_SOURCES REPLACE "\\$\\(UNIT_TEST_DIR\\)/" "${CMAKE_SOURCE_DIR}/t/unit-tests/")
+add_library(unit-test-lib STATIC ${unit-test_SOURCES})
parse_makefile_for_scripts(unit_test_PROGRAMS "UNIT_TEST_PROGRAMS" "")
foreach(unit_test ${unit_test_PROGRAMS})
add_executable("${unit_test}" "${CMAKE_SOURCE_DIR}/t/unit-tests/${unit_test}.c")
- target_link_libraries("${unit_test}" unit-test-lib unit-test-lib-oid common-main)
+ target_link_libraries("${unit_test}" unit-test-lib common-main)
set_target_properties("${unit_test}"
PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/t/unit-tests/bin)
if(MSVC)
@@ -1004,12 +1001,65 @@ foreach(unit_test ${unit_test_PROGRAMS})
endif()
endforeach()
+parse_makefile_for_scripts(clar_test_SUITES "CLAR_TEST_SUITES" "")
+
+set(clar_decls "")
+set(clar_cbs "")
+set(clar_cbs_count 0)
+set(clar_suites "static struct clar_suite _clar_suites[] = {\n")
+list(LENGTH clar_test_SUITES clar_suites_count)
+foreach(suite ${clar_test_SUITES})
+ file(STRINGS "${CMAKE_SOURCE_DIR}/t/unit-tests/${suite}.c" decls
+ REGEX "^void test_${suite}__[a-zA-Z_0-9][a-zA-Z_0-9]*\\(void\\)$")
+
+ list(LENGTH decls decls_count)
+ string(REGEX REPLACE "void (test_${suite}__([a-zA-Z_0-9]*))\\(void\\)" " { \"\\2\", &\\1 },\n" cbs ${decls})
+ string(JOIN "" cbs ${cbs})
+ list(TRANSFORM decls PREPEND "extern ")
+ string(JOIN ";\n" decls ${decls})
+
+ string(APPEND clar_decls "${decls};\n")
+ string(APPEND clar_cbs
+ "static const struct clar_func _clar_cb_${suite}[] = {\n"
+ ${cbs}
+ "};\n")
+ string(APPEND clar_suites
+ " {\n"
+ " \"${suite}\",\n"
+ " { NULL, NULL },\n"
+ " { NULL, NULL },\n"
+ " _clar_cb_${suite}, ${decls_count}, 1\n"
+ " },\n")
+ math(EXPR clar_cbs_count "${clar_cbs_count}+${decls_count}")
+endforeach()
+string(APPEND clar_suites
+ "};\n"
+ "static const size_t _clar_suite_count = ${clar_suites_count};\n"
+ "static const size_t _clar_callback_count = ${clar_cbs_count};\n")
+file(WRITE "${CMAKE_BINARY_DIR}/t/unit-tests/clar-decls.h" "${clar_decls}")
+file(WRITE "${CMAKE_BINARY_DIR}/t/unit-tests/clar.suite" "${clar_decls}" "${clar_cbs}" "${clar_suites}")
+
+list(TRANSFORM clar_test_SUITES PREPEND "${CMAKE_SOURCE_DIR}/t/unit-tests/")
+list(TRANSFORM clar_test_SUITES APPEND ".c")
+add_library(unit-tests-lib ${clar_test_SUITES} "${CMAKE_SOURCE_DIR}/t/unit-tests/clar/clar.c")
+target_include_directories(unit-tests-lib PRIVATE "${CMAKE_SOURCE_DIR}/t/unit-tests")
+add_executable(unit-tests "${CMAKE_SOURCE_DIR}/t/unit-tests/unit-test.c")
+target_link_libraries(unit-tests unit-tests-lib common-main)
+set_target_properties(unit-tests
+ PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/t/unit-tests/bin)
+if(MSVC)
+ set_target_properties(unit-tests
+ PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/t/unit-tests/bin)
+ set_target_properties(unit-tests
+ PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/t/unit-tests/bin)
+endif()
+
#test-tool
parse_makefile_for_sources(test-tool_SOURCES "TEST_BUILTINS_OBJS")
add_library(test-lib OBJECT ${CMAKE_SOURCE_DIR}/t/unit-tests/test-lib.c)
list(TRANSFORM test-tool_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/t/helper/")
-add_executable(test-tool ${CMAKE_SOURCE_DIR}/t/helper/test-tool.c ${test-tool_SOURCES} ${test-reftable_SOURCES})
+add_executable(test-tool ${CMAKE_SOURCE_DIR}/t/helper/test-tool.c ${test-tool_SOURCES})
target_link_libraries(test-tool test-lib common-main)
set_target_properties(test-fake-ssh test-tool
diff --git a/contrib/git-jump/git-jump b/contrib/git-jump/git-jump
index 47e0c557e6..3f69675961 100755
--- a/contrib/git-jump/git-jump
+++ b/contrib/git-jump/git-jump
@@ -44,13 +44,13 @@ open_editor() {
mode_diff() {
git diff --no-prefix --relative "$@" |
perl -ne '
- if (m{^\+\+\+ (.*)}) { $file = $1; next }
+ if (m{^\+\+\+ (.*)}) { $file = $1 eq "/dev/null" ? undef : $1; next }
defined($file) or next;
if (m/^@@ .*?\+(\d+)/) { $line = $1; next }
defined($line) or next;
if (/^ /) { $line++; next }
if (/^[-+]\s*(.*)/) {
- print "$file:$line: $1\n";
+ print "$file:$line:1: $1\n";
$line = undef;
}
'
diff --git a/credential.c b/credential.c
index ee46351ce0..6dea3859ec 100644
--- a/credential.c
+++ b/credential.c
@@ -13,6 +13,8 @@
#include "strbuf.h"
#include "urlmatch.h"
#include "git-compat-util.h"
+#include "trace2.h"
+#include "repository.h"
void credential_init(struct credential *c)
{
@@ -251,14 +253,36 @@ static char *credential_ask_one(const char *what, struct credential *c,
return xstrdup(r);
}
-static void credential_getpass(struct credential *c)
+static int credential_getpass(struct credential *c)
{
+ int interactive;
+ char *value;
+ if (!git_config_get_maybe_bool("credential.interactive", &interactive) &&
+ !interactive) {
+ trace2_data_intmax("credential", the_repository,
+ "interactive/skipped", 1);
+ return -1;
+ }
+ if (!git_config_get_string("credential.interactive", &value)) {
+ int same = !strcmp(value, "never");
+ free(value);
+ if (same) {
+ trace2_data_intmax("credential", the_repository,
+ "interactive/skipped", 1);
+ return -1;
+ }
+ }
+
+ trace2_region_enter("credential", "interactive", the_repository);
if (!c->username)
c->username = credential_ask_one("Username", c,
PROMPT_ASKPASS|PROMPT_ECHO);
if (!c->password)
c->password = credential_ask_one("Password", c,
PROMPT_ASKPASS);
+ trace2_region_leave("credential", "interactive", the_repository);
+
+ return 0;
}
int credential_has_capability(const struct credential_capability *capa,
@@ -501,8 +525,8 @@ void credential_fill(struct credential *c, int all_capabilities)
c->helpers.items[i].string);
}
- credential_getpass(c);
- if (!c->username && !c->password && !c->credential)
+ if (credential_getpass(c) ||
+ (!c->username && !c->password && !c->credential))
die("unable to get password from user");
}
diff --git a/diff-no-index.c b/diff-no-index.c
index 3a8965672c..c5fb06e6d1 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -362,7 +362,7 @@ int diff_no_index(struct rev_info *revs,
* The return code for --no-index imitates diff(1):
* 0 = no changes, 1 = changes, else error
*/
- ret = diff_result_code(&revs->diffopt);
+ ret = diff_result_code(revs);
out:
for (i = 0; i < ARRAY_SIZE(to_free); i++)
diff --git a/diff.c b/diff.c
index 6555b8a32c..173cbe2bed 100644
--- a/diff.c
+++ b/diff.c
@@ -12,6 +12,7 @@
#include "environment.h"
#include "gettext.h"
#include "tempfile.h"
+#include "revision.h"
#include "quote.h"
#include "diff.h"
#include "diffcore.h"
@@ -29,6 +30,7 @@
#include "merge-ll.h"
#include "string-list.h"
#include "strvec.h"
+#include "tmp-objdir.h"
#include "graph.h"
#include "oid-array.h"
#include "packfile.h"
@@ -3675,6 +3677,7 @@ static void builtin_diff(const char *name_a,
emit_diff_symbol(o, DIFF_SYMBOL_BINARY_FILES,
sb.buf, sb.len, 0);
strbuf_release(&sb);
+ o->found_changes = 1;
goto free_ab_and_return;
}
if (fill_mmfile(o->repo, &mf1, one) < 0 ||
@@ -7091,10 +7094,16 @@ void diffcore_std(struct diff_options *options)
options->found_follow = 0;
}
-int diff_result_code(struct diff_options *opt)
+int diff_result_code(struct rev_info *revs)
{
+ struct diff_options *opt = &revs->diffopt;
int result = 0;
+ if (revs->remerge_diff) {
+ tmp_objdir_destroy(revs->remerge_objdir);
+ revs->remerge_objdir = NULL;
+ }
+
diff_warn_rename_limit("diff.renameLimit",
opt->needed_rename_limit,
opt->degraded_cc_to_c);
diff --git a/diff.h b/diff.h
index b95d3c1e83..0cde3b34e2 100644
--- a/diff.h
+++ b/diff.h
@@ -648,7 +648,7 @@ int do_diff_cache(const struct object_id *, struct diff_options *);
int diff_flush_patch_id(struct diff_options *, struct object_id *, int);
void flush_one_hunk(struct object_id *result, git_hash_ctx *ctx);
-int diff_result_code(struct diff_options *);
+int diff_result_code(struct rev_info *);
int diff_no_index(struct rev_info *,
int implicit_no_index, int, const char **);
diff --git a/diffcore-rename.c b/diffcore-rename.c
index fab45b10d7..3d6826baa3 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -933,7 +933,7 @@ static int find_basename_matches(struct diff_options *options,
* spend more cycles to find similarities between files, so it may
* be less likely that this heuristic is wanted. If someone is
* doing break detection, that means they do not want filename
- * similarity to imply any form of content similiarity, and thus
+ * similarity to imply any form of content similarity, and thus
* this heuristic would definitely be incompatible.
*/
@@ -1534,7 +1534,7 @@ void diffcore_rename_extended(struct diff_options *options,
* - remove ones not found in relevant_sources
* and
* - remove ones in relevant_sources which are needed only
- * for directory renames IF no ancestory directory
+ * for directory renames IF no ancestry directory
* actually needs to know any more individual path
* renames under them
*/
diff --git a/dir.c b/dir.c
index 787bcb7a1a..e3ddd5b529 100644
--- a/dir.c
+++ b/dir.c
@@ -20,6 +20,7 @@
#include "object-store-ll.h"
#include "path.h"
#include "refs.h"
+#include "repository.h"
#include "wildmatch.h"
#include "pathspec.h"
#include "utf8.h"
@@ -2836,7 +2837,7 @@ static const char *get_ident_string(void)
return sb.buf;
if (uname(&uts) < 0)
die_errno(_("failed to get kernel name and information"));
- strbuf_addf(&sb, "Location %s, system %s", get_git_work_tree(),
+ strbuf_addf(&sb, "Location %s, system %s", repo_get_work_tree(the_repository),
uts.sysname);
return sb.buf;
}
diff --git a/environment.c b/environment.c
index 1d6c48b52d..a2ce998081 100644
--- a/environment.c
+++ b/environment.c
@@ -22,15 +22,9 @@
#include "fmt-merge-msg.h"
#include "commit.h"
#include "strvec.h"
-#include "object-file.h"
-#include "object-store-ll.h"
#include "path.h"
-#include "replace-object.h"
-#include "tmp-objdir.h"
#include "chdir-notify.h"
#include "setup.h"
-#include "shallow.h"
-#include "trace.h"
#include "write-or-die.h"
int trust_executable_bit = 1;
@@ -40,9 +34,7 @@ int has_symlinks = 1;
int minimum_abbrev = 4, default_abbrev = -1;
int ignore_case;
int assume_unchanged;
-int prefer_symlink_refs;
int is_bare_repository_cfg = -1; /* unspecified */
-int warn_ambiguous_refs = 1;
int warn_on_object_refname_ambiguity = 1;
int repository_format_precious_objects;
char *git_commit_encoding;
@@ -75,7 +67,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
#define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS
#endif
enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
-char *notes_ref_name;
int grafts_keep_true_parents;
int core_apply_sparse_checkout;
int core_sparse_checkout_cone;
@@ -83,7 +74,6 @@ int sparse_expect_files_outside_of_patterns;
int merge_log_config = -1;
int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
unsigned long pack_size_limit_cfg;
-enum log_refs_config log_all_ref_updates = LOG_REFS_UNSET;
int max_allowed_tree_depth =
#ifdef _MSC_VER
/*
@@ -123,8 +113,6 @@ int core_preload_index = 1;
/* This is set by setup_git_dir_gently() and/or git_default_config() */
char *git_work_tree_cfg;
-static char *git_namespace;
-
/*
* Repository-local GIT_* environment variables; see environment.h for details.
*/
@@ -147,27 +135,6 @@ const char * const local_repo_env[] = {
NULL
};
-static char *expand_namespace(const char *raw_namespace)
-{
- struct strbuf buf = STRBUF_INIT;
- struct strbuf **components, **c;
-
- if (!raw_namespace || !*raw_namespace)
- return xstrdup("");
-
- strbuf_addstr(&buf, raw_namespace);
- components = strbuf_split(&buf, '/');
- strbuf_reset(&buf);
- for (c = components; *c; c++)
- if (strcmp((*c)->buf, "/") != 0)
- strbuf_addf(&buf, "refs/namespaces/%s", (*c)->buf);
- strbuf_list_free(components);
- if (check_refname_format(buf.buf, 0))
- die(_("bad git namespace path \"%s\""), raw_namespace);
- strbuf_addch(&buf, '/');
- return strbuf_detach(&buf, NULL);
-}
-
const char *getenv_safe(struct strvec *argv, const char *name)
{
const char *value = getenv(name);
@@ -179,47 +146,10 @@ const char *getenv_safe(struct strvec *argv, const char *name)
return argv->v[argv->nr - 1];
}
-void setup_git_env(const char *git_dir)
-{
- char *git_replace_ref_base;
- const char *shallow_file;
- const char *replace_ref_base;
- struct set_gitdir_args args = { NULL };
- struct strvec to_free = STRVEC_INIT;
-
- args.commondir = getenv_safe(&to_free, GIT_COMMON_DIR_ENVIRONMENT);
- args.object_dir = getenv_safe(&to_free, DB_ENVIRONMENT);
- args.graft_file = getenv_safe(&to_free, GRAFT_ENVIRONMENT);
- args.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT);
- args.alternate_db = getenv_safe(&to_free, ALTERNATE_DB_ENVIRONMENT);
- if (getenv(GIT_QUARANTINE_ENVIRONMENT)) {
- args.disable_ref_updates = 1;
- }
-
- repo_set_gitdir(the_repository, git_dir, &args);
- strvec_clear(&to_free);
-
- if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
- disable_replace_refs();
- replace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);
- git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base
- : "refs/replace/");
- update_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);
-
- free(git_namespace);
- git_namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));
- shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);
- if (shallow_file)
- set_alternate_shallow_file(the_repository, shallow_file, 0);
-
- if (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0))
- fetch_if_missing = 0;
-}
-
int is_bare_repository(void)
{
/* if core.bare is not 'false', let's see if there is a work tree */
- return is_bare_repository_cfg && !get_git_work_tree();
+ return is_bare_repository_cfg && !repo_get_work_tree(the_repository);
}
int have_git_dir(void)
@@ -228,156 +158,45 @@ int have_git_dir(void)
|| the_repository->gitdir;
}
-const char *get_git_dir(void)
-{
- if (!the_repository->gitdir)
- BUG("git environment hasn't been setup");
- return the_repository->gitdir;
-}
-
-const char *get_git_common_dir(void)
-{
- if (!the_repository->commondir)
- BUG("git environment hasn't been setup");
- return the_repository->commondir;
-}
-
const char *get_git_namespace(void)
{
- if (!git_namespace)
- BUG("git environment hasn't been setup");
- return git_namespace;
-}
+ static const char *namespace;
-const char *strip_namespace(const char *namespaced_ref)
-{
- const char *out;
- if (skip_prefix(namespaced_ref, get_git_namespace(), &out))
- return out;
- return NULL;
-}
-
-static int git_work_tree_initialized;
+ struct strbuf buf = STRBUF_INIT;
+ struct strbuf **components, **c;
+ const char *raw_namespace;
-/*
- * Note. This works only before you used a work tree. This was added
- * primarily to support git-clone to work in a new repository it just
- * created, and is not meant to flip between different work trees.
- */
-void set_git_work_tree(const char *new_work_tree)
-{
- if (git_work_tree_initialized) {
- struct strbuf realpath = STRBUF_INIT;
+ if (namespace)
+ return namespace;
- strbuf_realpath(&realpath, new_work_tree, 1);
- new_work_tree = realpath.buf;
- if (strcmp(new_work_tree, the_repository->worktree))
- die("internal error: work tree has already been set\n"
- "Current worktree: %s\nNew worktree: %s",
- the_repository->worktree, new_work_tree);
- strbuf_release(&realpath);
- return;
+ raw_namespace = getenv(GIT_NAMESPACE_ENVIRONMENT);
+ if (!raw_namespace || !*raw_namespace) {
+ namespace = "";
+ return namespace;
}
- git_work_tree_initialized = 1;
- repo_set_worktree(the_repository, new_work_tree);
-}
-
-const char *get_git_work_tree(void)
-{
- return the_repository->worktree;
-}
-
-const char *get_object_directory(void)
-{
- if (!the_repository->objects->odb)
- BUG("git environment hasn't been setup");
- return the_repository->objects->odb->path;
-}
-
-int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)
-{
- int fd;
- /*
- * we let the umask do its job, don't try to be more
- * restrictive except to remove write permission.
- */
- int mode = 0444;
- git_path_buf(temp_filename, "objects/%s", pattern);
- fd = git_mkstemp_mode(temp_filename->buf, mode);
- if (0 <= fd)
- return fd;
-
- /* slow path */
- /* some mkstemp implementations erase temp_filename on failure */
- git_path_buf(temp_filename, "objects/%s", pattern);
- safe_create_leading_directories(temp_filename->buf);
- return xmkstemp_mode(temp_filename->buf, mode);
-}
-
-int odb_pack_keep(const char *name)
-{
- int fd;
-
- fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
- if (0 <= fd)
- return fd;
-
- /* slow path */
- safe_create_leading_directories_const(name);
- return open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
-}
-
-char *get_index_file(void)
-{
- if (!the_repository->index_file)
- BUG("git environment hasn't been setup");
- return the_repository->index_file;
-}
-
-char *get_graft_file(struct repository *r)
-{
- if (!r->graft_file)
- BUG("git environment hasn't been setup");
- return r->graft_file;
-}
-static void set_git_dir_1(const char *path)
-{
- xsetenv(GIT_DIR_ENVIRONMENT, path, 1);
- setup_git_env(path);
-}
+ strbuf_addstr(&buf, raw_namespace);
+ components = strbuf_split(&buf, '/');
+ strbuf_reset(&buf);
+ for (c = components; *c; c++)
+ if (strcmp((*c)->buf, "/") != 0)
+ strbuf_addf(&buf, "refs/namespaces/%s", (*c)->buf);
+ strbuf_list_free(components);
+ if (check_refname_format(buf.buf, 0))
+ die(_("bad git namespace path \"%s\""), raw_namespace);
+ strbuf_addch(&buf, '/');
-static void update_relative_gitdir(const char *name UNUSED,
- const char *old_cwd,
- const char *new_cwd,
- void *data UNUSED)
-{
- char *path = reparent_relative_path(old_cwd, new_cwd, get_git_dir());
- struct tmp_objdir *tmp_objdir = tmp_objdir_unapply_primary_odb();
+ namespace = strbuf_detach(&buf, NULL);
- trace_printf_key(&trace_setup_key,
- "setup: move $GIT_DIR to '%s'",
- path);
- set_git_dir_1(path);
- if (tmp_objdir)
- tmp_objdir_reapply_primary_odb(tmp_objdir, old_cwd, new_cwd);
- free(path);
+ return namespace;
}
-void set_git_dir(const char *path, int make_realpath)
+const char *strip_namespace(const char *namespaced_ref)
{
- struct strbuf realpath = STRBUF_INIT;
-
- if (make_realpath) {
- strbuf_realpath(&realpath, path, 1);
- path = realpath.buf;
- }
-
- set_git_dir_1(path);
- if (!is_absolute_path(path))
- chdir_notify_register(NULL, update_relative_gitdir, NULL);
-
- strbuf_release(&realpath);
+ const char *out;
+ if (skip_prefix(namespaced_ref, get_git_namespace(), &out))
+ return out;
+ return NULL;
}
const char *get_log_output_encoding(void)
diff --git a/environment.h b/environment.h
index 0148738ed6..923e12661e 100644
--- a/environment.h
+++ b/environment.h
@@ -1,22 +1,7 @@
#ifndef ENVIRONMENT_H
#define ENVIRONMENT_H
-struct repository;
-struct strvec;
-
-/*
- * The character that begins a commented line in user-editable file
- * that is subject to stripspace.
- */
-extern const char *comment_line_str;
-extern char *comment_line_str_to_free;
-extern int auto_comment_line_char;
-
-/*
- * Wrapper of getenv() that returns a strdup value. This value is kept
- * in argv to be freed later.
- */
-const char *getenv_safe(struct strvec *argv, const char *name);
+#include "repo-settings.h"
/* Double-check local_repo_env below if you add to this list. */
#define GIT_DIR_ENVIRONMENT "GIT_DIR"
@@ -87,6 +72,8 @@ const char *getenv_safe(struct strvec *argv, const char *name);
*/
#define GIT_IMPLICIT_WORK_TREE_ENVIRONMENT "GIT_IMPLICIT_WORK_TREE"
+#define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
+
/*
* Repository-local GIT_* environment variables; these will be cleared
* when git spawns a sub-process that runs inside another repository.
@@ -95,6 +82,50 @@ const char *getenv_safe(struct strvec *argv, const char *name);
*/
extern const char * const local_repo_env[];
+struct strvec;
+
+/*
+ * Wrapper of getenv() that returns a strdup value. This value is kept
+ * in argv to be freed later.
+ */
+const char *getenv_safe(struct strvec *argv, const char *name);
+
+/*
+ * Should we print an ellipsis after an abbreviated SHA-1 value
+ * when doing diff-raw output or indicating a detached HEAD?
+ */
+int print_sha1_ellipsis(void);
+
+/*
+ * Returns the boolean value of $GIT_OPTIONAL_LOCKS (or the default value).
+ */
+int use_optional_locks(void);
+
+const char *get_git_namespace(void);
+const char *strip_namespace(const char *namespaced_ref);
+
+/*
+ * TODO: All the below state either explicitly or implicitly relies on
+ * `the_repository`. We should eventually get rid of these and make the
+ * dependency on a repository explicit:
+ *
+ * - `setup_git_env()` ideally shouldn't exist as it modifies global state,
+ * namely the environment. The current process shouldn't ever access that
+ * state via envvars though, but should instead consult a `struct
+ * repository`. When spawning new processes, we would ideally also pass a
+ * `struct repository` and then set up the environment variables for the
+ * child process, only.
+ *
+ * - `have_git_dir()` should not have to exist at all. Instead, we should
+ * decide on whether or not we have a `struct repository`.
+ *
+ * - All the global config variables should become tied to a repository. Like
+ * this, we'd correctly honor repository-local configuration and be able to
+ * distinguish configuration values from different repositories.
+ *
+ * Please do not add new global config variables here.
+ */
+# ifdef USE_THE_REPOSITORY_VARIABLE
void setup_git_env(const char *git_dir);
/*
@@ -103,21 +134,19 @@ void setup_git_env(const char *git_dir);
*/
int have_git_dir(void);
+/*
+ * Accessors for the core.sharedrepository config which lazy-load the value
+ * from the config (if not already set). The "reset" function can be
+ * used to unset "set" or cached value, meaning that the value will be loaded
+ * fresh from the config file on the next call to get_shared_repository().
+ */
+void set_shared_repository(int value);
+int get_shared_repository(void);
+void reset_shared_repository(void);
+
extern int is_bare_repository_cfg;
int is_bare_repository(void);
extern char *git_work_tree_cfg;
-const char *get_git_dir(void);
-const char *get_git_common_dir(void);
-const char *get_object_directory(void);
-char *get_index_file(void);
-char *get_graft_file(struct repository *r);
-void set_git_dir(const char *path, int make_realpath);
-const char *get_git_namespace(void);
-const char *strip_namespace(const char *namespaced_ref);
-const char *get_git_work_tree(void);
-void set_git_work_tree(const char *tree);
-
-#define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
/* Environment bits from configuration mechanism */
extern int trust_executable_bit;
@@ -127,8 +156,6 @@ extern int has_symlinks;
extern int minimum_abbrev, default_abbrev;
extern int ignore_case;
extern int assume_unchanged;
-extern int prefer_symlink_refs;
-extern int warn_ambiguous_refs;
extern int warn_on_object_refname_ambiguity;
extern char *apply_default_whitespace;
extern char *apply_default_ignorewhitespace;
@@ -143,16 +170,6 @@ extern unsigned long big_file_threshold;
extern unsigned long pack_size_limit_cfg;
extern int max_allowed_tree_depth;
-/*
- * Accessors for the core.sharedrepository config which lazy-load the value
- * from the config (if not already set). The "reset" function can be
- * used to unset "set" or cached value, meaning that the value will be loaded
- * fresh from the config file on the next call to get_shared_repository().
- */
-void set_shared_repository(int value);
-int get_shared_repository(void);
-void reset_shared_repository(void);
-
extern int core_preload_index;
extern int precomposed_unicode;
extern int protect_hfs;
@@ -162,25 +179,13 @@ extern int core_apply_sparse_checkout;
extern int core_sparse_checkout_cone;
extern int sparse_expect_files_outside_of_patterns;
-/*
- * Returns the boolean value of $GIT_OPTIONAL_LOCKS (or the default value).
- */
-int use_optional_locks(void);
-
-enum log_refs_config {
- LOG_REFS_UNSET = -1,
- LOG_REFS_NONE = 0,
- LOG_REFS_NORMAL,
- LOG_REFS_ALWAYS
-};
-extern enum log_refs_config log_all_ref_updates;
-
enum rebase_setup_type {
AUTOREBASE_NEVER = 0,
AUTOREBASE_LOCAL,
AUTOREBASE_REMOTE,
AUTOREBASE_ALWAYS
};
+extern enum rebase_setup_type autorebase;
enum push_default_type {
PUSH_DEFAULT_NOTHING = 0,
@@ -190,38 +195,18 @@ enum push_default_type {
PUSH_DEFAULT_CURRENT,
PUSH_DEFAULT_UNSPECIFIED
};
-
-extern enum rebase_setup_type autorebase;
extern enum push_default_type push_default;
enum object_creation_mode {
OBJECT_CREATION_USES_HARDLINKS = 0,
OBJECT_CREATION_USES_RENAMES = 1
};
-
extern enum object_creation_mode object_creation_mode;
-extern char *notes_ref_name;
-
extern int grafts_keep_true_parents;
extern int repository_format_precious_objects;
-/*
- * Create a temporary file rooted in the object database directory, or
- * die on failure. The filename is taken from "pattern", which should have the
- * usual "XXXXXX" trailer, and the resulting filename is written into the
- * "template" buffer. Returns the open descriptor.
- */
-int odb_mkstemp(struct strbuf *temp_filename, const char *pattern);
-
-/*
- * Create a pack .keep file named "name" (which should generally be the output
- * of odb_pack_name). Returns a file descriptor opened for writing, or -1 on
- * error.
- */
-int odb_pack_keep(const char *name);
-
const char *get_log_output_encoding(void);
const char *get_commit_output_encoding(void);
@@ -233,9 +218,12 @@ extern char *askpass_program;
extern char *excludes_file;
/*
- * Should we print an ellipsis after an abbreviated SHA-1 value
- * when doing diff-raw output or indicating a detached HEAD?
+ * The character that begins a commented line in user-editable file
+ * that is subject to stripspace.
*/
-int print_sha1_ellipsis(void);
+extern const char *comment_line_str;
+extern char *comment_line_str_to_free;
+extern int auto_comment_line_char;
-#endif
+# endif /* USE_THE_REPOSITORY_VARIABLE */
+#endif /* ENVIRONMENT_H */
diff --git a/fetch-pack.c b/fetch-pack.c
index 2c76bcad40..f752da93a8 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -1839,7 +1839,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
string_list_append_nodup(pack_lockfiles,
xstrfmt("%s/pack/pack-%s.keep",
- get_object_directory(),
+ repo_get_object_directory(the_repository),
packname));
}
string_list_clear(&packfile_uris, 0);
diff --git a/fsmonitor-settings.c b/fsmonitor-settings.c
index e818583420..a6587a8972 100644
--- a/fsmonitor-settings.c
+++ b/fsmonitor-settings.c
@@ -7,7 +7,7 @@
#include "fsmonitor-path-utils.h"
/*
- * We keep this structure defintion private and have getters
+ * We keep this structure definition private and have getters
* for all fields so that we can lazy load it as needed.
*/
struct fsmonitor_settings {
diff --git a/fsmonitor.c b/fsmonitor.c
index 28130f748f..237ca59d00 100644
--- a/fsmonitor.c
+++ b/fsmonitor.c
@@ -8,6 +8,7 @@
#include "fsmonitor.h"
#include "fsmonitor-ipc.h"
#include "name-hash.h"
+#include "repository.h"
#include "run-command.h"
#include "strbuf.h"
#include "trace2.h"
@@ -169,7 +170,7 @@ static int query_fsmonitor_hook(struct repository *r,
strvec_pushf(&cp.args, "%d", version);
strvec_pushf(&cp.args, "%s", last_update);
cp.use_shell = 1;
- cp.dir = get_git_work_tree();
+ cp.dir = repo_get_work_tree(the_repository);
trace2_region_enter("fsm_hook", "query", NULL);
diff --git a/git-instaweb.sh b/git-instaweb.sh
index 994431c887..8dbe21d588 100755
--- a/git-instaweb.sh
+++ b/git-instaweb.sh
@@ -612,7 +612,7 @@ python_conf() {
ln -sf "$root/static" "$fqgitdir/gitweb/$httpd_only/"
# generate a standalone 'python http.server' script in $fqgitdir/gitweb
- # This asumes that python is in user's $PATH
+ # This assumes that python is in user's $PATH
# This script is Python 2 and 3 compatible
cat > "$fqgitdir/gitweb/gitweb.py" <<EOF
#!/usr/bin/env python
diff --git a/git-p4.py b/git-p4.py
index f1ab31d540..c0ca7becaf 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -54,7 +54,7 @@ import time
import zipfile
import zlib
-# On python2.7 where raw_input() and input() are both availble,
+# On python2.7 where raw_input() and input() are both available,
# we want raw_input's semantics, but aliased to input for python3
# compatibility
# support basestring in python3
@@ -1804,7 +1804,7 @@ class P4Submit(Command, P4UserMap):
status from the script will abort the process.
The purpose of the hook is to edit the message file in place, and it is not
- supressed by the `--no-verify` option. This hook is called even if
+ suppressed by the `--no-verify` option. This hook is called even if
`--prepare-p4-only` is set.
The `p4-changelist` hook is executed after the changelist message has been
diff --git a/git.c b/git.c
index 3c7fabfda2..2a9752c91c 100644
--- a/git.c
+++ b/git.c
@@ -31,7 +31,7 @@
struct cmd_struct {
const char *cmd;
- int (*fn)(int, const char **, const char *);
+ int (*fn)(int, const char **, const char *, struct repository *);
unsigned int option;
};
@@ -441,7 +441,7 @@ static int handle_alias(int *argcp, const char ***argv)
return ret;
}
-static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
+static int run_builtin(struct cmd_struct *p, int argc, const char **argv, struct repository *repo)
{
int status, help;
struct stat st;
@@ -479,9 +479,9 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
trace_argv_printf(argv, "trace: built-in: git");
trace2_cmd_name(p->cmd);
- validate_cache_entries(the_repository->index);
- status = p->fn(argc, argv, prefix);
- validate_cache_entries(the_repository->index);
+ validate_cache_entries(repo->index);
+ status = p->fn(argc, argv, prefix, (p->option & RUN_SETUP)? repo : NULL);
+ validate_cache_entries(repo->index);
if (status)
return status;
@@ -746,7 +746,7 @@ static void handle_builtin(int argc, const char **argv)
builtin = get_builtin(cmd);
if (builtin) {
- int ret = run_builtin(builtin, argc, argv);
+ int ret = run_builtin(builtin, argc, argv, the_repository);
strvec_clear(&args);
free(argv_copy);
exit(ret);
diff --git a/gpg-interface.c b/gpg-interface.c
index cf6126b5aa..07335987a6 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -400,7 +400,7 @@ static void parse_ssh_output(struct signature_check *sigc)
* Note that "PRINCIPAL" can contain whitespace, "RSA" and
* "SHA256" part could be a different token that names of
* the algorithms used, and "FINGERPRINT" is a hexadecimal
- * string. By finding the last occurence of " with ", we can
+ * string. By finding the last occurrence of " with ", we can
* reliably parse out the PRINCIPAL.
*/
sigc->result = 'B';
diff --git a/help.c b/help.c
index c03863f226..4ad4ebdd2c 100644
--- a/help.c
+++ b/help.c
@@ -16,6 +16,7 @@
#include "parse-options.h"
#include "prompt.h"
#include "fsmonitor-ipc.h"
+#include "repository.h"
#ifndef NO_CURL
#include "git-curl-compat.h" /* For LIBCURL_VERSION only */
@@ -618,7 +619,7 @@ const char *help_unknown_cmd(const char *cmd)
memset(&other_cmds, 0, sizeof(other_cmds));
memset(&aliases, 0, sizeof(aliases));
- read_early_config(git_unknown_cmd_config, NULL);
+ read_early_config(the_repository, git_unknown_cmd_config, NULL);
/*
* Disable autocorrection prompt in a non-interactive session
@@ -775,7 +776,7 @@ void get_version_info(struct strbuf *buf, int show_build_options)
}
}
-int cmd_version(int argc, const char **argv, const char *prefix)
+int cmd_version(int argc, const char **argv, const char *prefix, struct repository *repository UNUSED)
{
struct strbuf buf = STRBUF_INIT;
int build_options = 0;
diff --git a/http-backend.c b/http-backend.c
index 79ce097359..73eec4ea3d 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -601,7 +601,7 @@ static void get_head(struct strbuf *hdr, char *arg UNUSED)
static void get_info_packs(struct strbuf *hdr, char *arg UNUSED)
{
- size_t objdirlen = strlen(get_object_directory());
+ size_t objdirlen = strlen(repo_get_object_directory(the_repository));
struct strbuf buf = STRBUF_INIT;
struct packed_git *p;
size_t cnt = 0;
diff --git a/http.c b/http.c
index 6c6cc5c822..376af88c5d 100644
--- a/http.c
+++ b/http.c
@@ -1707,7 +1707,7 @@ void run_active_slot(struct active_request_slot *slot)
* The value of slot->finished we set before the loop was used
* to set our "finished" variable when our request completed.
*
- * 1. The slot may not have been reused for another requst
+ * 1. The slot may not have been reused for another request
* yet, in which case it still has &finished.
*
* 2. The slot may already be in-use to serve another request,
diff --git a/imap-send.c b/imap-send.c
index 2dd42807cd..ec68a06687 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -31,9 +31,6 @@
#include "parse-options.h"
#include "setup.h"
#include "strbuf.h"
-#if defined(NO_OPENSSL) && !defined(HAVE_OPENSSL_CSPRNG)
-typedef void *SSL;
-#endif
#ifdef USE_CURL_FOR_IMAP_SEND
#include "http.h"
#endif
@@ -85,7 +82,11 @@ struct imap_server_conf {
struct imap_socket {
int fd[2];
+#if defined(NO_OPENSSL) && !defined(HAVE_OPENSSL_CSPRNG)
+ void *ssl;
+#else
SSL *ssl;
+#endif
};
struct imap_buffer {
diff --git a/log-tree.c b/log-tree.c
index 04cef08b83..3758e0d3b8 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -1015,6 +1015,17 @@ static int do_remerge_diff(struct rev_info *opt,
struct strbuf parent1_desc = STRBUF_INIT;
struct strbuf parent2_desc = STRBUF_INIT;
+ /*
+ * Lazily prepare a temporary object directory and rotate it
+ * into the alternative object store list as the primary.
+ */
+ if (opt->remerge_diff && !opt->remerge_objdir) {
+ opt->remerge_objdir = tmp_objdir_create("remerge-diff");
+ if (!opt->remerge_objdir)
+ return error(_("unable to create temporary object directory"));
+ tmp_objdir_replace_primary_odb(opt->remerge_objdir, 1);
+ }
+
/* Setup merge options */
init_ui_merge_options(&o, the_repository);
o.show_rename_progress = 0;
@@ -1051,10 +1062,7 @@ static int do_remerge_diff(struct rev_info *opt,
merge_finalize(&o, &res);
/* Clean up the contents of the temporary object directory */
- if (opt->remerge_objdir)
- tmp_objdir_discard_objects(opt->remerge_objdir);
- else
- BUG("did a remerge diff without remerge_objdir?!?");
+ tmp_objdir_discard_objects(opt->remerge_objdir);
return !opt->loginfo;
}
diff --git a/merge-ll.c b/merge-ll.c
index badb6dea57..8e63071922 100644
--- a/merge-ll.c
+++ b/merge-ll.c
@@ -334,7 +334,7 @@ static int read_merge_config(const char *var, const char *value,
* %X - the revision for our version
* %Y - the revision for their version
*
- * If the file is not named indentically in all versions, then each
+ * If the file is not named identically in all versions, then each
* revision is joined with the corresponding path, separated by a colon.
* The external merge driver should write the results in the
* file named by %A, and signal that it has done with zero exit
diff --git a/merge-ort.c b/merge-ort.c
index 0ed3cd06b1..8b81153e8f 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -1147,7 +1147,7 @@ static void collect_rename_info(struct merge_options *opt,
* Update dir_rename_mask (determines ignore-rename-source validity)
*
* dir_rename_mask helps us keep track of when directory rename
- * detection may be relevant. Basically, whenver a directory is
+ * detection may be relevant. Basically, whenever a directory is
* removed on one side of history, and a file is added to that
* directory on the other side of history, directory rename
* detection is relevant (meaning we have to detect renames for all
@@ -3837,7 +3837,7 @@ static int write_completed_directory(struct merge_options *opt,
* src/moduleB 2
*
* which is used to know that xtract.c & token.txt are from the
- * toplevel dirctory, while umm.c & stuff.h & baz.c are from the
+ * toplevel directory, while umm.c & stuff.h & baz.c are from the
* src/moduleB directory. Again, following the example above,
* once we need to process src/moduleB, then info->offsets is
* updated to
diff --git a/name-hash.c b/name-hash.c
index 3a58ce03d9..95528e3bcd 100644
--- a/name-hash.c
+++ b/name-hash.c
@@ -5,6 +5,9 @@
*
* Copyright (C) 2008 Linus Torvalds
*/
+
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
#include "environment.h"
#include "gettext.h"
diff --git a/notes.c b/notes.c
index da42df282d..f4f18daf07 100644
--- a/notes.c
+++ b/notes.c
@@ -992,15 +992,16 @@ static int notes_display_config(const char *k, const char *v,
return 0;
}
-const char *default_notes_ref(void)
+char *default_notes_ref(struct repository *repo)
{
- const char *notes_ref = NULL;
+ char *notes_ref = NULL;
+
if (!notes_ref)
- notes_ref = getenv(GIT_NOTES_REF_ENVIRONMENT);
+ notes_ref = xstrdup_or_null(getenv(GIT_NOTES_REF_ENVIRONMENT));
if (!notes_ref)
- notes_ref = notes_ref_name; /* value of core.notesRef config */
+ repo_config_get_string(repo, "core.notesref", &notes_ref);
if (!notes_ref)
- notes_ref = GIT_NOTES_DEFAULT_REF;
+ notes_ref = xstrdup(GIT_NOTES_DEFAULT_REF);
return notes_ref;
}
@@ -1010,13 +1011,14 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
struct object_id oid, object_oid;
unsigned short mode;
struct leaf_node root_tree;
+ char *to_free = NULL;
if (!t)
t = &default_notes_tree;
assert(!t->initialized);
if (!notes_ref)
- notes_ref = default_notes_ref();
+ notes_ref = to_free = default_notes_ref(the_repository);
update_ref_namespace(NAMESPACE_NOTES, xstrdup(notes_ref));
if (!combine_notes)
@@ -1033,7 +1035,7 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
if (flags & NOTES_INIT_EMPTY ||
repo_get_oid_treeish(the_repository, notes_ref, &object_oid))
- return;
+ goto out;
if (flags & NOTES_INIT_WRITABLE && refs_read_ref(get_main_ref_store(the_repository), notes_ref, &object_oid))
die("Cannot use notes ref %s", notes_ref);
if (get_tree_entry(the_repository, &object_oid, "", &oid, &mode))
@@ -1043,6 +1045,9 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
oidclr(&root_tree.key_oid, the_repository->hash_algo);
oidcpy(&root_tree.val_oid, &oid);
load_subtree(t, &root_tree, t->root, 0);
+
+out:
+ free(to_free);
}
struct notes_tree **load_notes_trees(struct string_list *refs, int flags)
@@ -1105,7 +1110,7 @@ void load_display_notes(struct display_notes_opt *opt)
if (!opt || opt->use_default_notes > 0 ||
(opt->use_default_notes == -1 && !opt->extra_notes_refs.nr)) {
- string_list_append(&display_notes_refs, default_notes_ref());
+ string_list_append_nodup(&display_notes_refs, default_notes_ref(the_repository));
display_ref_env = getenv(GIT_NOTES_DISPLAY_REF_ENVIRONMENT);
if (display_ref_env) {
string_list_add_refs_from_colon_sep(&display_notes_refs,
diff --git a/notes.h b/notes.h
index 235216944b..6dc6d7b265 100644
--- a/notes.h
+++ b/notes.h
@@ -4,6 +4,7 @@
#include "string-list.h"
struct object_id;
+struct repository;
struct strbuf;
/*
@@ -70,7 +71,7 @@ extern struct notes_tree {
* 3. The value of the core.notesRef config variable, if set
* 4. GIT_NOTES_DEFAULT_REF (i.e. "refs/notes/commits")
*/
-const char *default_notes_ref(void);
+char *default_notes_ref(struct repository *repo);
/*
* Flags controlling behaviour of notes tree initialization
diff --git a/object-file.c b/object-file.c
index c5994202ba..7ac9533ab1 100644
--- a/object-file.c
+++ b/object-file.c
@@ -419,6 +419,39 @@ enum scld_error safe_create_leading_directories_const(const char *path)
return result;
}
+int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)
+{
+ int fd;
+ /*
+ * we let the umask do its job, don't try to be more
+ * restrictive except to remove write permission.
+ */
+ int mode = 0444;
+ git_path_buf(temp_filename, "objects/%s", pattern);
+ fd = git_mkstemp_mode(temp_filename->buf, mode);
+ if (0 <= fd)
+ return fd;
+
+ /* slow path */
+ /* some mkstemp implementations erase temp_filename on failure */
+ git_path_buf(temp_filename, "objects/%s", pattern);
+ safe_create_leading_directories(temp_filename->buf);
+ return xmkstemp_mode(temp_filename->buf, mode);
+}
+
+int odb_pack_keep(const char *name)
+{
+ int fd;
+
+ fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
+ if (0 <= fd)
+ return fd;
+
+ /* slow path */
+ safe_create_leading_directories_const(name);
+ return open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
+}
+
static void fill_loose_path(struct strbuf *buf, const struct object_id *oid)
{
int i;
@@ -2053,7 +2086,7 @@ static int start_loose_object_common(struct strbuf *tmp_file,
else if (errno == EACCES)
return error(_("insufficient permission for adding "
"an object to repository database %s"),
- get_object_directory());
+ repo_get_object_directory(the_repository));
else
return error_errno(
_("unable to create temporary file"));
@@ -2228,7 +2261,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len,
prepare_loose_object_bulk_checkin();
/* Since oid is not determined, save tmp file to odb path. */
- strbuf_addf(&filename, "%s/", get_object_directory());
+ strbuf_addf(&filename, "%s/", repo_get_object_directory(the_repository));
hdrlen = format_object_header(hdr, sizeof(hdr), OBJ_BLOB, len);
/*
@@ -2275,7 +2308,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len,
/*
* Common steps for write_loose_object and stream_loose_object to
- * end writing loose oject:
+ * end writing loose object:
*
* - End the compression of zlib stream.
* - Get the calculated oid.
diff --git a/object-name.c b/object-name.c
index 09c1bd93a3..c892fbe80a 100644
--- a/object-name.c
+++ b/object-name.c
@@ -20,6 +20,7 @@
#include "pretty.h"
#include "object-store-ll.h"
#include "read-cache-ll.h"
+#include "repo-settings.h"
#include "repository.h"
#include "setup.h"
#include "midx.h"
@@ -959,7 +960,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
int fatal = !(flags & GET_OID_QUIETLY);
if (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) {
- if (warn_ambiguous_refs && warn_on_object_refname_ambiguity) {
+ if (repo_settings_get_warn_ambiguous_refs(r) && warn_on_object_refname_ambiguity) {
refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0);
if (refs_found > 0) {
warning(warn_msg, len, str);
@@ -1020,7 +1021,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
if (!refs_found)
return -1;
- if (warn_ambiguous_refs && !(flags & GET_OID_QUIETLY) &&
+ if (repo_settings_get_warn_ambiguous_refs(r) && !(flags & GET_OID_QUIETLY) &&
(refs_found > 1 ||
!get_short_oid(r, str, len, &tmp_oid, GET_OID_QUIETLY)))
warning(warn_msg, len, str);
diff --git a/object-store-ll.h b/object-store-ll.h
index c5f2bb2fc2..53b8e693b1 100644
--- a/object-store-ll.h
+++ b/object-store-ll.h
@@ -232,6 +232,21 @@ struct raw_object_store *raw_object_store_new(void);
void raw_object_store_clear(struct raw_object_store *o);
/*
+ * Create a temporary file rooted in the object database directory, or
+ * die on failure. The filename is taken from "pattern", which should have the
+ * usual "XXXXXX" trailer, and the resulting filename is written into the
+ * "template" buffer. Returns the open descriptor.
+ */
+int odb_mkstemp(struct strbuf *temp_filename, const char *pattern);
+
+/*
+ * Create a pack .keep file named "name" (which should generally be the output
+ * of odb_pack_name). Returns a file descriptor opened for writing, or -1 on
+ * error.
+ */
+int odb_pack_keep(const char *name);
+
+/*
* Put in `buf` the name of the file in the local object database that
* would be used to store a loose object with the specified oid.
*/
diff --git a/pack-write.c b/pack-write.c
index d07f03d0ab..27965672f1 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -12,6 +12,7 @@
#include "pack-objects.h"
#include "pack-revindex.h"
#include "path.h"
+#include "repository.h"
#include "strbuf.h"
void reset_pack_idx_option(struct pack_idx_option *opts)
@@ -473,7 +474,7 @@ char *index_pack_lockfile(int ip_out, int *is_well_formed)
packname[len-1] = 0;
if (skip_prefix(packname, "keep\t", &name))
return xstrfmt("%s/pack/pack-%s.keep",
- get_object_directory(), name);
+ repo_get_object_directory(the_repository), name);
return NULL;
}
if (is_well_formed)
diff --git a/packfile.c b/packfile.c
index cf12a539ea..df4ba67719 100644
--- a/packfile.c
+++ b/packfile.c
@@ -30,7 +30,7 @@ char *odb_pack_name(struct strbuf *buf,
const char *ext)
{
strbuf_reset(buf);
- strbuf_addf(buf, "%s/pack/pack-%s.%s", get_object_directory(),
+ strbuf_addf(buf, "%s/pack/pack-%s.%s", repo_get_object_directory(the_repository),
hash_to_hex(hash), ext);
return buf->buf;
}
diff --git a/pager.c b/pager.c
index 9c24ce6263..40b664f893 100644
--- a/pager.c
+++ b/pager.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
#include "config.h"
#include "editor.h"
@@ -92,7 +94,8 @@ const char *git_pager(int stdout_is_tty)
pager = getenv("GIT_PAGER");
if (!pager) {
if (!pager_program)
- read_early_config(core_pager_config, NULL);
+ read_early_config(the_repository,
+ core_pager_config, NULL);
pager = pager_program;
}
if (!pager)
@@ -298,7 +301,7 @@ int check_pager_config(const char *cmd)
data.want = -1;
data.value = NULL;
- read_early_config(pager_command_config, &data);
+ read_early_config(the_repository, pager_command_config, &data);
if (data.value)
pager_program = data.value;
diff --git a/path.c b/path.c
index a3bf25b7de..93491bab14 100644
--- a/path.c
+++ b/path.c
@@ -2,6 +2,8 @@
* Utilities for paths and pathnames
*/
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
#include "abspath.h"
#include "environment.h"
diff --git a/pathspec.c b/pathspec.c
index fe1f0f41af..0fc6f84a6e 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -495,9 +495,9 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags,
if (!have_git_dir())
die(_("'%s' is outside the directory tree"),
copyfrom);
- hint_path = get_git_work_tree();
+ hint_path = repo_get_work_tree(the_repository);
if (!hint_path)
- hint_path = get_git_dir();
+ hint_path = repo_get_git_dir(the_repository);
die(_("%s: '%s' is outside repository at '%s'"), elt,
copyfrom, absolute_path(hint_path));
}
diff --git a/perl/Git.pm b/perl/Git.pm
index aebfe0c6e0..667152c6c6 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -187,7 +187,7 @@ sub repository {
try {
# Note that "--is-bare-repository" must come first, as
# --git-dir output could contain newlines.
- $out = $search->command([qw(rev-parse --is-bare-repository --git-dir)],
+ $out = $search->command([qw(rev-parse --is-bare-repository --absolute-git-dir)],
STDERR => 0);
} catch Git::Error::Command with {
throw Error::Simple("fatal: not a git repository: $opts{Directory}");
@@ -196,12 +196,12 @@ sub repository {
chomp $out;
my ($bare, $dir) = split /\n/, $out, 2;
- require Cwd;
- if ($bare ne 'true') {
- require File::Spec;
- File::Spec->file_name_is_absolute($dir) or $dir = $opts{Directory} . '/' . $dir;
- $opts{Repository} = Cwd::abs_path($dir);
+ # We know this is an absolute path, because we used
+ # --absolute-git-dir above.
+ $opts{Repository} = $dir;
+ if ($bare ne 'true') {
+ require Cwd;
# If --git-dir went ok, this shouldn't die either.
my $prefix = $search->command_oneline('rev-parse', '--show-prefix');
$dir = Cwd::abs_path($opts{Directory}) . '/';
@@ -214,8 +214,6 @@ sub repository {
$opts{WorkingCopy} = $dir;
$opts{WorkingSubdir} = $prefix;
- } else {
- $opts{Repository} = Cwd::abs_path($dir);
}
delete $opts{Directory};
diff --git a/preload-index.c b/preload-index.c
index 63fd35d64b..7926eb09a6 100644
--- a/preload-index.c
+++ b/preload-index.c
@@ -1,6 +1,9 @@
/*
* Copyright (C) 2008 Linus Torvalds
*/
+
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
#include "pathspec.h"
#include "dir.h"
diff --git a/pretty.c b/pretty.c
index 5e5ae45253..6403e26890 100644
--- a/pretty.c
+++ b/pretty.c
@@ -2205,7 +2205,7 @@ static void strbuf_add_tabexpand(struct strbuf *sb, struct grep_opt *opt,
}
/*
- * pp_handle_indent() prints out the intendation, and
+ * pp_handle_indent() prints out the indentation, and
* the whole line (without the final newline), after
* de-tabifying.
*/
diff --git a/prompt.c b/prompt.c
index 8935fe4dfb..f21c5bf1c7 100644
--- a/prompt.c
+++ b/prompt.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
#include "parse.h"
#include "environment.h"
diff --git a/prune-packed.c b/prune-packed.c
index e54daf740a..2bb99c29df 100644
--- a/prune-packed.c
+++ b/prune-packed.c
@@ -1,10 +1,12 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
-#include "environment.h"
#include "gettext.h"
#include "object-store-ll.h"
#include "packfile.h"
#include "progress.h"
#include "prune-packed.h"
+#include "repository.h"
static struct progress *progress;
@@ -37,7 +39,7 @@ void prune_packed_objects(int opts)
if (opts & PRUNE_PACKED_VERBOSE)
progress = start_delayed_progress(_("Removing duplicate objects"), 256);
- for_each_loose_file_in_objdir(get_object_directory(),
+ for_each_loose_file_in_objdir(repo_get_object_directory(the_repository),
prune_object, NULL, prune_subdir, &opts);
/* Ensure we show 100% before finishing progress */
diff --git a/read-cache-ll.h b/read-cache-ll.h
index e0e39607ef..b5d11d07a8 100644
--- a/read-cache-ll.h
+++ b/read-cache-ll.h
@@ -151,7 +151,7 @@ enum sparse_index_mode {
/*
* The index has already been collapsed to sparse directories
- * whereever possible.
+ * wherever possible.
*/
INDEX_COLLAPSED,
diff --git a/read-cache.c b/read-cache.c
index 4e67dc182e..764fdfec46 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -31,6 +31,7 @@
#include "path.h"
#include "preload-index.h"
#include "read-cache.h"
+#include "repository.h"
#include "resolve-undo.h"
#include "revision.h"
#include "strbuf.h"
@@ -3238,10 +3239,11 @@ static int should_delete_shared_index(const char *shared_index_path)
static int clean_shared_index_files(const char *current_hex)
{
struct dirent *de;
- DIR *dir = opendir(get_git_dir());
+ DIR *dir = opendir(repo_get_git_dir(the_repository));
if (!dir)
- return error_errno(_("unable to open git dir: %s"), get_git_dir());
+ return error_errno(_("unable to open git dir: %s"),
+ repo_get_git_dir(the_repository));
while ((de = readdir(dir)) != NULL) {
const char *sha1_hex;
diff --git a/rebase.c b/rebase.c
index 69a1822da3..9d1ae95978 100644
--- a/rebase.c
+++ b/rebase.c
@@ -11,7 +11,7 @@
* The callers that care if (any) rebase is requested should say
* if (REBASE_TRUE <= rebase_parse_value(string))
*
- * The callers that want to differenciate an unrecognised value and
+ * The callers that want to differentiate an unrecognised value and
* false can do so by treating _INVALID and _FALSE differently.
*/
enum rebase_type rebase_parse_value(const char *value)
diff --git a/ref-filter.c b/ref-filter.c
index b6c6c10127..dd195007ce 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -13,6 +13,7 @@
#include "object-name.h"
#include "object-store-ll.h"
#include "oid-array.h"
+#include "repo-settings.h"
#include "repository.h"
#include "commit.h"
#include "mailmap.h"
@@ -75,11 +76,11 @@ struct refname_atom {
int lstrip, rstrip;
};
-static struct ref_trailer_buf {
+struct ref_trailer_buf {
struct string_list filter_list;
struct strbuf sepbuf;
struct strbuf kvsepbuf;
-} ref_trailer_buf = {STRING_LIST_INIT_NODUP, STRBUF_INIT, STRBUF_INIT};
+};
static struct expand_data {
struct object_id oid;
@@ -201,6 +202,7 @@ static struct used_atom {
enum { C_BARE, C_BODY, C_BODY_DEP, C_LENGTH, C_LINES,
C_SIG, C_SUB, C_SUB_SANITIZE, C_TRAILERS } option;
struct process_trailer_options trailer_opts;
+ struct ref_trailer_buf *trailer_buf;
unsigned int nlines;
} contents;
struct {
@@ -232,7 +234,7 @@ static struct used_atom {
enum { S_BARE, S_GRADE, S_SIGNER, S_KEY,
S_FINGERPRINT, S_PRI_KEY_FP, S_TRUST_LEVEL } option;
} signature;
- const char **describe_args;
+ struct strvec describe_args;
struct refname_atom refname;
char *head;
} u;
@@ -566,21 +568,36 @@ static int trailers_atom_parser(struct ref_format *format UNUSED,
atom->u.contents.trailer_opts.no_divider = 1;
if (arg) {
- const char *argbuf = xstrfmt("%s)", arg);
+ char *argbuf = xstrfmt("%s)", arg);
+ const char *arg = argbuf;
char *invalid_arg = NULL;
+ struct ref_trailer_buf *tb;
+
+ /*
+ * Do not inline these directly into the used_atom struct!
+ * When we parse them in format_set_trailers_options(),
+ * we will make pointer references directly to them,
+ * which will not survive a realloc() of the used_atom list.
+ * They must be allocated in a separate, stable struct.
+ */
+ atom->u.contents.trailer_buf = tb = xmalloc(sizeof(*tb));
+ string_list_init_dup(&tb->filter_list);
+ strbuf_init(&tb->sepbuf, 0);
+ strbuf_init(&tb->kvsepbuf, 0);
if (format_set_trailers_options(&atom->u.contents.trailer_opts,
- &ref_trailer_buf.filter_list,
- &ref_trailer_buf.sepbuf,
- &ref_trailer_buf.kvsepbuf,
- &argbuf, &invalid_arg)) {
+ &tb->filter_list,
+ &tb->sepbuf, &tb->kvsepbuf,
+ &arg, &invalid_arg)) {
if (!invalid_arg)
strbuf_addf(err, _("expected %%(trailers:key=<value>)"));
else
strbuf_addf(err, _("unknown %%(trailers) argument: %s"), invalid_arg);
- free((char *)invalid_arg);
+ free(invalid_arg);
+ free(argbuf);
return -1;
}
+ free(argbuf);
}
atom->u.contents.option = C_TRAILERS;
return 0;
@@ -677,7 +694,7 @@ static int describe_atom_parser(struct ref_format *format UNUSED,
struct used_atom *atom,
const char *arg, struct strbuf *err)
{
- struct strvec args = STRVEC_INIT;
+ strvec_init(&atom->u.describe_args);
for (;;) {
int found = 0;
@@ -686,13 +703,12 @@ static int describe_atom_parser(struct ref_format *format UNUSED,
if (!arg || !*arg)
break;
- found = describe_atom_option_parser(&args, &arg, err);
+ found = describe_atom_option_parser(&atom->u.describe_args, &arg, err);
if (found < 0)
return found;
if (!found)
return err_bad_arg(err, "describe", bad_arg);
}
- atom->u.describe_args = strvec_detach(&args);
return 0;
}
@@ -986,6 +1002,7 @@ struct ref_formatting_stack {
struct ref_formatting_stack *prev;
struct strbuf output;
void (*at_end)(struct ref_formatting_stack **stack);
+ void (*at_end_data_free)(void *data);
void *at_end_data;
};
@@ -1154,6 +1171,8 @@ static void pop_stack_element(struct ref_formatting_stack **stack)
if (prev)
strbuf_addbuf(&prev->output, &current->output);
strbuf_release(&current->output);
+ if (current->at_end_data_free)
+ current->at_end_data_free(current->at_end_data);
free(current);
*stack = prev;
}
@@ -1213,15 +1232,13 @@ static void if_then_else_handler(struct ref_formatting_stack **stack)
}
*stack = cur;
- free(if_then_else);
}
static int if_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state,
struct strbuf *err UNUSED)
{
struct ref_formatting_stack *new_stack;
- struct if_then_else *if_then_else = xcalloc(1,
- sizeof(struct if_then_else));
+ struct if_then_else *if_then_else = xcalloc(1, sizeof(*if_then_else));
if_then_else->str = atomv->atom->u.if_then_else.str;
if_then_else->cmp_status = atomv->atom->u.if_then_else.cmp_status;
@@ -1230,6 +1247,7 @@ static int if_atom_handler(struct atom_value *atomv, struct ref_formatting_state
new_stack = state->stack;
new_stack->at_end = if_then_else_handler;
new_stack->at_end_data = if_then_else;
+ new_stack->at_end_data_free = free;
return 0;
}
@@ -1833,16 +1851,10 @@ static void find_subpos(const char *buf,
size_t *nonsiglen,
const char **sig, size_t *siglen)
{
- struct strbuf payload = STRBUF_INIT;
- struct strbuf signature = STRBUF_INIT;
const char *eol;
const char *end = buf + strlen(buf);
const char *sigstart;
- /* parse signature first; we might not even have a subject line */
- parse_signature(buf, end - buf, &payload, &signature);
- strbuf_release(&payload);
-
/* skip past header until we hit empty line */
while (*buf && *buf != '\n') {
eol = strchrnul(buf, '\n');
@@ -1853,8 +1865,10 @@ static void find_subpos(const char *buf,
/* skip any empty lines */
while (*buf == '\n')
buf++;
- *sig = strbuf_detach(&signature, siglen);
+ /* parse signature first; we might not even have a subject line */
sigstart = buf + parse_signed_buffer(buf, strlen(buf));
+ *sig = sigstart;
+ *siglen = end - *sig;
/* subject is first non-empty line */
*sub = buf;
@@ -1929,7 +1943,7 @@ static void grab_describe_values(struct atom_value *val, int deref,
cmd.git_cmd = 1;
strvec_push(&cmd.args, "describe");
- strvec_pushv(&cmd.args, atom->u.describe_args);
+ strvec_pushv(&cmd.args, atom->u.describe_args.v);
strvec_push(&cmd.args, oid_to_hex(&commit->object.oid));
if (pipe_command(&cmd, NULL, 0, &out, 0, &err, 0) < 0) {
error(_("failed to run 'describe'"));
@@ -2012,16 +2026,23 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct exp
v->s = strbuf_detach(&s, NULL);
} else if (atom->u.contents.option == C_TRAILERS) {
struct strbuf s = STRBUF_INIT;
+ const char *msg;
+ char *to_free = NULL;
+
+ if (siglen)
+ msg = to_free = xmemdupz(subpos, sigpos - subpos);
+ else
+ msg = subpos;
/* Format the trailer info according to the trailer_opts given */
- format_trailers_from_commit(&atom->u.contents.trailer_opts, subpos, &s);
+ format_trailers_from_commit(&atom->u.contents.trailer_opts, msg, &s);
+ free(to_free);
v->s = strbuf_detach(&s, NULL);
} else if (atom->u.contents.option == C_BARE)
v->s = xstrdup(subpos);
}
- free((void *)sigpos);
}
/*
@@ -2160,7 +2181,7 @@ static const char *show_ref(struct refname_atom *atom, const char *refname)
if (atom->option == R_SHORT)
return refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
refname,
- warn_ambiguous_refs);
+ repo_settings_get_warn_ambiguous_refs(the_repository));
else if (atom->option == R_LSTRIP)
return lstrip_ref_components(refname, atom->lstrip);
else if (atom->option == R_RSTRIP)
@@ -2219,7 +2240,7 @@ static void fill_remote_ref_details(struct used_atom *atom, const char *refname,
const char *merge;
merge = remote_ref_for_branch(branch, atom->u.remote_ref.push);
- *s = xstrdup(merge ? merge : "");
+ *s = merge ? merge : xstrdup("");
} else
BUG("unhandled RR_* enum");
}
@@ -2364,7 +2385,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
CALLOC_ARRAY(ref->value, used_atom_cnt);
/**
- * NEEDSWORK: The following code might be unncessary if all codepaths
+ * NEEDSWORK: The following code might be unnecessary if all codepaths
* that call populate_value() populates the symref member of ref_array_item
* like in apply_ref_filter(). Currently pretty_print_ref() is the only codepath
* that calls populate_value() without first populating symref.
@@ -2985,6 +3006,19 @@ void ref_array_clear(struct ref_array *array)
struct used_atom *atom = &used_atom[i];
if (atom->atom_type == ATOM_HEAD)
free(atom->u.head);
+ else if (atom->atom_type == ATOM_DESCRIBE)
+ strvec_clear(&atom->u.describe_args);
+ else if (atom->atom_type == ATOM_TRAILERS ||
+ (atom->atom_type == ATOM_CONTENTS &&
+ atom->u.contents.option == C_TRAILERS)) {
+ struct ref_trailer_buf *tb = atom->u.contents.trailer_buf;
+ if (tb) {
+ string_list_clear(&tb->filter_list, 0);
+ strbuf_release(&tb->sepbuf);
+ strbuf_release(&tb->kvsepbuf);
+ free(tb);
+ }
+ }
free((char *)atom->name);
}
FREE_AND_NULL(used_atom);
@@ -3590,3 +3624,16 @@ void ref_filter_clear(struct ref_filter *filter)
free_commit_list(filter->unreachable_from);
ref_filter_init(filter);
}
+
+void ref_format_init(struct ref_format *format)
+{
+ struct ref_format blank = REF_FORMAT_INIT;
+ memcpy(format, &blank, sizeof(blank));
+}
+
+void ref_format_clear(struct ref_format *format)
+{
+ string_list_clear(&format->bases, 0);
+ string_list_clear(&format->is_base_tips, 0);
+ ref_format_init(format);
+}
diff --git a/ref-filter.h b/ref-filter.h
index e794b8a676..754038ab07 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -221,4 +221,7 @@ void filter_is_base(struct repository *r,
void ref_filter_init(struct ref_filter *filter);
void ref_filter_clear(struct ref_filter *filter);
+void ref_format_init(struct ref_format *format);
+void ref_format_clear(struct ref_format *format);
+
#endif /* REF_FILTER_H */
diff --git a/refs.c b/refs.c
index ceb72d4bd7..5f729ed412 100644
--- a/refs.c
+++ b/refs.c
@@ -24,7 +24,7 @@
#include "submodule.h"
#include "worktree.h"
#include "strvec.h"
-#include "repository.h"
+#include "repo-settings.h"
#include "setup.h"
#include "sigchain.h"
#include "date.h"
@@ -730,7 +730,7 @@ int expand_ref(struct repository *repo, const char *str, int len,
if (r) {
if (!refs_found++)
*ref = xstrdup(r);
- if (!warn_ambiguous_refs)
+ if (!repo_settings_get_warn_ambiguous_refs(repo))
break;
} else if ((flag & REF_ISSYMREF) && strcmp(fullref.buf, "HEAD")) {
warning(_("ignoring dangling symref %s"), fullref.buf);
@@ -775,7 +775,7 @@ int repo_dwim_log(struct repository *r, const char *str, int len,
if (oid)
oidcpy(oid, &hash);
}
- if (!warn_ambiguous_refs)
+ if (!repo_settings_get_warn_ambiguous_refs(r))
break;
}
strbuf_release(&path);
@@ -958,7 +958,8 @@ static char *normalize_reflog_message(const char *msg)
return strbuf_detach(&sb, NULL);
}
-int should_autocreate_reflog(const char *refname)
+int should_autocreate_reflog(enum log_refs_config log_all_ref_updates,
+ const char *refname)
{
switch (log_all_ref_updates) {
case LOG_REFS_ALWAYS:
@@ -1517,6 +1518,19 @@ const char **hidden_refs_to_excludes(const struct strvec *hide_refs)
return hide_refs->v;
}
+const char **get_namespaced_exclude_patterns(const char **exclude_patterns,
+ const char *namespace,
+ struct strvec *out)
+{
+ if (!namespace || !*namespace || !exclude_patterns || !*exclude_patterns)
+ return exclude_patterns;
+
+ for (size_t i = 0; exclude_patterns[i]; i++)
+ strvec_pushf(out, "%s%s", namespace, exclude_patterns[i]);
+
+ return out->v;
+}
+
const char *find_descendant_ref(const char *dirname,
const struct string_list *extras,
const struct string_list *skip)
@@ -1634,11 +1648,19 @@ int refs_for_each_namespaced_ref(struct ref_store *refs,
const char **exclude_patterns,
each_ref_fn fn, void *cb_data)
{
- struct strbuf buf = STRBUF_INIT;
+ struct strvec namespaced_exclude_patterns = STRVEC_INIT;
+ struct strbuf prefix = STRBUF_INIT;
int ret;
- strbuf_addf(&buf, "%srefs/", get_git_namespace());
- ret = do_for_each_ref(refs, buf.buf, exclude_patterns, fn, 0, 0, cb_data);
- strbuf_release(&buf);
+
+ exclude_patterns = get_namespaced_exclude_patterns(exclude_patterns,
+ get_git_namespace(),
+ &namespaced_exclude_patterns);
+
+ strbuf_addf(&prefix, "%srefs/", get_git_namespace());
+ ret = do_for_each_ref(refs, prefix.buf, exclude_patterns, fn, 0, 0, cb_data);
+
+ strvec_clear(&namespaced_exclude_patterns);
+ strbuf_release(&prefix);
return ret;
}
@@ -1719,6 +1741,7 @@ int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store,
const char **exclude_patterns,
each_ref_fn fn, void *cb_data)
{
+ struct strvec namespaced_exclude_patterns = STRVEC_INIT;
struct string_list prefixes = STRING_LIST_INIT_DUP;
struct string_list_item *prefix;
struct strbuf buf = STRBUF_INIT;
@@ -1730,6 +1753,10 @@ int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store,
strbuf_addstr(&buf, namespace);
namespace_len = buf.len;
+ exclude_patterns = get_namespaced_exclude_patterns(exclude_patterns,
+ namespace,
+ &namespaced_exclude_patterns);
+
for_each_string_list_item(prefix, &prefixes) {
strbuf_addstr(&buf, prefix->string);
ret = refs_for_each_fullref_in(ref_store, buf.buf,
@@ -1739,6 +1766,7 @@ int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store,
strbuf_setlen(&buf, namespace_len);
}
+ strvec_clear(&namespaced_exclude_patterns);
string_list_clear(&prefixes, 0);
strbuf_release(&buf);
return ret;
diff --git a/refs.h b/refs.h
index f8b919a138..108dfc93b3 100644
--- a/refs.h
+++ b/refs.h
@@ -3,6 +3,7 @@
#include "commit.h"
#include "repository.h"
+#include "repo-settings.h"
struct fsck_options;
struct object_id;
@@ -16,7 +17,7 @@ enum ref_storage_format ref_storage_format_by_name(const char *name);
const char *ref_storage_format_to_name(enum ref_storage_format ref_storage_format);
/*
- * Resolve a reference, recursively following symbolic refererences.
+ * Resolve a reference, recursively following symbolic references.
*
* Return the name of the non-symbolic reference that ultimately pointed
* at the resolved object name. The return value, if not NULL, is a
@@ -111,7 +112,8 @@ int refs_verify_refname_available(struct ref_store *refs,
int refs_ref_exists(struct ref_store *refs, const char *refname);
-int should_autocreate_reflog(const char *refname);
+int should_autocreate_reflog(enum log_refs_config log_all_ref_updates,
+ const char *refname);
int is_branch(const char *refname);
@@ -488,7 +490,7 @@ int refs_delete_reflog(struct ref_store *refs, const char *refname);
* from UTC. Its absolute value is formed by multiplying the hour
* part by 100 and adding the minute part. For example, 1 hour ahead
* of UTC, CET == "+0100", is represented as positive one hundred (not
- * postiive sixty).
+ * positive sixty).
*
* The msg parameter is a single complete line; a reflog message given
* to refs_delete_ref, refs_update_ref, etc. is returned to the
@@ -859,6 +861,15 @@ int ref_is_hidden(const char *, const char *, const struct strvec *);
*/
const char **hidden_refs_to_excludes(const struct strvec *hide_refs);
+/*
+ * Prefix all exclude patterns with the namespace, if any. This is required
+ * because exclude patterns apply to the stripped reference name, not the full
+ * reference name with the namespace.
+ */
+const char **get_namespaced_exclude_patterns(const char **exclude_patterns,
+ const char *namespace,
+ struct strvec *out);
+
/* Is this a per-worktree ref living in the refs/ namespace? */
int is_per_worktree_ref(const char *refname);
@@ -986,7 +997,7 @@ struct ref_store *get_worktree_ref_store(const struct worktree *wt);
/*
* Some of the names specified by refs have special meaning to Git.
- * Organize these namespaces in a comon 'ref_namespace' array for
+ * Organize these namespaces in a common 'ref_namespace' array for
* reference from multiple places in the codebase.
*/
diff --git a/refs/files-backend.c b/refs/files-backend.c
index c7f3f4e591..0824c0b8a9 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1,4 +1,7 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "../git-compat-util.h"
+#include "../config.h"
#include "../copy.h"
#include "../environment.h"
#include "../gettext.h"
@@ -6,6 +9,7 @@
#include "../hex.h"
#include "../fsck.h"
#include "../refs.h"
+#include "../repo-settings.h"
#include "refs-internal.h"
#include "ref-cache.h"
#include "packed-backend.h"
@@ -72,6 +76,8 @@ struct files_ref_store {
unsigned int store_flags;
char *gitcommondir;
+ enum log_refs_config log_all_ref_updates;
+ int prefer_symlink_refs;
struct ref_cache *loose;
@@ -104,6 +110,8 @@ static struct ref_store *files_ref_store_init(struct repository *repo,
refs->gitcommondir = strbuf_detach(&sb, NULL);
refs->packed_ref_store =
packed_ref_store_init(repo, refs->gitcommondir, flags);
+ refs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);
+ repo_config_get_bool(repo, "core.prefersymlinkrefs", &refs->prefer_symlink_refs);
chdir_notify_reparent("files-backend $GIT_DIR", &refs->base.gitdir);
chdir_notify_reparent("files-backend $GIT_COMMONDIR",
@@ -1506,6 +1514,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs,
static int commit_ref_update(struct files_ref_store *refs,
struct ref_lock *lock,
const struct object_id *oid, const char *logmsg,
+ int flags,
struct strbuf *err);
/*
@@ -1649,7 +1658,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
oidcpy(&lock->old_oid, &orig_oid);
if (write_ref_to_lockfile(refs, lock, &orig_oid, 0, &err) ||
- commit_ref_update(refs, lock, &orig_oid, logmsg, &err)) {
+ commit_ref_update(refs, lock, &orig_oid, logmsg, 0, &err)) {
error("unable to write current sha1 into %s: %s", newrefname, err.buf);
strbuf_release(&err);
goto rollback;
@@ -1666,14 +1675,11 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
goto rollbacklog;
}
- flag = log_all_ref_updates;
- log_all_ref_updates = LOG_REFS_NONE;
if (write_ref_to_lockfile(refs, lock, &orig_oid, 0, &err) ||
- commit_ref_update(refs, lock, &orig_oid, NULL, &err)) {
+ commit_ref_update(refs, lock, &orig_oid, NULL, REF_SKIP_CREATE_REFLOG, &err)) {
error("unable to write current sha1 into %s: %s", oldrefname, err.buf);
strbuf_release(&err);
}
- log_all_ref_updates = flag;
rollbacklog:
if (logmoved && rename(sb_newref.buf, sb_oldref.buf))
@@ -1768,13 +1774,17 @@ static int log_ref_setup(struct files_ref_store *refs,
const char *refname, int force_create,
int *logfd, struct strbuf *err)
{
+ enum log_refs_config log_refs_cfg = refs->log_all_ref_updates;
struct strbuf logfile_sb = STRBUF_INIT;
char *logfile;
+ if (log_refs_cfg == LOG_REFS_UNSET)
+ log_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;
+
files_reflog_path(refs, &logfile_sb, refname);
logfile = strbuf_detach(&logfile_sb, NULL);
- if (force_create || should_autocreate_reflog(refname)) {
+ if (force_create || should_autocreate_reflog(log_refs_cfg, refname)) {
if (raceproof_create_file(logfile, open_or_create_logfile, logfd)) {
if (errno == ENOENT)
strbuf_addf(err, "unable to create directory for '%s': "
@@ -1863,9 +1873,6 @@ static int files_log_ref_write(struct files_ref_store *refs,
if (flags & REF_SKIP_CREATE_REFLOG)
return 0;
- if (log_all_ref_updates == LOG_REFS_UNSET)
- log_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;
-
result = log_ref_setup(refs, refname,
flags & REF_FORCE_CREATE_REFLOG,
&logfd, err);
@@ -1954,6 +1961,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs,
static int commit_ref_update(struct files_ref_store *refs,
struct ref_lock *lock,
const struct object_id *oid, const char *logmsg,
+ int flags,
struct strbuf *err)
{
files_assert_main_repository(refs, "commit_ref_update");
@@ -1961,7 +1969,7 @@ static int commit_ref_update(struct files_ref_store *refs,
clear_loose_ref_cache(refs);
if (files_log_ref_write(refs, lock->ref_name,
&lock->old_oid, oid,
- logmsg, 0, err)) {
+ logmsg, flags, err)) {
char *old_msg = strbuf_detach(err, NULL);
strbuf_addf(err, "cannot update the ref '%s': %s",
lock->ref_name, old_msg);
@@ -1994,7 +2002,7 @@ static int commit_ref_update(struct files_ref_store *refs,
struct strbuf log_err = STRBUF_INIT;
if (files_log_ref_write(refs, "HEAD",
&lock->old_oid, oid,
- logmsg, 0, &log_err)) {
+ logmsg, flags, &log_err)) {
error("%s", log_err.buf);
strbuf_release(&log_err);
}
@@ -3005,7 +3013,7 @@ static int files_transaction_finish(struct ref_store *ref_store,
* We try creating a symlink, if that succeeds we continue to the
* next update. If not, we try and create a regular symref.
*/
- if (update->new_target && prefer_symlink_refs)
+ if (update->new_target && refs->prefer_symlink_refs)
if (!create_ref_symlink(lock, update->new_target))
continue;
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index 1c4b19e737..3c96fbf66f 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -19,8 +19,10 @@
#include "../reftable/reftable-record.h"
#include "../reftable/reftable-error.h"
#include "../reftable/reftable-iterator.h"
+#include "../repo-settings.h"
#include "../setup.h"
#include "../strmap.h"
+#include "../trace2.h"
#include "parse.h"
#include "refs-internal.h"
@@ -51,6 +53,7 @@ struct reftable_ref_store {
struct reftable_write_options write_options;
unsigned int store_flags;
+ enum log_refs_config log_all_ref_updates;
int err;
};
@@ -156,22 +159,23 @@ static struct reftable_stack *stack_for(struct reftable_ref_store *store,
}
}
-static int should_write_log(struct ref_store *refs, const char *refname)
+static int should_write_log(struct reftable_ref_store *refs, const char *refname)
{
- if (log_all_ref_updates == LOG_REFS_UNSET)
- log_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;
+ enum log_refs_config log_refs_cfg = refs->log_all_ref_updates;
+ if (log_refs_cfg == LOG_REFS_UNSET)
+ log_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;
- switch (log_all_ref_updates) {
+ switch (log_refs_cfg) {
case LOG_REFS_NONE:
- return refs_reflog_exists(refs, refname);
+ return refs_reflog_exists(&refs->base, refname);
case LOG_REFS_ALWAYS:
return 1;
case LOG_REFS_NORMAL:
- if (should_autocreate_reflog(refname))
+ if (should_autocreate_reflog(log_refs_cfg, refname))
return 1;
- return refs_reflog_exists(refs, refname);
+ return refs_reflog_exists(&refs->base, refname);
default:
- BUG("unhandled core.logAllRefUpdates value %d", log_all_ref_updates);
+ BUG("unhandled core.logAllRefUpdates value %d", log_refs_cfg);
}
}
@@ -256,6 +260,13 @@ static int reftable_be_config(const char *var, const char *value,
if (factor > UINT8_MAX)
die("reftable geometric factor cannot exceed %u", (unsigned)UINT8_MAX);
opts->auto_compaction_factor = factor;
+ } else if (!strcmp(var, "reftable.locktimeout")) {
+ int64_t lock_timeout = git_config_int64(var, value, ctx->kvi);
+ if (lock_timeout > LONG_MAX)
+ die("reftable lock timeout cannot exceed %"PRIdMAX, (intmax_t)LONG_MAX);
+ if (lock_timeout < 0 && lock_timeout != -1)
+ die("reftable lock timeout does not support negative values other than -1");
+ opts->lock_timeout_ms = lock_timeout;
}
return 0;
@@ -276,11 +287,13 @@ static struct ref_store *reftable_be_init(struct repository *repo,
base_ref_store_init(&refs->base, repo, gitdir, &refs_be_reftable);
strmap_init(&refs->worktree_stacks);
refs->store_flags = store_flags;
+ refs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);
refs->write_options.hash_id = repo->hash_algo->format_id;
refs->write_options.default_permissions = calc_shared_perm(0666 & ~mask);
refs->write_options.disable_auto_compact =
!git_env_bool("GIT_TEST_REFTABLE_AUTOCOMPACTION", 1);
+ refs->write_options.lock_timeout_ms = 100;
git_config(reftable_be_config, &refs->write_options);
@@ -447,10 +460,81 @@ struct reftable_ref_iterator {
const char *prefix;
size_t prefix_len;
+ char **exclude_patterns;
+ size_t exclude_patterns_index;
+ size_t exclude_patterns_strlen;
unsigned int flags;
int err;
};
+/*
+ * Handle exclude patterns. Returns either `1`, which tells the caller that the
+ * current reference shall not be shown. Or `0`, which indicates that it should
+ * be shown.
+ */
+static int should_exclude_current_ref(struct reftable_ref_iterator *iter)
+{
+ while (iter->exclude_patterns[iter->exclude_patterns_index]) {
+ const char *pattern = iter->exclude_patterns[iter->exclude_patterns_index];
+ char *ref_after_pattern;
+ int cmp;
+
+ /*
+ * Lazily cache the pattern length so that we don't have to
+ * recompute it every time this function is called.
+ */
+ if (!iter->exclude_patterns_strlen)
+ iter->exclude_patterns_strlen = strlen(pattern);
+
+ /*
+ * When the reference name is lexicographically bigger than the
+ * current exclude pattern we know that it won't ever match any
+ * of the following references, either. We thus advance to the
+ * next pattern and re-check whether it matches.
+ *
+ * Otherwise, if it's smaller, then we do not have a match and
+ * thus want to show the current reference.
+ */
+ cmp = strncmp(iter->ref.refname, pattern,
+ iter->exclude_patterns_strlen);
+ if (cmp > 0) {
+ iter->exclude_patterns_index++;
+ iter->exclude_patterns_strlen = 0;
+ continue;
+ }
+ if (cmp < 0)
+ return 0;
+
+ /*
+ * The reference shares a prefix with the exclude pattern and
+ * shall thus be omitted. We skip all references that match the
+ * pattern by seeking to the first reference after the block of
+ * matches.
+ *
+ * This is done by appending the highest possible character to
+ * the pattern. Consequently, all references that have the
+ * pattern as prefix and whose suffix starts with anything in
+ * the range [0x00, 0xfe] are skipped. And given that 0xff is a
+ * non-printable character that shouldn't ever be in a ref name,
+ * we'd not yield any such record, either.
+ *
+ * Note that the seeked-to reference may also be excluded. This
+ * is not handled here though, but the caller is expected to
+ * loop and re-verify the next reference for us.
+ */
+ ref_after_pattern = xstrfmt("%s%c", pattern, 0xff);
+ iter->err = reftable_iterator_seek_ref(&iter->iter, ref_after_pattern);
+ iter->exclude_patterns_index++;
+ iter->exclude_patterns_strlen = 0;
+ trace2_counter_add(TRACE2_COUNTER_ID_REFTABLE_RESEEKS, 1);
+
+ free(ref_after_pattern);
+ return 1;
+ }
+
+ return 0;
+}
+
static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
{
struct reftable_ref_iterator *iter =
@@ -481,6 +565,9 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
break;
}
+ if (iter->exclude_patterns && should_exclude_current_ref(iter))
+ continue;
+
if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
parse_worktree_ref(iter->ref.refname, NULL, NULL, NULL) !=
REF_WORKTREE_CURRENT)
@@ -570,6 +657,11 @@ static int reftable_ref_iterator_abort(struct ref_iterator *ref_iterator)
(struct reftable_ref_iterator *)ref_iterator;
reftable_ref_record_release(&iter->ref);
reftable_iterator_destroy(&iter->iter);
+ if (iter->exclude_patterns) {
+ for (size_t i = 0; iter->exclude_patterns[i]; i++)
+ free(iter->exclude_patterns[i]);
+ free(iter->exclude_patterns);
+ }
free(iter);
return ITER_DONE;
}
@@ -580,9 +672,53 @@ static struct ref_iterator_vtable reftable_ref_iterator_vtable = {
.abort = reftable_ref_iterator_abort
};
+static int qsort_strcmp(const void *va, const void *vb)
+{
+ const char *a = *(const char **)va;
+ const char *b = *(const char **)vb;
+ return strcmp(a, b);
+}
+
+static char **filter_exclude_patterns(const char **exclude_patterns)
+{
+ size_t filtered_size = 0, filtered_alloc = 0;
+ char **filtered = NULL;
+
+ if (!exclude_patterns)
+ return NULL;
+
+ for (size_t i = 0; ; i++) {
+ const char *exclude_pattern = exclude_patterns[i];
+ int has_glob = 0;
+
+ if (!exclude_pattern)
+ break;
+
+ for (const char *p = exclude_pattern; *p; p++) {
+ has_glob = is_glob_special(*p);
+ if (has_glob)
+ break;
+ }
+ if (has_glob)
+ continue;
+
+ ALLOC_GROW(filtered, filtered_size + 1, filtered_alloc);
+ filtered[filtered_size++] = xstrdup(exclude_pattern);
+ }
+
+ if (filtered_size) {
+ QSORT(filtered, filtered_size, qsort_strcmp);
+ ALLOC_GROW(filtered, filtered_size + 1, filtered_alloc);
+ filtered[filtered_size++] = NULL;
+ }
+
+ return filtered;
+}
+
static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_store *refs,
struct reftable_stack *stack,
const char *prefix,
+ const char **exclude_patterns,
int flags)
{
struct reftable_ref_iterator *iter;
@@ -595,6 +731,7 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_
iter->base.oid = &iter->oid;
iter->flags = flags;
iter->refs = refs;
+ iter->exclude_patterns = filter_exclude_patterns(exclude_patterns);
ret = refs->err;
if (ret)
@@ -616,7 +753,7 @@ done:
static struct ref_iterator *reftable_be_iterator_begin(struct ref_store *ref_store,
const char *prefix,
- const char **exclude_patterns UNUSED,
+ const char **exclude_patterns,
unsigned int flags)
{
struct reftable_ref_iterator *main_iter, *worktree_iter;
@@ -627,7 +764,8 @@ static struct ref_iterator *reftable_be_iterator_begin(struct ref_store *ref_sto
required_flags |= REF_STORE_ODB;
refs = reftable_be_downcast(ref_store, required_flags, "ref_iterator_begin");
- main_iter = ref_iterator_for_stack(refs, refs->main_stack, prefix, flags);
+ main_iter = ref_iterator_for_stack(refs, refs->main_stack, prefix,
+ exclude_patterns, flags);
/*
* The worktree stack is only set when we're in an actual worktree
@@ -641,7 +779,8 @@ static struct ref_iterator *reftable_be_iterator_begin(struct ref_store *ref_sto
* Otherwise we merge both the common and the per-worktree refs into a
* single iterator.
*/
- worktree_iter = ref_iterator_for_stack(refs, refs->worktree_stack, prefix, flags);
+ worktree_iter = ref_iterator_for_stack(refs, refs->worktree_stack, prefix,
+ exclude_patterns, flags);
return merge_ref_iterator_begin(&worktree_iter->base, &main_iter->base,
ref_iterator_select, NULL);
}
@@ -762,7 +901,8 @@ static int prepare_transaction_update(struct write_transaction_table_arg **out,
if (ret)
return ret;
- ret = reftable_stack_new_addition(&addition, stack);
+ ret = reftable_stack_new_addition(&addition, stack,
+ REFTABLE_STACK_NEW_ADDITION_RELOAD);
if (ret) {
if (ret == REFTABLE_LOCK_ERROR)
strbuf_addstr(err, "cannot lock references");
@@ -1218,7 +1358,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
} else if (!(u->flags & REF_SKIP_CREATE_REFLOG) &&
(u->flags & REF_HAVE_NEW) &&
(u->flags & REF_FORCE_CREATE_REFLOG ||
- should_write_log(&arg->refs->base, u->refname))) {
+ should_write_log(arg->refs, u->refname))) {
struct reftable_log_record *log;
int create_reflog = 1;
@@ -2199,7 +2339,7 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
if (ret < 0)
goto done;
- ret = reftable_stack_new_addition(&add, stack);
+ ret = reftable_stack_new_addition(&add, stack, 0);
if (ret < 0)
goto done;
diff --git a/reftable/reader.c b/reftable/reader.c
index f877099087..6494ce2e32 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -328,6 +328,7 @@ static int table_iter_seek_to(struct table_iter *ti, uint64_t off, uint8_t typ)
ti->typ = block_reader_type(&ti->br);
ti->block_off = off;
block_iter_seek_start(&ti->bi, &ti->br);
+ ti->is_finished = 0;
return 0;
}
diff --git a/reftable/reftable-stack.h b/reftable/reftable-stack.h
index f4f8cabc7f..6370fe45dd 100644
--- a/reftable/reftable-stack.h
+++ b/reftable/reftable-stack.h
@@ -37,12 +37,21 @@ uint64_t reftable_stack_next_update_index(struct reftable_stack *st);
/* holds a transaction to add tables at the top of a stack. */
struct reftable_addition;
+enum {
+ /*
+ * Reload the stack when the stack is out-of-date after locking it.
+ */
+ REFTABLE_STACK_NEW_ADDITION_RELOAD = (1 << 0),
+};
+
/*
* returns a new transaction to add reftables to the given stack. As a side
- * effect, the ref database is locked.
+ * effect, the ref database is locked. Accepts REFTABLE_STACK_NEW_ADDITION_*
+ * flags.
*/
int reftable_stack_new_addition(struct reftable_addition **dest,
- struct reftable_stack *st);
+ struct reftable_stack *st,
+ unsigned int flags);
/* Adds a reftable to transaction. */
int reftable_addition_add(struct reftable_addition *add,
diff --git a/reftable/reftable-tests.h b/reftable/reftable-tests.h
deleted file mode 100644
index 5d725c69c7..0000000000
--- a/reftable/reftable-tests.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
-Copyright 2020 Google LLC
-
-Use of this source code is governed by a BSD-style
-license that can be found in the LICENSE file or at
-https://developers.google.com/open-source/licenses/bsd
-*/
-
-#ifndef REFTABLE_TESTS_H
-#define REFTABLE_TESTS_H
-
-int stack_test_main(int argc, const char **argv);
-
-#endif
diff --git a/reftable/reftable-writer.h b/reftable/reftable-writer.h
index 189b1f4144..f5e25cfda1 100644
--- a/reftable/reftable-writer.h
+++ b/reftable/reftable-writer.h
@@ -51,6 +51,17 @@ struct reftable_write_options {
* tables to compact. Defaults to 2 if unset.
*/
uint8_t auto_compaction_factor;
+
+ /*
+ * The number of milliseconds to wait when trying to lock "tables.list".
+ * Note that this does not apply to locking individual tables, as these
+ * should only ever be locked when already holding the "tables.list"
+ * lock.
+ *
+ * Passing 0 will fail immediately when the file is locked, passing a
+ * negative value will cause us to block indefinitely.
+ */
+ long lock_timeout_ms;
};
/* reftable_block_stats holds statistics for a single block type */
diff --git a/reftable/stack.c b/reftable/stack.c
index ce0a35216b..84cf37a2ad 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -596,15 +596,18 @@ struct reftable_addition {
#define REFTABLE_ADDITION_INIT {0}
static int reftable_stack_init_addition(struct reftable_addition *add,
- struct reftable_stack *st)
+ struct reftable_stack *st,
+ unsigned int flags)
{
struct strbuf lock_file_name = STRBUF_INIT;
int err;
add->stack = st;
- err = hold_lock_file_for_update(&add->tables_list_lock, st->list_file,
- LOCK_NO_DEREF);
+ err = hold_lock_file_for_update_timeout(&add->tables_list_lock,
+ st->list_file,
+ LOCK_NO_DEREF,
+ st->opts.lock_timeout_ms);
if (err < 0) {
if (errno == EEXIST) {
err = REFTABLE_LOCK_ERROR;
@@ -624,6 +627,11 @@ static int reftable_stack_init_addition(struct reftable_addition *add,
err = stack_uptodate(st);
if (err < 0)
goto done;
+ if (err > 0 && flags & REFTABLE_STACK_NEW_ADDITION_RELOAD) {
+ err = reftable_stack_reload_maybe_reuse(add->stack, 1);
+ if (err)
+ goto done;
+ }
if (err > 0) {
err = REFTABLE_OUTDATED_ERROR;
goto done;
@@ -631,9 +639,8 @@ static int reftable_stack_init_addition(struct reftable_addition *add,
add->next_update_index = reftable_stack_next_update_index(st);
done:
- if (err) {
+ if (err)
reftable_addition_close(add);
- }
strbuf_release(&lock_file_name);
return err;
}
@@ -737,13 +744,14 @@ done:
}
int reftable_stack_new_addition(struct reftable_addition **dest,
- struct reftable_stack *st)
+ struct reftable_stack *st,
+ unsigned int flags)
{
int err = 0;
struct reftable_addition empty = REFTABLE_ADDITION_INIT;
REFTABLE_CALLOC_ARRAY(*dest, 1);
**dest = empty;
- err = reftable_stack_init_addition(*dest, st);
+ err = reftable_stack_init_addition(*dest, st, flags);
if (err) {
reftable_free(*dest);
*dest = NULL;
@@ -757,7 +765,7 @@ static int stack_try_add(struct reftable_stack *st,
void *arg)
{
struct reftable_addition add = REFTABLE_ADDITION_INIT;
- int err = reftable_stack_init_addition(&add, st);
+ int err = reftable_stack_init_addition(&add, st, 0);
if (err < 0)
goto done;
@@ -1056,8 +1064,10 @@ static int stack_compact_range(struct reftable_stack *st,
* Hold the lock so that we can read "tables.list" and lock all tables
* which are part of the user-specified range.
*/
- err = hold_lock_file_for_update(&tables_list_lock, st->list_file,
- LOCK_NO_DEREF);
+ err = hold_lock_file_for_update_timeout(&tables_list_lock,
+ st->list_file,
+ LOCK_NO_DEREF,
+ st->opts.lock_timeout_ms);
if (err < 0) {
if (errno == EEXIST)
err = REFTABLE_LOCK_ERROR;
@@ -1156,8 +1166,10 @@ static int stack_compact_range(struct reftable_stack *st,
* "tables.list". We'll then replace the compacted range of tables with
* the new table.
*/
- err = hold_lock_file_for_update(&tables_list_lock, st->list_file,
- LOCK_NO_DEREF);
+ err = hold_lock_file_for_update_timeout(&tables_list_lock,
+ st->list_file,
+ LOCK_NO_DEREF,
+ st->opts.lock_timeout_ms);
if (err < 0) {
if (errno == EEXIST)
err = REFTABLE_LOCK_ERROR;
@@ -1602,7 +1614,7 @@ static int reftable_stack_clean_locked(struct reftable_stack *st)
int reftable_stack_clean(struct reftable_stack *st)
{
struct reftable_addition *add = NULL;
- int err = reftable_stack_new_addition(&add, st);
+ int err = reftable_stack_new_addition(&add, st, 0);
if (err < 0) {
goto done;
}
diff --git a/reftable/test_framework.c b/reftable/test_framework.c
deleted file mode 100644
index a07fec5d84..0000000000
--- a/reftable/test_framework.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-Copyright 2020 Google LLC
-
-Use of this source code is governed by a BSD-style
-license that can be found in the LICENSE file or at
-https://developers.google.com/open-source/licenses/bsd
-*/
-
-#include "system.h"
-#include "test_framework.h"
-
-
-void set_test_hash(uint8_t *p, int i)
-{
- memset(p, (uint8_t)i, hash_size(GIT_SHA1_FORMAT_ID));
-}
-
-ssize_t strbuf_add_void(void *b, const void *data, size_t sz)
-{
- strbuf_add(b, data, sz);
- return sz;
-}
-
-int noop_flush(void *arg UNUSED)
-{
- return 0;
-}
diff --git a/reftable/test_framework.h b/reftable/test_framework.h
deleted file mode 100644
index 687390f9c2..0000000000
--- a/reftable/test_framework.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-Copyright 2020 Google LLC
-
-Use of this source code is governed by a BSD-style
-license that can be found in the LICENSE file or at
-https://developers.google.com/open-source/licenses/bsd
-*/
-
-#ifndef TEST_FRAMEWORK_H
-#define TEST_FRAMEWORK_H
-
-#include "system.h"
-#include "reftable-error.h"
-
-#define EXPECT_ERR(c) \
- do { \
- if (c != 0) { \
- fflush(stderr); \
- fflush(stdout); \
- fprintf(stderr, "%s: %d: error == %d (%s), want 0\n", \
- __FILE__, __LINE__, c, reftable_error_str(c)); \
- abort(); \
- } \
- } while (0)
-
-#define EXPECT_STREQ(a, b) \
- do { \
- if (strcmp(a, b)) { \
- fflush(stderr); \
- fflush(stdout); \
- fprintf(stderr, "%s:%d: %s (%s) != %s (%s)\n", __FILE__, \
- __LINE__, #a, a, #b, b); \
- abort(); \
- } \
- } while (0)
-
-#define EXPECT(c) \
- do { \
- if (!(c)) { \
- fflush(stderr); \
- fflush(stdout); \
- fprintf(stderr, "%s: %d: failed assertion %s\n", __FILE__, \
- __LINE__, #c); \
- abort(); \
- } \
- } while (0)
-
-#define RUN_TEST(f) \
- fprintf(stderr, "running %s\n", #f); \
- fflush(stderr); \
- f();
-
-void set_test_hash(uint8_t *p, int i);
-
-/* Like strbuf_add, but suitable for passing to reftable_new_writer
- */
-ssize_t strbuf_add_void(void *b, const void *data, size_t sz);
-
-int noop_flush(void *);
-
-#endif
diff --git a/remote.c b/remote.c
index bff54046b2..390a03c264 100644
--- a/remote.c
+++ b/remote.c
@@ -632,7 +632,7 @@ const char *pushremote_for_branch(struct branch *branch, int *explicit)
static struct remote *remotes_remote_get(struct remote_state *remote_state,
const char *name);
-const char *remote_ref_for_branch(struct branch *branch, int for_push)
+char *remote_ref_for_branch(struct branch *branch, int for_push)
{
read_config(the_repository, 0);
die_on_missing_branch(the_repository, branch);
@@ -640,11 +640,11 @@ const char *remote_ref_for_branch(struct branch *branch, int for_push)
if (branch) {
if (!for_push) {
if (branch->merge_nr) {
- return branch->merge_name[0];
+ return xstrdup(branch->merge_name[0]);
}
} else {
- const char *dst,
- *remote_name = remotes_pushremote_for_branch(
+ char *dst;
+ const char *remote_name = remotes_pushremote_for_branch(
the_repository->remote_state, branch,
NULL);
struct remote *remote = remotes_remote_get(
diff --git a/remote.h b/remote.h
index b901b56746..a58713f20a 100644
--- a/remote.h
+++ b/remote.h
@@ -329,7 +329,7 @@ struct branch {
struct branch *branch_get(const char *name);
const char *remote_for_branch(struct branch *branch, int *explicit);
const char *pushremote_for_branch(struct branch *branch, int *explicit);
-const char *remote_ref_for_branch(struct branch *branch, int for_push);
+char *remote_ref_for_branch(struct branch *branch, int for_push);
/* returns true if the given branch has merge configuration given. */
int branch_has_merge_config(struct branch *branch);
diff --git a/repo-settings.c b/repo-settings.c
index 2b4e68731b..4699b4b365 100644
--- a/repo-settings.c
+++ b/repo-settings.c
@@ -1,5 +1,6 @@
#include "git-compat-util.h"
#include "config.h"
+#include "repo-settings.h"
#include "repository.h"
#include "midx.h"
@@ -19,6 +20,7 @@ static void repo_cfg_int(struct repository *r, const char *key, int *dest,
void prepare_repo_settings(struct repository *r)
{
+ const struct repo_settings defaults = REPO_SETTINGS_INIT;
int experimental;
int value;
const char *strval;
@@ -28,13 +30,11 @@ void prepare_repo_settings(struct repository *r)
if (!r->gitdir)
BUG("Cannot add settings for uninitialized repository");
- if (r->settings.initialized++)
+ if (r->settings.initialized)
return;
- /* Defaults */
- r->settings.index_version = -1;
- r->settings.core_untracked_cache = UNTRACKED_CACHE_KEEP;
- r->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE;
+ memcpy(&r->settings, &defaults, sizeof(defaults));
+ r->settings.initialized++;
/* Booleans config or default, cascades to other settings */
repo_cfg_bool(r, "feature.manyfiles", &manyfiles, 0);
@@ -124,3 +124,28 @@ void prepare_repo_settings(struct repository *r)
*/
r->settings.command_requires_full_index = 1;
}
+
+enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo)
+{
+ const char *value;
+
+ if (!repo_config_get_string_tmp(repo, "core.logallrefupdates", &value)) {
+ if (value && !strcasecmp(value, "always"))
+ return LOG_REFS_ALWAYS;
+ else if (git_config_bool("core.logallrefupdates", value))
+ return LOG_REFS_NORMAL;
+ else
+ return LOG_REFS_NONE;
+ }
+
+ return LOG_REFS_UNSET;
+}
+
+int repo_settings_get_warn_ambiguous_refs(struct repository *repo)
+{
+ prepare_repo_settings(repo);
+ if (repo->settings.warn_ambiguous_refs < 0)
+ repo_cfg_bool(repo, "core.warnambiguousrefs",
+ &repo->settings.warn_ambiguous_refs, 1);
+ return repo->settings.warn_ambiguous_refs;
+}
diff --git a/repo-settings.h b/repo-settings.h
new file mode 100644
index 0000000000..51d6156a11
--- /dev/null
+++ b/repo-settings.h
@@ -0,0 +1,75 @@
+#ifndef REPO_SETTINGS_H
+#define REPO_SETTINGS_H
+
+struct fsmonitor_settings;
+struct repository;
+
+enum untracked_cache_setting {
+ UNTRACKED_CACHE_KEEP,
+ UNTRACKED_CACHE_REMOVE,
+ UNTRACKED_CACHE_WRITE,
+};
+
+enum fetch_negotiation_setting {
+ FETCH_NEGOTIATION_CONSECUTIVE,
+ FETCH_NEGOTIATION_SKIPPING,
+ FETCH_NEGOTIATION_NOOP,
+};
+
+enum log_refs_config {
+ LOG_REFS_UNSET = -1,
+ LOG_REFS_NONE = 0,
+ LOG_REFS_NORMAL,
+ LOG_REFS_ALWAYS
+};
+
+struct repo_settings {
+ int initialized;
+
+ int core_commit_graph;
+ int commit_graph_generation_version;
+ int commit_graph_changed_paths_version;
+ int gc_write_commit_graph;
+ int fetch_write_commit_graph;
+ int command_requires_full_index;
+ int sparse_index;
+ int pack_read_reverse_index;
+ int pack_use_bitmap_boundary_traversal;
+ int pack_use_multi_pack_reuse;
+
+ /*
+ * Does this repository have core.useReplaceRefs=true (on by
+ * default)? This provides a repository-scoped version of this
+ * config, though it could be disabled process-wide via some Git
+ * builtins or the --no-replace-objects option. See
+ * replace_refs_enabled() for more details.
+ */
+ int read_replace_refs;
+
+ struct fsmonitor_settings *fsmonitor; /* lazily loaded */
+
+ int index_version;
+ int index_skip_hash;
+ enum untracked_cache_setting core_untracked_cache;
+
+ int pack_use_sparse;
+ enum fetch_negotiation_setting fetch_negotiation_algorithm;
+
+ int core_multi_pack_index;
+ int warn_ambiguous_refs; /* lazily loaded via accessor */
+};
+#define REPO_SETTINGS_INIT { \
+ .index_version = -1, \
+ .core_untracked_cache = UNTRACKED_CACHE_KEEP, \
+ .fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE, \
+ .warn_ambiguous_refs = -1, \
+}
+
+void prepare_repo_settings(struct repository *r);
+
+/* Read the value for "core.logAllRefUpdates". */
+enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo);
+/* Read the value for "core.warnAmbiguousRefs". */
+int repo_settings_get_warn_ambiguous_refs(struct repository *repo);
+
+#endif /* REPO_SETTINGS_H */
diff --git a/repository.c b/repository.c
index e6fc2c6aa9..f988b8ae68 100644
--- a/repository.c
+++ b/repository.c
@@ -91,6 +91,46 @@ static void expand_base_dir(char **out, const char *in,
*out = xstrfmt("%s/%s", base_dir, def_in);
}
+const char *repo_get_git_dir(struct repository *repo)
+{
+ if (!repo->gitdir)
+ BUG("repository hasn't been set up");
+ return repo->gitdir;
+}
+
+const char *repo_get_common_dir(struct repository *repo)
+{
+ if (!repo->commondir)
+ BUG("repository hasn't been set up");
+ return repo->commondir;
+}
+
+const char *repo_get_object_directory(struct repository *repo)
+{
+ if (!repo->objects->odb)
+ BUG("repository hasn't been set up");
+ return repo->objects->odb->path;
+}
+
+const char *repo_get_index_file(struct repository *repo)
+{
+ if (!repo->index_file)
+ BUG("repository hasn't been set up");
+ return repo->index_file;
+}
+
+const char *repo_get_graft_file(struct repository *repo)
+{
+ if (!repo->graft_file)
+ BUG("repository hasn't been set up");
+ return repo->graft_file;
+}
+
+const char *repo_get_work_tree(struct repository *repo)
+{
+ return repo->worktree;
+}
+
static void repo_set_commondir(struct repository *repo,
const char *commondir)
{
diff --git a/repository.h b/repository.h
index af6ea0a62c..24a66a496a 100644
--- a/repository.h
+++ b/repository.h
@@ -2,9 +2,9 @@
#define REPOSITORY_H
#include "strmap.h"
+#include "repo-settings.h"
struct config_set;
-struct fsmonitor_settings;
struct git_hash_algo;
struct index_state;
struct lock_file;
@@ -14,59 +14,12 @@ struct submodule_cache;
struct promisor_remote_config;
struct remote_state;
-enum untracked_cache_setting {
- UNTRACKED_CACHE_KEEP,
- UNTRACKED_CACHE_REMOVE,
- UNTRACKED_CACHE_WRITE,
-};
-
-enum fetch_negotiation_setting {
- FETCH_NEGOTIATION_CONSECUTIVE,
- FETCH_NEGOTIATION_SKIPPING,
- FETCH_NEGOTIATION_NOOP,
-};
-
enum ref_storage_format {
REF_STORAGE_FORMAT_UNKNOWN,
REF_STORAGE_FORMAT_FILES,
REF_STORAGE_FORMAT_REFTABLE,
};
-struct repo_settings {
- int initialized;
-
- int core_commit_graph;
- int commit_graph_generation_version;
- int commit_graph_changed_paths_version;
- int gc_write_commit_graph;
- int fetch_write_commit_graph;
- int command_requires_full_index;
- int sparse_index;
- int pack_read_reverse_index;
- int pack_use_bitmap_boundary_traversal;
- int pack_use_multi_pack_reuse;
-
- /*
- * Does this repository have core.useReplaceRefs=true (on by
- * default)? This provides a repository-scoped version of this
- * config, though it could be disabled process-wide via some Git
- * builtins or the --no-replace-objects option. See
- * replace_refs_enabled() for more details.
- */
- int read_replace_refs;
-
- struct fsmonitor_settings *fsmonitor; /* lazily loaded */
-
- int index_version;
- int index_skip_hash;
- enum untracked_cache_setting core_untracked_cache;
-
- int pack_use_sparse;
- enum fetch_negotiation_setting fetch_negotiation_algorithm;
-
- int core_multi_pack_index;
-};
-
struct repo_path_cache {
char *squash_msg;
char *merge_msg;
@@ -206,6 +159,13 @@ struct repository {
extern struct repository *the_repository;
#endif
+const char *repo_get_git_dir(struct repository *repo);
+const char *repo_get_common_dir(struct repository *repo);
+const char *repo_get_object_directory(struct repository *repo);
+const char *repo_get_index_file(struct repository *repo);
+const char *repo_get_graft_file(struct repository *repo);
+const char *repo_get_work_tree(struct repository *repo);
+
/*
* Define a custom repository layout. Any field can be NULL, which
* will default back to the path according to the default layout.
@@ -266,8 +226,6 @@ int repo_read_index_unmerged(struct repository *);
*/
void repo_update_index_if_able(struct repository *, struct lock_file *);
-void prepare_repo_settings(struct repository *r);
-
/*
* Return 1 if upgrade repository format to target_version succeeded,
* 0 if no upgrade is necessary, and -1 when upgrade is not possible.
diff --git a/revision.h b/revision.h
index 0e470d1df1..71e984c452 100644
--- a/revision.h
+++ b/revision.h
@@ -549,7 +549,7 @@ int rewrite_parents(struct rev_info *revs,
* The log machinery saves the original parent list so that
* get_saved_parents() can later tell what the real parents of the
* commits are, when commit->parents has been modified by history
- * simpification.
+ * simplification.
*
* get_saved_parents() will transparently return commit->parents if
* history simplification is off.
diff --git a/run-command.h b/run-command.h
index 03e7222d8b..0df25e445f 100644
--- a/run-command.h
+++ b/run-command.h
@@ -535,7 +535,7 @@ enum start_bg_result {
/* timeout expired waiting for child to become "ready" */
SBGR_TIMEOUT,
- /* child process exited or was signalled before becomming "ready" */
+ /* child process exited or was signalled before becoming "ready" */
SBGR_DIED,
};
diff --git a/scalar.c b/scalar.c
index 09560aeab5..73b79a5d4c 100644
--- a/scalar.c
+++ b/scalar.c
@@ -733,6 +733,9 @@ static int cmd_reconfigure(int argc, const char **argv)
the_repository = old_repo;
+ if (toggle_maintenance(1) >= 0)
+ succeeded = 1;
+
loop_end:
if (!succeeded) {
res = -1;
diff --git a/server-info.c b/server-info.c
index 1508fa6f82..c5af4cd98a 100644
--- a/server-info.c
+++ b/server-info.c
@@ -2,7 +2,6 @@
#include "git-compat-util.h"
#include "dir.h"
-#include "environment.h"
#include "hex.h"
#include "repository.h"
#include "refs.h"
@@ -342,7 +341,8 @@ static int write_pack_info_file(struct update_info_ctx *uic)
static int update_info_packs(int force)
{
- char *infofile = mkpathdup("%s/info/packs", get_object_directory());
+ char *infofile = mkpathdup("%s/info/packs",
+ repo_get_object_directory(the_repository));
int ret;
init_pack_info(infofile, force);
diff --git a/setup.c b/setup.c
index 29f8673921..94e79b2e48 100644
--- a/setup.c
+++ b/setup.c
@@ -7,16 +7,22 @@
#include "exec-cmd.h"
#include "gettext.h"
#include "hex.h"
+#include "object-file.h"
#include "object-name.h"
#include "refs.h"
+#include "replace-object.h"
#include "repository.h"
#include "config.h"
#include "dir.h"
#include "setup.h"
+#include "shallow.h"
#include "string-list.h"
+#include "strvec.h"
#include "chdir-notify.h"
#include "path.h"
#include "quote.h"
+#include "tmp-objdir.h"
+#include "trace.h"
#include "trace2.h"
#include "worktree.h"
#include "exec-cmd.h"
@@ -51,7 +57,7 @@ static int abspath_part_inside_repo(char *path)
size_t wtlen;
char *path0;
int off;
- const char *work_tree = precompose_string_if_needed(get_git_work_tree());
+ const char *work_tree = precompose_string_if_needed(repo_get_work_tree(the_repository));
struct strbuf realpath = STRBUF_INIT;
if (!work_tree)
@@ -147,9 +153,9 @@ char *prefix_path(const char *prefix, int len, const char *path)
{
char *r = prefix_path_gently(prefix, len, NULL, path);
if (!r) {
- const char *hint_path = get_git_work_tree();
+ const char *hint_path = repo_get_work_tree(the_repository);
if (!hint_path)
- hint_path = get_git_dir();
+ hint_path = repo_get_git_dir(the_repository);
die(_("'%s' is outside repository at '%s'"), path,
absolute_path(hint_path));
}
@@ -468,14 +474,14 @@ int is_nonbare_repository_dir(struct strbuf *path)
int is_inside_git_dir(void)
{
if (inside_git_dir < 0)
- inside_git_dir = is_inside_dir(get_git_dir());
+ inside_git_dir = is_inside_dir(repo_get_git_dir(the_repository));
return inside_git_dir;
}
int is_inside_work_tree(void)
{
if (inside_work_tree < 0)
- inside_work_tree = is_inside_dir(get_git_work_tree());
+ inside_work_tree = is_inside_dir(repo_get_work_tree(the_repository));
return inside_work_tree;
}
@@ -490,7 +496,7 @@ void setup_work_tree(void)
if (work_tree_config_is_bogus)
die(_("unable to set up work tree using invalid config"));
- work_tree = get_git_work_tree();
+ work_tree = repo_get_work_tree(the_repository);
if (!work_tree || chdir_notify(work_tree))
die(_("this operation must be run in a work tree"));
@@ -518,7 +524,7 @@ static void setup_original_cwd(void)
* directory we inherited from our parent process, which is a
* directory we want to avoid removing.
*
- * For convience, we would like to have the path relative to the
+ * For convenience, we would like to have the path relative to the
* worktree instead of an absolute path.
*
* Yes, startup_info->original_cwd is usually the same as 'prefix',
@@ -547,7 +553,7 @@ static void setup_original_cwd(void)
* Get our worktree; we only protect the current working directory
* if it's in the worktree.
*/
- worktree = get_git_work_tree();
+ worktree = repo_get_work_tree(the_repository);
if (!worktree)
goto no_prevention_needed;
@@ -1062,9 +1068,9 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
set_git_work_tree(".");
/* set_git_work_tree() must have been called by now */
- worktree = get_git_work_tree();
+ worktree = repo_get_work_tree(the_repository);
- /* both get_git_work_tree() and cwd are already normalized */
+ /* both repo_get_work_tree() and cwd are already normalized */
if (!strcmp(cwd->buf, worktree)) { /* cwd == worktree */
set_git_dir(gitdirenv, 0);
free(gitfile);
@@ -1613,6 +1619,106 @@ enum discovery_result discover_git_directory_reason(struct strbuf *commondir,
return result;
}
+void setup_git_env(const char *git_dir)
+{
+ char *git_replace_ref_base;
+ const char *shallow_file;
+ const char *replace_ref_base;
+ struct set_gitdir_args args = { NULL };
+ struct strvec to_free = STRVEC_INIT;
+
+ args.commondir = getenv_safe(&to_free, GIT_COMMON_DIR_ENVIRONMENT);
+ args.object_dir = getenv_safe(&to_free, DB_ENVIRONMENT);
+ args.graft_file = getenv_safe(&to_free, GRAFT_ENVIRONMENT);
+ args.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT);
+ args.alternate_db = getenv_safe(&to_free, ALTERNATE_DB_ENVIRONMENT);
+ if (getenv(GIT_QUARANTINE_ENVIRONMENT)) {
+ args.disable_ref_updates = 1;
+ }
+
+ repo_set_gitdir(the_repository, git_dir, &args);
+ strvec_clear(&to_free);
+
+ if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
+ disable_replace_refs();
+ replace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);
+ git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base
+ : "refs/replace/");
+ update_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);
+
+ shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);
+ if (shallow_file)
+ set_alternate_shallow_file(the_repository, shallow_file, 0);
+
+ if (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0))
+ fetch_if_missing = 0;
+}
+
+static void set_git_dir_1(const char *path)
+{
+ xsetenv(GIT_DIR_ENVIRONMENT, path, 1);
+ setup_git_env(path);
+}
+
+static void update_relative_gitdir(const char *name UNUSED,
+ const char *old_cwd,
+ const char *new_cwd,
+ void *data UNUSED)
+{
+ char *path = reparent_relative_path(old_cwd, new_cwd,
+ repo_get_git_dir(the_repository));
+ struct tmp_objdir *tmp_objdir = tmp_objdir_unapply_primary_odb();
+
+ trace_printf_key(&trace_setup_key,
+ "setup: move $GIT_DIR to '%s'",
+ path);
+ set_git_dir_1(path);
+ if (tmp_objdir)
+ tmp_objdir_reapply_primary_odb(tmp_objdir, old_cwd, new_cwd);
+ free(path);
+}
+
+void set_git_dir(const char *path, int make_realpath)
+{
+ struct strbuf realpath = STRBUF_INIT;
+
+ if (make_realpath) {
+ strbuf_realpath(&realpath, path, 1);
+ path = realpath.buf;
+ }
+
+ set_git_dir_1(path);
+ if (!is_absolute_path(path))
+ chdir_notify_register(NULL, update_relative_gitdir, NULL);
+
+ strbuf_release(&realpath);
+}
+
+static int git_work_tree_initialized;
+
+/*
+ * Note. This works only before you used a work tree. This was added
+ * primarily to support git-clone to work in a new repository it just
+ * created, and is not meant to flip between different work trees.
+ */
+void set_git_work_tree(const char *new_work_tree)
+{
+ if (git_work_tree_initialized) {
+ struct strbuf realpath = STRBUF_INIT;
+
+ strbuf_realpath(&realpath, new_work_tree, 1);
+ new_work_tree = realpath.buf;
+ if (strcmp(new_work_tree, the_repository->worktree))
+ die("internal error: work tree has already been set\n"
+ "Current worktree: %s\nNew worktree: %s",
+ the_repository->worktree, new_work_tree);
+ strbuf_release(&realpath);
+ return;
+ }
+ git_work_tree_initialized = 1;
+ repo_set_worktree(the_repository, new_work_tree);
+}
+
const char *setup_git_directory_gently(int *nongit_ok)
{
static struct strbuf cwd = STRBUF_INIT;
@@ -1836,7 +1942,7 @@ void check_repository_format(struct repository_format *fmt)
struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
if (!fmt)
fmt = &repo_fmt;
- check_repository_format_gently(get_git_dir(), fmt, NULL);
+ check_repository_format_gently(repo_get_git_dir(the_repository), fmt, NULL);
startup_info->have_repository = 1;
repo_set_hash_algo(the_repository, fmt->hash_algo);
repo_set_compat_hash_algo(the_repository, fmt->compat_hash_algo);
@@ -2068,7 +2174,7 @@ static void copy_templates(const char *option_template)
goto close_free_return;
}
- strbuf_addstr(&path, get_git_common_dir());
+ strbuf_addstr(&path, repo_get_common_dir(the_repository));
strbuf_complete(&path, '/');
copy_templates_1(&path, &template_path, dir);
close_free_return:
@@ -2192,7 +2298,7 @@ static int create_default_files(const char *template_path,
char *path;
int reinit;
int filemode;
- const char *work_tree = get_git_work_tree();
+ const char *work_tree = repo_get_work_tree(the_repository);
/*
* First copy the templates -- we might have the default
@@ -2224,7 +2330,7 @@ static int create_default_files(const char *template_path,
* shared-repository settings, we would need to fix them up.
*/
if (get_shared_repository()) {
- adjust_shared_perm(get_git_dir());
+ adjust_shared_perm(repo_get_git_dir(the_repository));
}
initialize_repository_version(fmt->hash_algo, fmt->ref_storage_format, 0);
@@ -2248,7 +2354,7 @@ static int create_default_files(const char *template_path,
else {
git_config_set("core.bare", "false");
/* allow template config file to override the default */
- if (log_all_ref_updates == LOG_REFS_UNSET)
+ if (repo_settings_get_log_all_ref_updates(the_repository) == LOG_REFS_UNSET)
git_config_set("core.logallrefupdates", "true");
if (needs_work_tree_config(original_git_dir, work_tree))
git_config_set("core.worktree", work_tree);
@@ -2282,7 +2388,7 @@ static void create_object_directory(void)
struct strbuf path = STRBUF_INIT;
size_t baselen;
- strbuf_addstr(&path, get_object_directory());
+ strbuf_addstr(&path, repo_get_object_directory(the_repository));
baselen = path.len;
safe_create_dir(path.buf, 1);
@@ -2434,12 +2540,12 @@ int init_db(const char *git_dir, const char *real_git_dir,
die(_("%s already exists"), real_git_dir);
set_git_dir(real_git_dir, 1);
- git_dir = get_git_dir();
+ git_dir = repo_get_git_dir(the_repository);
separate_git_dir(git_dir, original_git_dir);
}
else {
set_git_dir(git_dir, 1);
- git_dir = get_git_dir();
+ git_dir = repo_get_git_dir(the_repository);
}
startup_info->have_repository = 1;
diff --git a/setup.h b/setup.h
index cd8dbc2497..e496ab3e4d 100644
--- a/setup.h
+++ b/setup.h
@@ -94,6 +94,9 @@ static inline int discover_git_directory(struct strbuf *commondir,
return 0;
}
+void set_git_dir(const char *path, int make_realpath);
+void set_git_work_tree(const char *tree);
+
const char *setup_git_directory_gently(int *);
const char *setup_git_directory(void);
char *prefix_path(const char *prefix, int len, const char *path);
@@ -176,7 +179,7 @@ int verify_repository_format(const struct repository_format *format,
struct strbuf *err);
/*
- * Check the repository format version in the path found in get_git_dir(),
+ * Check the repository format version in the path found in repo_get_git_dir(the_repository),
* and die if it is a version we don't understand. Generally one would
* set_git_dir() before calling this, and use it only for "are we in a valid
* repo?".
diff --git a/sideband.c b/sideband.c
index 4e816be4e9..02805573fa 100644
--- a/sideband.c
+++ b/sideband.c
@@ -191,7 +191,7 @@ int demultiplex_sideband(const char *me, int status,
int linelen = brk - b;
/*
- * For message accross packet boundary, there would have
+ * For message across packet boundary, there would have
* a nonempty "scratch" buffer from last call of this
* function, and there may have a leading CR/LF in "buf".
* For this case we should add a clear-to-eol suffix to
diff --git a/sparse-index.c b/sparse-index.c
index 9958656ded..3d7f2164e2 100644
--- a/sparse-index.c
+++ b/sparse-index.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
#include "environment.h"
#include "gettext.h"
@@ -19,9 +21,10 @@
* advice for advice.sparseIndexExpanded when expanding a sparse index to a full
* one. However, this is sometimes done on purpose, such as in the sparse-checkout
* builtin, even when index.sparse=false. This may be disabled in
- * convert_to_sparse().
+ * convert_to_sparse() or by commands that know they will lead to a full
+ * expansion, but this message is not actionable.
*/
-static int give_advice_on_expansion = 1;
+int give_advice_on_expansion = 1;
#define ADVICE_MSG \
"The sparse index is expanding to a full index, a slow operation.\n" \
"Your working directory likely has contents that are outside of\n" \
diff --git a/sparse-index.h b/sparse-index.h
index a16f3e67d7..727034be7c 100644
--- a/sparse-index.h
+++ b/sparse-index.h
@@ -1,6 +1,13 @@
#ifndef SPARSE_INDEX_H__
#define SPARSE_INDEX_H__
+/*
+ * If performing an operation where the index is supposed to expand to a
+ * full index, then disable the advice message by setting this global to
+ * zero.
+ */
+extern int give_advice_on_expansion;
+
struct index_state;
#define SPARSE_INDEX_MEMORY_ONLY (1 << 0)
int is_sparse_index_allowed(struct index_state *istate, int flags);
diff --git a/statinfo.c b/statinfo.c
index 3c6bc049c1..30a164b0e6 100644
--- a/statinfo.c
+++ b/statinfo.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
#include "environment.h"
#include "statinfo.h"
diff --git a/submodule.c b/submodule.c
index a07debc227..74d5766f07 100644
--- a/submodule.c
+++ b/submodule.c
@@ -2469,7 +2469,7 @@ void absorb_git_dir_into_superproject(const char *path,
} else {
/* Is it already absorbed into the superprojects git dir? */
char *real_sub_git_dir = real_pathdup(sub_git_dir, 1);
- char *real_common_git_dir = real_pathdup(get_git_common_dir(), 1);
+ char *real_common_git_dir = real_pathdup(repo_get_common_dir(the_repository), 1);
if (!starts_with(real_sub_git_dir, real_common_git_dir))
relocate_single_git_dir_into_superproject(path, super_prefix);
diff --git a/t/Makefile b/t/Makefile
index 4c30e7c06f..131ffd778f 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -48,6 +48,7 @@ CHAINLINTTESTS = $(sort $(patsubst chainlint/%.test,%,$(wildcard chainlint/*.tes
CHAINLINT = '$(PERL_PATH_SQ)' chainlint.pl
UNIT_TEST_SOURCES = $(wildcard unit-tests/t-*.c)
UNIT_TEST_PROGRAMS = $(patsubst unit-tests/%.c,unit-tests/bin/%$(X),$(UNIT_TEST_SOURCES))
+UNIT_TEST_PROGRAMS += unit-tests/bin/unit-tests$(X)
UNIT_TESTS = $(sort $(UNIT_TEST_PROGRAMS))
UNIT_TESTS_NO_DIR = $(notdir $(UNIT_TESTS))
@@ -68,7 +69,8 @@ failed:
test -z "$$failed" || $(MAKE) $$failed
prove: pre-clean check-chainlint $(TEST_LINT)
- @echo "*** prove (shell & unit tests) ***"; $(CHAINLINTSUPPRESS) TEST_SHELL_PATH='$(TEST_SHELL_PATH_SQ)' $(PROVE) --exec ./run-test.sh $(GIT_PROVE_OPTS) $(T) $(UNIT_TESTS) :: $(GIT_TEST_OPTS)
+ @echo "*** prove (shell & unit tests) ***"
+ @$(CHAINLINTSUPPRESS) TEST_OPTIONS='$(GIT_TEST_OPTS)' TEST_SHELL_PATH='$(TEST_SHELL_PATH_SQ)' $(PROVE) --exec ./run-test.sh $(GIT_PROVE_OPTS) $(T) $(UNIT_TESTS)
$(MAKE) clean-except-prove-cache
$(T):
diff --git a/t/chainlint.pl b/t/chainlint.pl
index 5361f23b1d..f0598e3934 100755
--- a/t/chainlint.pl
+++ b/t/chainlint.pl
@@ -9,9 +9,9 @@
# Input arguments are pathnames of shell scripts containing test definitions,
# or globs referencing a collection of scripts. For each problem discovered,
# the pathname of the script containing the test is printed along with the test
-# name and the test body with a `?!FOO?!` annotation at the location of each
-# detected problem, where "FOO" is a tag such as "AMP" which indicates a broken
-# &&-chain. Returns zero if no problems are discovered, otherwise non-zero.
+# name and the test body with a `?!LINT: ...?!` annotation at the location of
+# each detected problem, where "..." is an explanation of the problem. Returns
+# zero if no problems are discovered, otherwise non-zero.
use warnings;
use strict;
@@ -181,7 +181,7 @@ sub swallow_heredocs {
$self->{lineno} += () = $body =~ /\n/sg;
next;
}
- push(@{$self->{parser}->{problems}}, ['UNCLOSED-HEREDOC', $tag]);
+ push(@{$self->{parser}->{problems}}, ['HEREDOC', $tag]);
$$b =~ /(?:\G|\n).*\z/gc; # consume rest of input
my $body = substr($$b, $start, pos($$b) - $start);
$self->{lineno} += () = $body =~ /\n/sg;
@@ -238,6 +238,7 @@ sub new {
stop => [],
output => [],
heredocs => {},
+ insubshell => 0,
} => $class;
$self->{lexer} = Lexer->new($self, $s);
return $self;
@@ -296,8 +297,11 @@ sub parse_group {
sub parse_subshell {
my $self = shift @_;
- return ($self->parse(qr/^\)$/),
- $self->expect(')'));
+ $self->{insubshell}++;
+ my @tokens = ($self->parse(qr/^\)$/),
+ $self->expect(')'));
+ $self->{insubshell}--;
+ return @tokens;
}
sub parse_case_pattern {
@@ -528,7 +532,7 @@ sub parse_loop_body {
return @tokens if ends_with(\@tokens, [qr/^\|\|$/, "\n", qr/^echo$/, qr/^.+$/]);
# flag missing "return/exit" handling explicit failure in loop body
my $n = find_non_nl(\@tokens);
- push(@{$self->{problems}}, ['LOOP', $tokens[$n]]);
+ push(@{$self->{problems}}, [$self->{insubshell} ? 'LOOPEXIT' : 'LOOPRETURN', $tokens[$n]]);
return @tokens;
}
@@ -587,6 +591,7 @@ sub new {
my $class = shift @_;
my $self = $class->SUPER::new(@_);
$self->{ntests} = 0;
+ $self->{nerrs} = 0;
return $self;
}
@@ -619,6 +624,15 @@ sub unwrap {
return $s
}
+sub format_problem {
+ local $_ = shift;
+ /^AMP$/ && return "missing '&&'";
+ /^LOOPRETURN$/ && return "missing '|| return 1'";
+ /^LOOPEXIT$/ && return "missing '|| exit 1'";
+ /^HEREDOC$/ && return 'unclosed heredoc';
+ die("unrecognized problem type '$_'\n");
+}
+
sub check_test {
my $self = shift @_;
my $title = unwrap(shift @_);
@@ -634,22 +648,26 @@ sub check_test {
my $parser = TestParser->new(\$body);
my @tokens = $parser->parse();
my $problems = $parser->{problems};
+ $self->{nerrs} += @$problems;
return unless $emit_all || @$problems;
my $c = main::fd_colors(1);
+ my ($erropen, $errclose) = -t 1 ? ("$c->{rev}$c->{red}", $c->{reset}) : ('?!', '?!');
my $start = 0;
my $checked = '';
for (sort {$a->[1]->[2] <=> $b->[1]->[2]} @$problems) {
my ($label, $token) = @$_;
my $pos = $token->[2];
- $checked .= substr($body, $start, $pos - $start) . " ?!$label?! ";
+ my $err = format_problem($label);
+ $checked .= substr($body, $start, $pos - $start);
+ $checked .= ' ' unless $checked =~ /\s$/;
+ $checked .= "${erropen}LINT: $err$errclose";
+ $checked .= ' ' unless $pos >= length($body) ||
+ substr($body, $pos, 1) =~ /^\s/;
$start = $pos;
}
$checked .= substr($body, $start);
$checked =~ s/^/$lineno++ . ' '/mge;
$checked =~ s/^\d+ \n//;
- $checked =~ s/(\s) \?!/$1?!/mg;
- $checked =~ s/\?! (\s)/?!$1/mg;
- $checked =~ s/(\?![^?]+\?!)/$c->{rev}$c->{red}$1$c->{reset}/mg;
$checked =~ s/^\d+/$c->{dim}$&$c->{reset}/mg;
$checked .= "\n" unless $checked =~ /\n$/;
push(@{$self->{output}}, "$c->{blue}# chainlint: $title$c->{reset}\n$checked");
@@ -791,9 +809,9 @@ sub check_script {
my $c = fd_colors(1);
my $s = join('', @{$parser->{output}});
$emit->("$c->{bold}$c->{blue}# chainlint: $path$c->{reset}\n" . $s);
- $nerrs += () = $s =~ /\?![^?]+\?!/g;
}
$ntests += $parser->{ntests};
+ $nerrs += $parser->{nerrs};
}
return [$id, $nscripts, $ntests, $nerrs];
}
diff --git a/t/chainlint/arithmetic-expansion.expect b/t/chainlint/arithmetic-expansion.expect
index 338ecd5861..5677e16cad 100644
--- a/t/chainlint/arithmetic-expansion.expect
+++ b/t/chainlint/arithmetic-expansion.expect
@@ -4,6 +4,6 @@
5 baz
6 ) &&
7 (
-8 bar=$((42 + 1)) ?!AMP?!
+8 bar=$((42 + 1)) ?!LINT: missing '&&'?!
9 baz
10 )
diff --git a/t/chainlint/block.expect b/t/chainlint/block.expect
index b62e3d58c3..3d3f854c0d 100644
--- a/t/chainlint/block.expect
+++ b/t/chainlint/block.expect
@@ -1,20 +1,20 @@
2 (
3 foo &&
4 {
-5 echo a ?!AMP?!
+5 echo a ?!LINT: missing '&&'?!
6 echo b
7 } &&
8 bar &&
9 {
10 echo c
-11 } ?!AMP?!
+11 } ?!LINT: missing '&&'?!
12 baz
13 ) &&
14
15 {
-16 echo a; ?!AMP?! echo b
+16 echo a; ?!LINT: missing '&&'?! echo b
17 } &&
-18 { echo a; ?!AMP?! echo b; } &&
+18 { echo a; ?!LINT: missing '&&'?! echo b; } &&
19
20 {
21 echo "${var}9" &&
diff --git a/t/chainlint/broken-chain.expect b/t/chainlint/broken-chain.expect
index 9a1838736f..b7b1ce8509 100644
--- a/t/chainlint/broken-chain.expect
+++ b/t/chainlint/broken-chain.expect
@@ -1,6 +1,6 @@
2 (
3 foo &&
-4 bar ?!AMP?!
+4 bar ?!LINT: missing '&&'?!
5 baz &&
6 wop
7 )
diff --git a/t/chainlint/case.expect b/t/chainlint/case.expect
index c04c61ff36..0a3b09e470 100644
--- a/t/chainlint/case.expect
+++ b/t/chainlint/case.expect
@@ -9,11 +9,11 @@
10 case "$x" in
11 x) foo ;;
12 *) bar ;;
-13 esac ?!AMP?!
+13 esac ?!LINT: missing '&&'?!
14 foobar
15 ) &&
16 (
17 case "$x" in 1) true;; esac &&
-18 case "$y" in 2) false;; esac ?!AMP?!
+18 case "$y" in 2) false;; esac ?!LINT: missing '&&'?!
19 foobar
20 )
diff --git a/t/chainlint/chain-break-false.expect b/t/chainlint/chain-break-false.expect
index 4f815f8e14..f6a0a301e9 100644
--- a/t/chainlint/chain-break-false.expect
+++ b/t/chainlint/chain-break-false.expect
@@ -4,6 +4,6 @@
5 echo failed!
6 false
7 else
-8 echo it went okay ?!AMP?!
+8 echo it went okay ?!LINT: missing '&&'?!
9 congratulate user
10 fi
diff --git a/t/chainlint/chained-block.expect b/t/chainlint/chained-block.expect
index a546b714a6..f2501bba90 100644
--- a/t/chainlint/chained-block.expect
+++ b/t/chainlint/chained-block.expect
@@ -1,5 +1,5 @@
2 echo nobody home && {
-3 test the doohicky ?!AMP?!
+3 test the doohicky ?!LINT: missing '&&'?!
4 right now
5 } &&
6
diff --git a/t/chainlint/chained-subshell.expect b/t/chainlint/chained-subshell.expect
index f78b268291..93fb1a6578 100644
--- a/t/chainlint/chained-subshell.expect
+++ b/t/chainlint/chained-subshell.expect
@@ -1,10 +1,10 @@
2 mkdir sub && (
3 cd sub &&
-4 foo the bar ?!AMP?!
+4 foo the bar ?!LINT: missing '&&'?!
5 nuff said
6 ) &&
7
8 cut "-d " -f actual | (read s1 s2 s3 &&
-9 test -f $s1 ?!AMP?!
+9 test -f $s1 ?!LINT: missing '&&'?!
10 test $(cat $s2) = tree2path1 &&
11 test $(cat $s3) = tree3path1)
diff --git a/t/chainlint/command-substitution.expect b/t/chainlint/command-substitution.expect
index 5e31b36db6..73809fd585 100644
--- a/t/chainlint/command-substitution.expect
+++ b/t/chainlint/command-substitution.expect
@@ -4,6 +4,6 @@
5 baz
6 ) &&
7 (
-8 bar=$(gobble blocks) ?!AMP?!
+8 bar=$(gobble blocks) ?!LINT: missing '&&'?!
9 baz
10 )
diff --git a/t/chainlint/complex-if-in-cuddled-loop.expect b/t/chainlint/complex-if-in-cuddled-loop.expect
index 3a740103db..e66bb2d5d0 100644
--- a/t/chainlint/complex-if-in-cuddled-loop.expect
+++ b/t/chainlint/complex-if-in-cuddled-loop.expect
@@ -4,6 +4,6 @@
5 :
6 else
7 echo >file
-8 fi ?!LOOP?!
+8 fi ?!LINT: missing '|| exit 1'?!
9 done) &&
10 test ! -f file
diff --git a/t/chainlint/cuddled.expect b/t/chainlint/cuddled.expect
index b06d638311..1864b3fc8b 100644
--- a/t/chainlint/cuddled.expect
+++ b/t/chainlint/cuddled.expect
@@ -2,7 +2,7 @@
3 bar
4 ) &&
5
-6 (cd foo ?!AMP?!
+6 (cd foo ?!LINT: missing '&&'?!
7 bar
8 ) &&
9
@@ -13,5 +13,5 @@
14 (cd foo &&
15 bar) &&
16
-17 (cd foo ?!AMP?!
+17 (cd foo ?!LINT: missing '&&'?!
18 bar)
diff --git a/t/chainlint/for-loop.expect b/t/chainlint/for-loop.expect
index 908aeedf96..5029eacce3 100644
--- a/t/chainlint/for-loop.expect
+++ b/t/chainlint/for-loop.expect
@@ -1,14 +1,14 @@
2 (
3 for i in a b c
4 do
-5 echo $i ?!AMP?!
-6 cat <<-\EOF ?!LOOP?!
+5 echo $i ?!LINT: missing '&&'?!
+6 cat <<-\EOF ?!LINT: missing '|| exit 1'?!
7 bar
8 EOF
-9 done ?!AMP?!
+9 done ?!LINT: missing '&&'?!
10
11 for i in a b c; do
12 echo $i &&
-13 cat $i ?!LOOP?!
+13 cat $i ?!LINT: missing '|| exit 1'?!
14 done
15 )
diff --git a/t/chainlint/function.expect b/t/chainlint/function.expect
index c226246b25..9e46a3554a 100644
--- a/t/chainlint/function.expect
+++ b/t/chainlint/function.expect
@@ -4,8 +4,8 @@
5
6 remove_object() {
7 file=$(sha1_file "$*") &&
-8 test -e "$file" ?!AMP?!
+8 test -e "$file" ?!LINT: missing '&&'?!
9 rm -f "$file"
-10 } ?!AMP?!
+10 } ?!LINT: missing '&&'?!
11
12 sha1_file arg && remove_object arg
diff --git a/t/chainlint/here-doc-body-indent.expect b/t/chainlint/here-doc-body-indent.expect
index 4323acc93d..4306faee86 100644
--- a/t/chainlint/here-doc-body-indent.expect
+++ b/t/chainlint/here-doc-body-indent.expect
@@ -1,2 +1,2 @@
-2 echo "we should find this" ?!AMP?!
+2 echo "we should find this" ?!LINT: missing '&&'?!
3 echo "even though our heredoc has its indent stripped"
diff --git a/t/chainlint/here-doc-body-pathological.expect b/t/chainlint/here-doc-body-pathological.expect
index a93a1fa3aa..2f8ea03a47 100644
--- a/t/chainlint/here-doc-body-pathological.expect
+++ b/t/chainlint/here-doc-body-pathological.expect
@@ -1,7 +1,7 @@
-2 echo "outer here-doc does not allow indented end-tag" ?!AMP?!
+2 echo "outer here-doc does not allow indented end-tag" ?!LINT: missing '&&'?!
3 cat >file <<-\EOF &&
4 but this inner here-doc
5 does allow indented EOF
6 EOF
-7 echo "missing chain after" ?!AMP?!
+7 echo "missing chain after" ?!LINT: missing '&&'?!
8 echo "but this line is OK because it's the end"
diff --git a/t/chainlint/here-doc-body.expect b/t/chainlint/here-doc-body.expect
index ddf1c412af..df8d79bc0a 100644
--- a/t/chainlint/here-doc-body.expect
+++ b/t/chainlint/here-doc-body.expect
@@ -1,7 +1,7 @@
-2 echo "missing chain before" ?!AMP?!
+2 echo "missing chain before" ?!LINT: missing '&&'?!
3 cat >file <<-\EOF &&
4 inside inner here-doc
5 these are not shell commands
6 EOF
-7 echo "missing chain after" ?!AMP?!
+7 echo "missing chain after" ?!LINT: missing '&&'?!
8 echo "but this line is OK because it's the end"
diff --git a/t/chainlint/here-doc-double.expect b/t/chainlint/here-doc-double.expect
index 20dba4b452..e5e981889f 100644
--- a/t/chainlint/here-doc-double.expect
+++ b/t/chainlint/here-doc-double.expect
@@ -1,2 +1,2 @@
-8 echo "actual test commands" ?!AMP?!
+8 echo "actual test commands" ?!LINT: missing '&&'?!
9 echo "that should be checked"
diff --git a/t/chainlint/here-doc-indent-operator.expect b/t/chainlint/here-doc-indent-operator.expect
index 277a11202d..ec0e61505b 100644
--- a/t/chainlint/here-doc-indent-operator.expect
+++ b/t/chainlint/here-doc-indent-operator.expect
@@ -4,7 +4,7 @@
5 chunks: oid_fanout oid_lookup commit_metadata generation_data bloom_indexes bloom_data
6 EOF
7
-8 cat >expect << -EOF ?!AMP?!
+8 cat >expect << -EOF ?!LINT: missing '&&'?!
9 this is not indented
10 -EOF
11
diff --git a/t/chainlint/here-doc-multi-line-command-subst.expect b/t/chainlint/here-doc-multi-line-command-subst.expect
index 41b55f6437..8128f15b92 100644
--- a/t/chainlint/here-doc-multi-line-command-subst.expect
+++ b/t/chainlint/here-doc-multi-line-command-subst.expect
@@ -3,6 +3,6 @@
4 fossil
5 vegetable
6 END
-7 wiffle) ?!AMP?!
+7 wiffle) ?!LINT: missing '&&'?!
8 echo $x
9 )
diff --git a/t/chainlint/here-doc-multi-line-string.expect b/t/chainlint/here-doc-multi-line-string.expect
index c71828589e..a03a04ff3d 100644
--- a/t/chainlint/here-doc-multi-line-string.expect
+++ b/t/chainlint/here-doc-multi-line-string.expect
@@ -1,6 +1,6 @@
2 (
3 cat <<-\TXT && echo "multi-line
-4 string" ?!AMP?!
+4 string" ?!LINT: missing '&&'?!
5 fizzle
6 TXT
7 bap
diff --git a/t/chainlint/if-condition-split.expect b/t/chainlint/if-condition-split.expect
index 9daf3d294a..6d2a03dfdb 100644
--- a/t/chainlint/if-condition-split.expect
+++ b/t/chainlint/if-condition-split.expect
@@ -2,6 +2,6 @@
3 marcia ||
4 kevin
5 then
-6 echo "nomads" ?!AMP?!
+6 echo "nomads" ?!LINT: missing '&&'?!
7 echo "for sure"
8 fi
diff --git a/t/chainlint/if-in-loop.expect b/t/chainlint/if-in-loop.expect
index ff8c60dbdb..7e3ba740de 100644
--- a/t/chainlint/if-in-loop.expect
+++ b/t/chainlint/if-in-loop.expect
@@ -5,8 +5,8 @@
6 then
7 echo "err"
8 exit 1
-9 fi ?!AMP?!
+9 fi ?!LINT: missing '&&'?!
10 foo
-11 done ?!AMP?!
+11 done ?!LINT: missing '&&'?!
12 bar
13 )
diff --git a/t/chainlint/if-then-else.expect b/t/chainlint/if-then-else.expect
index 965d7e41a2..924caa2e4e 100644
--- a/t/chainlint/if-then-else.expect
+++ b/t/chainlint/if-then-else.expect
@@ -1,7 +1,7 @@
2 (
3 if test -n ""
4 then
-5 echo very ?!AMP?!
+5 echo very ?!LINT: missing '&&'?!
6 echo empty
7 elif test -z ""
8 then
@@ -11,7 +11,7 @@
12 cat <<-\EOF
13 bar
14 EOF
-15 fi ?!AMP?!
+15 fi ?!LINT: missing '&&'?!
16 echo poodle
17 ) &&
18 (
diff --git a/t/chainlint/inline-comment.expect b/t/chainlint/inline-comment.expect
index 0285c0b22c..4b4080124e 100644
--- a/t/chainlint/inline-comment.expect
+++ b/t/chainlint/inline-comment.expect
@@ -1,6 +1,6 @@
2 (
3 foobar && # comment 1
-4 barfoo ?!AMP?! # wrong position for &&
+4 barfoo ?!LINT: missing '&&'?! # wrong position for &&
5 flibble "not a # comment"
6 ) &&
7
diff --git a/t/chainlint/loop-detect-failure.expect b/t/chainlint/loop-detect-failure.expect
index 40c06f0d53..7d846b878d 100644
--- a/t/chainlint/loop-detect-failure.expect
+++ b/t/chainlint/loop-detect-failure.expect
@@ -11,5 +11,5 @@
12 do
13 printf "%"$n"s" X > r2/large.$n &&
14 git -C r2 add large.$n &&
-15 git -C r2 commit -m "$n" ?!LOOP?!
+15 git -C r2 commit -m "$n" ?!LINT: missing '|| return 1'?!
16 done
diff --git a/t/chainlint/loop-in-if.expect b/t/chainlint/loop-in-if.expect
index 4e8c67c914..32e076ad1b 100644
--- a/t/chainlint/loop-in-if.expect
+++ b/t/chainlint/loop-in-if.expect
@@ -3,10 +3,10 @@
4 then
5 while true
6 do
-7 echo "pop" ?!AMP?!
-8 echo "glup" ?!LOOP?!
-9 done ?!AMP?!
+7 echo "pop" ?!LINT: missing '&&'?!
+8 echo "glup" ?!LINT: missing '|| exit 1'?!
+9 done ?!LINT: missing '&&'?!
10 foo
-11 fi ?!AMP?!
+11 fi ?!LINT: missing '&&'?!
12 bar
13 )
diff --git a/t/chainlint/multi-line-string.expect b/t/chainlint/multi-line-string.expect
index 62c54e3a5e..9d33297525 100644
--- a/t/chainlint/multi-line-string.expect
+++ b/t/chainlint/multi-line-string.expect
@@ -3,7 +3,7 @@
4 line 2
5 line 3" &&
6 y="line 1
-7 line2" ?!AMP?!
+7 line2" ?!LINT: missing '&&'?!
8 foobar
9 ) &&
10 (
diff --git a/t/chainlint/negated-one-liner.expect b/t/chainlint/negated-one-liner.expect
index a6ce52a1da..0a6f3c29b2 100644
--- a/t/chainlint/negated-one-liner.expect
+++ b/t/chainlint/negated-one-liner.expect
@@ -1,5 +1,5 @@
2 ! (foo && bar) &&
3 ! (foo && bar) >baz &&
4
-5 ! (foo; ?!AMP?! bar) &&
-6 ! (foo; ?!AMP?! bar) >baz
+5 ! (foo; ?!LINT: missing '&&'?! bar) &&
+6 ! (foo; ?!LINT: missing '&&'?! bar) >baz
diff --git a/t/chainlint/nested-cuddled-subshell.expect b/t/chainlint/nested-cuddled-subshell.expect
index 0191c9c294..fec2c74274 100644
--- a/t/chainlint/nested-cuddled-subshell.expect
+++ b/t/chainlint/nested-cuddled-subshell.expect
@@ -5,7 +5,7 @@
6
7 (cd foo &&
8 bar
-9 ) ?!AMP?!
+9 ) ?!LINT: missing '&&'?!
10
11 (
12 cd foo &&
@@ -13,13 +13,13 @@
14
15 (
16 cd foo &&
-17 bar) ?!AMP?!
+17 bar) ?!LINT: missing '&&'?!
18
19 (cd foo &&
20 bar) &&
21
22 (cd foo &&
-23 bar) ?!AMP?!
+23 bar) ?!LINT: missing '&&'?!
24
25 foobar
26 )
diff --git a/t/chainlint/nested-here-doc.expect b/t/chainlint/nested-here-doc.expect
index 70d9b68dc9..571f4c9514 100644
--- a/t/chainlint/nested-here-doc.expect
+++ b/t/chainlint/nested-here-doc.expect
@@ -18,7 +18,7 @@
19 toink
20 INPUT_END
21
-22 cat <<-\EOT ?!AMP?!
+22 cat <<-\EOT ?!LINT: missing '&&'?!
23 text goes here
24 data <<EOF
25 data goes here
diff --git a/t/chainlint/nested-loop-detect-failure.expect b/t/chainlint/nested-loop-detect-failure.expect
index c13c4d2f90..b4aaa621a2 100644
--- a/t/chainlint/nested-loop-detect-failure.expect
+++ b/t/chainlint/nested-loop-detect-failure.expect
@@ -2,8 +2,8 @@
3 do
4 for j in 0 1 2 3 4 5 6 7 8 9;
5 do
-6 echo "$i$j" >"path$i$j" ?!LOOP?!
-7 done ?!LOOP?!
+6 echo "$i$j" >"path$i$j" ?!LINT: missing '|| return 1'?!
+7 done ?!LINT: missing '|| return 1'?!
8 done &&
9
10 for i in 0 1 2 3 4 5 6 7 8 9;
@@ -18,7 +18,7 @@
19 do
20 for j in 0 1 2 3 4 5 6 7 8 9;
21 do
-22 echo "$i$j" >"path$i$j" ?!LOOP?!
+22 echo "$i$j" >"path$i$j" ?!LINT: missing '|| return 1'?!
23 done || return 1
24 done &&
25
diff --git a/t/chainlint/nested-subshell-comment.expect b/t/chainlint/nested-subshell-comment.expect
index f89a8d03a8..078c6f275f 100644
--- a/t/chainlint/nested-subshell-comment.expect
+++ b/t/chainlint/nested-subshell-comment.expect
@@ -6,6 +6,6 @@
7 # minor numbers of cows (or do they?)
8 baz &&
9 snaff
-10 ) ?!AMP?!
+10 ) ?!LINT: missing '&&'?!
11 fuzzy
12 )
diff --git a/t/chainlint/nested-subshell.expect b/t/chainlint/nested-subshell.expect
index 811e8a7912..a8d85d5d5b 100644
--- a/t/chainlint/nested-subshell.expect
+++ b/t/chainlint/nested-subshell.expect
@@ -7,7 +7,7 @@
8
9 cd foo &&
10 (
-11 echo a ?!AMP?!
+11 echo a ?!LINT: missing '&&'?!
12 echo b
13 ) >file
14 )
diff --git a/t/chainlint/not-heredoc.expect b/t/chainlint/not-heredoc.expect
index 611b7b75cb..5d51705a7a 100644
--- a/t/chainlint/not-heredoc.expect
+++ b/t/chainlint/not-heredoc.expect
@@ -9,6 +9,6 @@
10 echo ourside &&
11 echo "=======" &&
12 echo theirside &&
-13 echo ">>>>>>> theirs" ?!AMP?!
+13 echo ">>>>>>> theirs" ?!LINT: missing '&&'?!
14 poodle
15 ) >merged
diff --git a/t/chainlint/one-liner-for-loop.expect b/t/chainlint/one-liner-for-loop.expect
index 49dcf065ef..e1fcbd3639 100644
--- a/t/chainlint/one-liner-for-loop.expect
+++ b/t/chainlint/one-liner-for-loop.expect
@@ -3,7 +3,7 @@
4 cd dir-rename-and-content &&
5 test_write_lines 1 2 3 4 5 >foo &&
6 mkdir olddir &&
-7 for i in a b c; do echo $i >olddir/$i; ?!LOOP?! done ?!AMP?!
+7 for i in a b c; do echo $i >olddir/$i; ?!LINT: missing '|| exit 1'?! done ?!LINT: missing '&&'?!
8 git add foo olddir &&
9 git commit -m "original" &&
10 )
diff --git a/t/chainlint/one-liner.expect b/t/chainlint/one-liner.expect
index 9861811283..5deeb05070 100644
--- a/t/chainlint/one-liner.expect
+++ b/t/chainlint/one-liner.expect
@@ -2,8 +2,8 @@
3 (foo && bar) |
4 (foo && bar) >baz &&
5
-6 (foo; ?!AMP?! bar) &&
-7 (foo; ?!AMP?! bar) |
-8 (foo; ?!AMP?! bar) >baz &&
+6 (foo; ?!LINT: missing '&&'?! bar) &&
+7 (foo; ?!LINT: missing '&&'?! bar) |
+8 (foo; ?!LINT: missing '&&'?! bar) >baz &&
9
10 (foo "bar; baz")
diff --git a/t/chainlint/pipe.expect b/t/chainlint/pipe.expect
index 1bbe5a2ce1..d947c76584 100644
--- a/t/chainlint/pipe.expect
+++ b/t/chainlint/pipe.expect
@@ -4,7 +4,7 @@
5 baz &&
6
7 fish |
-8 cow ?!AMP?!
+8 cow ?!LINT: missing '&&'?!
9
10 sunder
11 )
diff --git a/t/chainlint/semicolon.expect b/t/chainlint/semicolon.expect
index 866438310c..2b499fbe70 100644
--- a/t/chainlint/semicolon.expect
+++ b/t/chainlint/semicolon.expect
@@ -1,19 +1,19 @@
2 (
-3 cat foo ; ?!AMP?! echo bar ?!AMP?!
-4 cat foo ; ?!AMP?! echo bar
+3 cat foo ; ?!LINT: missing '&&'?! echo bar ?!LINT: missing '&&'?!
+4 cat foo ; ?!LINT: missing '&&'?! echo bar
5 ) &&
6 (
-7 cat foo ; ?!AMP?! echo bar &&
-8 cat foo ; ?!AMP?! echo bar
+7 cat foo ; ?!LINT: missing '&&'?! echo bar &&
+8 cat foo ; ?!LINT: missing '&&'?! echo bar
9 ) &&
10 (
11 echo "foo; bar" &&
-12 cat foo; ?!AMP?! echo bar
+12 cat foo; ?!LINT: missing '&&'?! echo bar
13 ) &&
14 (
15 foo;
16 ) &&
17 (cd foo &&
18 for i in a b c; do
-19 echo; ?!LOOP?!
+19 echo; ?!LINT: missing '|| exit 1'?!
20 done)
diff --git a/t/chainlint/subshell-here-doc.expect b/t/chainlint/subshell-here-doc.expect
index 5647500c82..e450caf948 100644
--- a/t/chainlint/subshell-here-doc.expect
+++ b/t/chainlint/subshell-here-doc.expect
@@ -6,7 +6,7 @@
7 nevermore...
8 EOF
9
-10 cat <<EOF >bip ?!AMP?!
+10 cat <<EOF >bip ?!LINT: missing '&&'?!
11 fish fly high
12 EOF
13
diff --git a/t/chainlint/subshell-one-liner.expect b/t/chainlint/subshell-one-liner.expect
index 214316c6a0..265d996a21 100644
--- a/t/chainlint/subshell-one-liner.expect
+++ b/t/chainlint/subshell-one-liner.expect
@@ -3,17 +3,17 @@
4 (foo && bar) |
5 (foo && bar) >baz &&
6
-7 (foo; ?!AMP?! bar) &&
-8 (foo; ?!AMP?! bar) |
-9 (foo; ?!AMP?! bar) >baz &&
+7 (foo; ?!LINT: missing '&&'?! bar) &&
+8 (foo; ?!LINT: missing '&&'?! bar) |
+9 (foo; ?!LINT: missing '&&'?! bar) >baz &&
10
11 (foo || exit 1) &&
12 (foo || exit 1) |
13 (foo || exit 1) >baz &&
14
-15 (foo && bar) ?!AMP?!
+15 (foo && bar) ?!LINT: missing '&&'?!
16
-17 (foo && bar; ?!AMP?! baz) ?!AMP?!
+17 (foo && bar; ?!LINT: missing '&&'?! baz) ?!LINT: missing '&&'?!
18
19 foobar
20 )
diff --git a/t/chainlint/token-pasting.expect b/t/chainlint/token-pasting.expect
index 64f3235d26..387189b6de 100644
--- a/t/chainlint/token-pasting.expect
+++ b/t/chainlint/token-pasting.expect
@@ -2,13 +2,13 @@
3 git config filter.rot13.clean ./rot13.sh &&
4
5 {
-6 echo "*.t filter=rot13" ?!AMP?!
+6 echo "*.t filter=rot13" ?!LINT: missing '&&'?!
7 echo "*.i ident"
8 } >.gitattributes &&
9
10 {
-11 echo a b c d e f g h i j k l m ?!AMP?!
-12 echo n o p q r s t u v w x y z ?!AMP?!
+11 echo a b c d e f g h i j k l m ?!LINT: missing '&&'?!
+12 echo n o p q r s t u v w x y z ?!LINT: missing '&&'?!
13 echo '$Id$'
14 } >test &&
15 cat test >test.t &&
@@ -19,7 +19,7 @@
20 git checkout -- test test.t test.i &&
21
22 echo "content-test2" >test2.o &&
-23 echo "content-test3 - filename with special characters" >"test3 'sq',$x=.o" ?!AMP?!
+23 echo "content-test3 - filename with special characters" >"test3 'sq',$x=.o" ?!LINT: missing '&&'?!
24
25 downstream_url_for_sed=$(
26 printf "%sn" "$downstream_url" |
diff --git a/t/chainlint/unclosed-here-doc-indent.expect b/t/chainlint/unclosed-here-doc-indent.expect
index f78e23cb63..156906c85a 100644
--- a/t/chainlint/unclosed-here-doc-indent.expect
+++ b/t/chainlint/unclosed-here-doc-indent.expect
@@ -1,4 +1,4 @@
2 command_which_is_run &&
-3 cat >expect <<-\EOF ?!UNCLOSED-HEREDOC?! &&
+3 cat >expect <<-\EOF ?!LINT: unclosed heredoc?! &&
4 we forget to end the here-doc
5 command_which_is_gobbled
diff --git a/t/chainlint/unclosed-here-doc.expect b/t/chainlint/unclosed-here-doc.expect
index 51304672cf..752c608862 100644
--- a/t/chainlint/unclosed-here-doc.expect
+++ b/t/chainlint/unclosed-here-doc.expect
@@ -1,5 +1,5 @@
2 command_which_is_run &&
-3 cat >expect <<\EOF ?!UNCLOSED-HEREDOC?! &&
+3 cat >expect <<\EOF ?!LINT: unclosed heredoc?! &&
4 we try to end the here-doc below,
5 but the indentation throws us off
6 since the operator is not "<<-".
diff --git a/t/chainlint/while-loop.expect b/t/chainlint/while-loop.expect
index 5ffabd5a93..2ba5582165 100644
--- a/t/chainlint/while-loop.expect
+++ b/t/chainlint/while-loop.expect
@@ -1,14 +1,14 @@
2 (
3 while true
4 do
-5 echo foo ?!AMP?!
-6 cat <<-\EOF ?!LOOP?!
+5 echo foo ?!LINT: missing '&&'?!
+6 cat <<-\EOF ?!LINT: missing '|| exit 1'?!
7 bar
8 EOF
-9 done ?!AMP?!
+9 done ?!LINT: missing '&&'?!
10
11 while true; do
12 echo foo &&
-13 cat bar ?!LOOP?!
+13 cat bar ?!LINT: missing '|| exit 1'?!
14 done
15 )
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index e193079ed5..33247f0e92 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -96,7 +96,8 @@ int cmd__config(int argc, const char **argv)
struct config_set cs;
if (argc == 3 && !strcmp(argv[1], "read_early_config")) {
- read_early_config(early_config_cb, (void *)argv[2]);
+ read_early_config(the_repository, early_config_cb,
+ (void *)argv[2]);
return 0;
}
diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c
index fd6e6cc4a5..3129aa28fd 100644
--- a/t/helper/test-path-utils.c
+++ b/t/helper/test-path-utils.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "abspath.h"
#include "environment.h"
diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c
index ce5a94fbd3..29d4e9a755 100644
--- a/t/helper/test-reftable.c
+++ b/t/helper/test-reftable.c
@@ -6,16 +6,8 @@
#include "reftable/reftable-merged.h"
#include "reftable/reftable-reader.h"
#include "reftable/reftable-stack.h"
-#include "reftable/reftable-tests.h"
#include "test-tool.h"
-int cmd__reftable(int argc, const char **argv)
-{
- /* test from simple to complex. */
- stack_test_main(argc, argv);
- return 0;
-}
-
static void print_help(void)
{
printf("usage: dump [-st] arg\n\n"
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index 7005b7d0bf..1ebb69a5dc 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -26,6 +26,7 @@ static struct test_cmd cmds[] = {
{ "drop-caches", cmd__drop_caches },
{ "dump-cache-tree", cmd__dump_cache_tree },
{ "dump-fsmonitor", cmd__dump_fsmonitor },
+ { "dump-reftable", cmd__dump_reftable },
{ "dump-split-index", cmd__dump_split_index },
{ "dump-untracked-cache", cmd__dump_untracked_cache },
{ "env-helper", cmd__env_helper },
@@ -60,9 +61,7 @@ static struct test_cmd cmds[] = {
{ "read-graph", cmd__read_graph },
{ "read-midx", cmd__read_midx },
{ "ref-store", cmd__ref_store },
- { "reftable", cmd__reftable },
{ "rot13-filter", cmd__rot13_filter },
- { "dump-reftable", cmd__dump_reftable },
{ "regex", cmd__regex },
{ "repository", cmd__repository },
{ "revision-walking", cmd__revision_walking },
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index b51f79e774..21802ac27d 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -55,7 +55,6 @@ int cmd__read_graph(int argc, const char **argv);
int cmd__read_midx(int argc, const char **argv);
int cmd__ref_store(int argc, const char **argv);
int cmd__rot13_filter(int argc, const char **argv);
-int cmd__reftable(int argc, const char **argv);
int cmd__regex(int argc, const char **argv);
int cmd__repository(int argc, const char **argv);
int cmd__revision_walking(int argc, const char **argv);
diff --git a/t/interop/README b/t/interop/README
index 72d42bd856..4e0608f857 100644
--- a/t/interop/README
+++ b/t/interop/README
@@ -83,3 +83,10 @@ You can then use test_expect_success as usual, with a few differences:
should create one with the appropriate version of git.
At the end of the script, call test_done as usual.
+
+Some older versions may need a few build knobs tweaked (e.g., ancient
+versions of Git no longer build with modern OpenSSL). Your script can
+set MAKE_OPTS_A and MAKE_OPTS_B, which will be passed alongside
+GIT_INTEROP_MAKE_OPTS. Users can override them per-script by setting
+GIT_INTEROP_MAKE_OPTS_{A,B} in the environment, just like they can set
+GIT_TEST_VERSION_{A,B}.
diff --git a/t/interop/i5500-git-daemon.sh b/t/interop/i5500-git-daemon.sh
index 4d22e42f84..88712d1b5d 100755
--- a/t/interop/i5500-git-daemon.sh
+++ b/t/interop/i5500-git-daemon.sh
@@ -2,6 +2,7 @@
VERSION_A=.
VERSION_B=v1.0.0
+MAKE_OPTS_B="NO_OPENSSL=TooOld"
: ${LIB_GIT_DAEMON_PORT:=5500}
LIB_GIT_DAEMON_COMMAND='git.a daemon'
diff --git a/t/interop/interop-lib.sh b/t/interop/interop-lib.sh
index 62f4481b6e..1b5864d2a7 100644
--- a/t/interop/interop-lib.sh
+++ b/t/interop/interop-lib.sh
@@ -45,7 +45,7 @@ build_version () {
(
cd "$dir" &&
- make $GIT_INTEROP_MAKE_OPTS >&2 &&
+ make $2 $GIT_INTEROP_MAKE_OPTS >&2 &&
touch .built
) || return 1
@@ -76,9 +76,11 @@ generate_wrappers () {
VERSION_A=${GIT_TEST_VERSION_A:-$VERSION_A}
VERSION_B=${GIT_TEST_VERSION_B:-$VERSION_B}
+MAKE_OPTS_A=${GIT_INTEROP_MAKE_OPTS_A:-$MAKE_OPTS_A}
+MAKE_OPTS_B=${GIT_INTEROP_MAKE_OPTS_B:-$MAKE_OPTS_B}
-if ! DIR_A=$(build_version "$VERSION_A") ||
- ! DIR_B=$(build_version "$VERSION_B")
+if ! DIR_A=$(build_version "$VERSION_A" "$MAKE_OPTS_A") ||
+ ! DIR_B=$(build_version "$VERSION_B" "$MAKE_OPTS_B")
then
echo >&2 "fatal: unable to build git versions"
exit 1
diff --git a/t/run-test.sh b/t/run-test.sh
index 13c353b91b..63328ac630 100755
--- a/t/run-test.sh
+++ b/t/run-test.sh
@@ -10,7 +10,7 @@ case "$1" in
echo >&2 "ERROR: TEST_SHELL_PATH is empty or not set"
exit 1
fi
- exec "${TEST_SHELL_PATH}" "$@"
+ exec "${TEST_SHELL_PATH}" "$@" ${TEST_OPTIONS}
;;
*)
exec "$@"
diff --git a/t/t0032-reftable-unittest.sh b/t/t0032-reftable-unittest.sh
deleted file mode 100755
index 471cb37ac2..0000000000
--- a/t/t0032-reftable-unittest.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2020 Google LLC
-#
-
-test_description='reftable unittests'
-
-TEST_PASSES_SANITIZE_LEAK=true
-. ./test-lib.sh
-
-test_expect_success 'unittests' '
- TMPDIR=$(pwd) && export TMPDIR &&
- test-tool reftable
-'
-
-test_done
diff --git a/t/t0211-trace2-perf.sh b/t/t0211-trace2-perf.sh
index 070fe7a5da..dddc130560 100755
--- a/t/t0211-trace2-perf.sh
+++ b/t/t0211-trace2-perf.sh
@@ -337,7 +337,8 @@ test_expect_success 'expect def_params for query command' '
# remote-curl.c rather than git.c. Confirm that we get def_param
# events from both layers.
#
-test_expect_success 'expect def_params for remote-curl and _run_dashed_' '
+test_expect_success LIBCURL \
+ 'expect def_params for remote-curl and _run_dashed_' '
test_when_finished "rm prop.perf actual" &&
test_config_global "trace2.configParams" "cfg.prop.*" &&
@@ -366,7 +367,8 @@ test_expect_success 'expect def_params for remote-curl and _run_dashed_' '
# an executable built from http-fetch.c. Confirm that we get
# def_param events from both layers.
#
-test_expect_success 'expect def_params for http-fetch and _run_dashed_' '
+test_expect_success LIBCURL \
+ 'expect def_params for http-fetch and _run_dashed_' '
test_when_finished "rm prop.perf actual" &&
test_config_global "trace2.configParams" "cfg.prop.*" &&
diff --git a/t/t0610-reftable-basics.sh b/t/t0610-reftable-basics.sh
index 37510c2b2a..2d951c8ceb 100755
--- a/t/t0610-reftable-basics.sh
+++ b/t/t0610-reftable-basics.sh
@@ -423,6 +423,64 @@ test_expect_success 'ref transaction: fails gracefully when auto compaction fail
)
'
+test_expect_success 'ref transaction: timeout acquiring tables.list lock' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ >.git/reftable/tables.list.lock &&
+ test_must_fail git update-ref refs/heads/branch HEAD 2>err &&
+ test_grep "cannot lock references" err
+ )
+'
+
+test_expect_success 'ref transaction: retry acquiring tables.list lock' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ LOCK=.git/reftable/tables.list.lock &&
+ >$LOCK &&
+ {
+ ( sleep 1 && rm -f $LOCK ) &
+ } &&
+ git -c reftable.lockTimeout=5000 update-ref refs/heads/branch HEAD
+ )
+'
+
+test_expect_success 'ref transaction: many concurrent writers' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ # Set a high timeout such that a busy CI machine will not abort
+ # early. 10 seconds should hopefully be ample of time to make
+ # this non-flaky.
+ git config set reftable.lockTimeout 10000 &&
+ test_commit --no-tag initial &&
+
+ head=$(git rev-parse HEAD) &&
+ for i in $(test_seq 100)
+ do
+ printf "%s commit\trefs/heads/branch-%s\n" "$head" "$i" ||
+ return 1
+ done >expect &&
+ printf "%s commit\trefs/heads/main\n" "$head" >>expect &&
+
+ for i in $(test_seq 100)
+ do
+ { git update-ref refs/heads/branch-$i HEAD& } ||
+ return 1
+ done &&
+
+ wait &&
+ git for-each-ref --sort=v:refname >actual &&
+ test_cmp expect actual
+ )
+'
+
test_expect_success 'pack-refs: compacts tables' '
test_when_finished "rm -rf repo" &&
git init repo &&
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index eb32da2a7f..6e230b5487 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -2355,7 +2355,10 @@ test_expect_success 'advice.sparseIndexExpanded' '
mkdir -p sparse-index/deep/deeper2/deepest &&
touch sparse-index/deep/deeper2/deepest/bogus &&
git -C sparse-index status 2>err &&
- grep "The sparse index is expanding to a full index" err
+ grep "The sparse index is expanding to a full index" err &&
+
+ git -C sparse-index sparse-checkout disable 2>err &&
+ test_line_count = 0 err
'
test_expect_success 'cat-file -p' '
diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh
index 5cde79ef8c..517d6c8693 100755
--- a/t/t1305-config-include.sh
+++ b/t/t1305-config-include.sh
@@ -357,4 +357,44 @@ test_expect_success 'include cycles are detected' '
grep "exceeded maximum include depth" stderr
'
+test_expect_success 'onbranch with unborn branch' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ git config set includeIf.onbranch:"*".path config.inc &&
+ git config set -f .git/config.inc foo.bar baz &&
+ git config get foo.bar
+ )
+'
+
+test_expect_success 'onbranch with detached HEAD' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ git config set "includeIf.onbranch:*.path" config.inc &&
+ git config set -f .git/config.inc foo.bar baz &&
+ test_commit initial &&
+ git switch --detach HEAD &&
+ test_must_fail git config get foo.bar
+ )
+'
+
+test_expect_success 'onbranch without repository' '
+ test_when_finished "rm -f .gitconfig config.inc" &&
+ git config set -f .gitconfig "includeIf.onbranch:**.path" config.inc &&
+ git config set -f config.inc foo.bar baz &&
+ git config get foo.bar &&
+ test_must_fail nongit git config get foo.bar
+'
+
+test_expect_success 'onbranch without repository but explicit nonexistent Git directory' '
+ test_when_finished "rm -f .gitconfig config.inc" &&
+ git config set -f .gitconfig "includeIf.onbranch:**.path" config.inc &&
+ git config set -f config.inc foo.bar baz &&
+ git config get foo.bar &&
+ test_must_fail nongit git --git-dir=nonexistent config get foo.bar
+'
+
test_done
diff --git a/t/t1419-exclude-refs.sh b/t/t1419-exclude-refs.sh
index 1359574419..3256e4462f 100755
--- a/t/t1419-exclude-refs.sh
+++ b/t/t1419-exclude-refs.sh
@@ -8,12 +8,6 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
-if test_have_prereq !REFFILES
-then
- skip_all='skipping `git for-each-ref --exclude` tests; need files backend'
- test_done
-fi
-
for_each_ref__exclude () {
GIT_TRACE2_PERF=1 test-tool ref-store main \
for-each-ref--exclude "$@" >actual.raw
@@ -28,7 +22,14 @@ assert_jumps () {
local nr="$1"
local trace="$2"
- grep -q "name:jumps_made value:$nr$" $trace
+ case "$GIT_DEFAULT_REF_FORMAT" in
+ files)
+ grep -q "name:jumps_made value:$nr$" $trace;;
+ reftable)
+ grep -q "name:reseeks_made value:$nr$" $trace;;
+ *)
+ BUG "unhandled ref format $GIT_DEFAULT_REF_FORMAT";;
+ esac
}
assert_no_jumps () {
@@ -89,7 +90,14 @@ test_expect_success 'adjacent, non-overlapping excluded regions' '
for_each_ref refs/heads/foo refs/heads/quux >expect &&
test_cmp expect actual &&
- assert_jumps 1 perf
+ case "$GIT_DEFAULT_REF_FORMAT" in
+ files)
+ assert_jumps 1 perf;;
+ reftable)
+ assert_jumps 2 perf;;
+ *)
+ BUG "unhandled ref format $GIT_DEFAULT_REF_FORMAT";;
+ esac
'
test_expect_success 'overlapping excluded regions' '
@@ -106,7 +114,30 @@ test_expect_success 'several overlapping excluded regions' '
for_each_ref refs/heads/quux >expect &&
test_cmp expect actual &&
- assert_jumps 1 perf
+ case "$GIT_DEFAULT_REF_FORMAT" in
+ files)
+ assert_jumps 1 perf;;
+ reftable)
+ assert_jumps 3 perf;;
+ *)
+ BUG "unhandled ref format $GIT_DEFAULT_REF_FORMAT";;
+ esac
+'
+
+test_expect_success 'unordered excludes' '
+ for_each_ref__exclude refs/heads \
+ refs/heads/foo refs/heads/baz >actual 2>perf &&
+ for_each_ref refs/heads/bar refs/heads/quux >expect &&
+
+ test_cmp expect actual &&
+ case "$GIT_DEFAULT_REF_FORMAT" in
+ files)
+ assert_jumps 1 perf;;
+ reftable)
+ assert_jumps 2 perf;;
+ *)
+ BUG "unhandled ref format $GIT_DEFAULT_REF_FORMAT";;
+ esac
'
test_expect_success 'non-matching excluded section' '
diff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh
index 990a036582..342defbb61 100755
--- a/t/t1517-outside-repo.sh
+++ b/t/t1517-outside-repo.sh
@@ -98,7 +98,7 @@ test_expect_success 'stripspace outside repository' '
nongit git stripspace -s </dev/null
'
-test_expect_success 'remote-http outside repository' '
+test_expect_success LIBCURL 'remote-http outside repository' '
test_must_fail git remote-http 2>actual &&
test_grep "^error: remote-curl" actual &&
(
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index bd8bcc381a..09f230eefb 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -145,7 +145,9 @@ test_expect_success 'Show verbose error when HEAD could not be detached' '
test_when_finished "rm -f B" &&
test_must_fail git rebase topic 2>output.err >output.out &&
test_grep "The following untracked working tree files would be overwritten by checkout:" output.err &&
- test_grep B output.err
+ test_grep B output.err &&
+ test_must_fail git rebase --quit 2>err &&
+ test_grep "no rebase in progress" err
'
test_expect_success 'fail when upstream arg is missing and not on branch' '
@@ -428,7 +430,9 @@ test_expect_success 'refuse to switch to branch checked out elsewhere' '
git checkout main &&
git worktree add wt &&
test_must_fail git -C wt rebase main main 2>err &&
- test_grep "already used by worktree at" err
+ test_grep "already used by worktree at" err &&
+ test_must_fail git -C wt rebase --quit 2>err &&
+ test_grep "no rebase in progress" err
'
test_expect_success 'rebase when inside worktree subdirectory' '
diff --git a/t/t3413-rebase-hook.sh b/t/t3413-rebase-hook.sh
index e8456831e8..426ff098e1 100755
--- a/t/t3413-rebase-hook.sh
+++ b/t/t3413-rebase-hook.sh
@@ -110,7 +110,9 @@ test_expect_success 'pre-rebase hook stops rebase (1)' '
git reset --hard side &&
test_must_fail git rebase main &&
test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
- test 0 = $(git rev-list HEAD...side | wc -l)
+ test 0 = $(git rev-list HEAD...side | wc -l) &&
+ test_must_fail git rebase --quit 2>err &&
+ test_grep "no rebase in progress" err
'
test_expect_success 'pre-rebase hook stops rebase (2)' '
diff --git a/t/t3420-rebase-autostash.sh b/t/t3420-rebase-autostash.sh
index 63e400b89f..b43046b3b0 100755
--- a/t/t3420-rebase-autostash.sh
+++ b/t/t3420-rebase-autostash.sh
@@ -82,6 +82,46 @@ testrebase () {
type=$1
dotest=$2
+ test_expect_success "rebase$type: restore autostash when pre-rebase hook fails" '
+ git checkout -f feature-branch &&
+ test_hook pre-rebase <<-\EOF &&
+ exit 1
+ EOF
+
+ echo changed >file0 &&
+ test_must_fail git rebase $type --autostash -f HEAD^ &&
+ test_must_fail git rebase --quit 2>err &&
+ test_grep "no rebase in progress" err &&
+ echo changed >expect &&
+ test_cmp expect file0
+ '
+
+ test_expect_success "rebase$type: restore autostash when checkout onto fails" '
+ git checkout -f --detach feature-branch &&
+ echo uncommitted-content >file0 &&
+ echo untracked >file4 &&
+ test_when_finished "rm file4" &&
+ test_must_fail git rebase $type --autostash \
+ unrelated-onto-branch &&
+ test_must_fail git rebase --quit 2>err &&
+ test_grep "no rebase in progress" err &&
+ echo uncommitted-content >expect &&
+ test_cmp expect file0
+ '
+
+ test_expect_success "rebase$type: restore autostash when branch checkout fails" '
+ git checkout -f unrelated-onto-branch^ &&
+ echo uncommitted-content >file0 &&
+ echo untracked >file4 &&
+ test_when_finished "rm file4" &&
+ test_must_fail git rebase $type --autostash HEAD \
+ unrelated-onto-branch &&
+ test_must_fail git rebase --quit 2>err &&
+ test_grep "no rebase in progress" err &&
+ echo uncommitted-content >expect &&
+ test_cmp expect file0
+ '
+
test_expect_success "rebase$type: dirty worktree, --no-autostash" '
test_config rebase.autostash true &&
git reset --hard &&
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 94671d3c46..4d9744e5fc 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -5,6 +5,7 @@
test_description='tests to ensure compatibility between am and interactive backends'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
diff --git a/t/t4017-diff-retval.sh b/t/t4017-diff-retval.sh
index d644310e22..1cea73ef5a 100755
--- a/t/t4017-diff-retval.sh
+++ b/t/t4017-diff-retval.sh
@@ -145,6 +145,14 @@ test_expect_success 'option errors are not confused by --exit-code' '
for option in --exit-code --quiet
do
+ test_expect_success "git diff $option returns 1 for changed binary file" "
+ test_when_finished 'rm -f .gitattributes' &&
+ git reset --hard &&
+ echo a binary >.gitattributes &&
+ echo 2 >>a &&
+ test_expect_code 1 git diff $option
+ "
+
test_expect_success "git diff $option returns 1 for copied file" "
git reset --hard &&
cp a copy &&
diff --git a/t/t4107-apply-ignore-whitespace.sh b/t/t4107-apply-ignore-whitespace.sh
index ac72eeaf27..5e6e203aa5 100755
--- a/t/t4107-apply-ignore-whitespace.sh
+++ b/t/t4107-apply-ignore-whitespace.sh
@@ -3,9 +3,9 @@
# Copyright (c) 2009 Giuseppe Bilotta
#
-test_description='git-apply --ignore-whitespace.
+test_description='git-apply --ignore-whitespace.'
-'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# This primes main.c file that indents without using HT at all.
diff --git a/t/t4108-apply-threeway.sh b/t/t4108-apply-threeway.sh
index 3211e1e65f..c6302163d8 100755
--- a/t/t4108-apply-threeway.sh
+++ b/t/t4108-apply-threeway.sh
@@ -82,6 +82,46 @@ test_expect_success 'apply with --3way with merge.conflictStyle = diff3' '
test_apply_with_3way
'
+test_apply_with_3way_favoritism () {
+ apply_arg=$1
+ merge_arg=$2
+
+ # Merging side should be similar to applying this patch
+ git diff ...side >P.diff &&
+
+ # The corresponding conflicted merge
+ git reset --hard &&
+ git checkout main^0 &&
+ git merge --no-commit $merge_arg side &&
+ git ls-files -s >expect.ls &&
+ print_sanitized_conflicted_diff >expect.diff &&
+
+ # should apply successfully
+ git reset --hard &&
+ git checkout main^0 &&
+ git apply --index --3way $apply_arg P.diff &&
+ git ls-files -s >actual.ls &&
+ print_sanitized_conflicted_diff >actual.diff &&
+
+ # The result should resemble the corresponding merge
+ test_cmp expect.ls actual.ls &&
+ test_cmp expect.diff actual.diff
+}
+
+test_expect_success 'apply with --3way --ours' '
+ test_apply_with_3way_favoritism --ours -Xours
+'
+
+test_expect_success 'apply with --3way --theirs' '
+ test_apply_with_3way_favoritism --theirs -Xtheirs
+'
+
+test_expect_success 'apply with --3way --union' '
+ echo "* merge=union" >.gitattributes &&
+ test_apply_with_3way_favoritism --union &&
+ rm .gitattributes
+'
+
test_expect_success 'apply with --3way with rerere enabled' '
test_config rerere.enabled true &&
diff --git a/t/t4124-apply-ws-rule.sh b/t/t4124-apply-ws-rule.sh
index 485c7d2d12..cdffee0273 100755
--- a/t/t4124-apply-ws-rule.sh
+++ b/t/t4124-apply-ws-rule.sh
@@ -2,6 +2,7 @@
test_description='core.whitespace rules and git apply'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
prepare_test_file () {
diff --git a/t/t4125-apply-ws-fuzz.sh b/t/t4125-apply-ws-fuzz.sh
index 090987c89b..f248cc2a00 100755
--- a/t/t4125-apply-ws-fuzz.sh
+++ b/t/t4125-apply-ws-fuzz.sh
@@ -2,6 +2,7 @@
test_description='applying patch that has broken whitespaces in context'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t4138-apply-ws-expansion.sh b/t/t4138-apply-ws-expansion.sh
index 8bbf8260fa..7981931b4e 100755
--- a/t/t4138-apply-ws-expansion.sh
+++ b/t/t4138-apply-ws-expansion.sh
@@ -5,6 +5,7 @@
test_description='git apply test patches with whitespace expansion.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh
index c0a4a02dcf..8e0f283c2b 100755
--- a/t/t4204-patch-id.sh
+++ b/t/t4204-patch-id.sh
@@ -115,46 +115,6 @@ test_expect_success 'patch-id supports git-format-patch output' '
test "$2" = $(git rev-parse HEAD)
'
-test_expect_success 'patch-id computes the same for various formats' '
- # This test happens to consider "git log -p -1" output
- # the canonical input format, so use it as the norm.
- git log -1 -p same >log-p.output &&
- git patch-id <log-p.output >expect &&
-
- # format-patch begins with "From <commit object name>"
- git format-patch -1 --stdout same >format-patch.output &&
- git patch-id <format-patch.output >actual &&
- test_cmp actual expect &&
-
- # "diff-tree --stdin -p" begins with "<commit object name>"
- same=$(git rev-parse same) &&
- echo $same | git diff-tree --stdin -p >diff-tree.output &&
- git patch-id <diff-tree.output >actual &&
- test_cmp actual expect &&
-
- # "diff-tree --stdin -v -p" begins with "commit <commit object name>"
- echo $same | git diff-tree --stdin -p -v >diff-tree-v.output &&
- git patch-id <diff-tree-v.output >actual &&
- test_cmp actual expect
-'
-
-hash=$(git rev-parse same:)
-for cruft in "$hash" "commit $hash is bad" "From $hash status"
-do
- test_expect_success "patch-id with <$cruft> in log message" '
- git format-patch -1 --stdout same >patch-0 &&
- git patch-id <patch-0 >expect &&
-
- {
- sed -e "/^$/q" patch-0 &&
- printf "random message\n%s\n\n" "$cruft" &&
- sed -e "1,/^$/d" patch-0
- } >patch-cruft &&
- git patch-id <patch-cruft >actual &&
- test_cmp actual expect
- '
-done
-
test_expect_success 'whitespace is irrelevant in footer' '
get_patch_id main &&
git checkout same &&
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index 7abba8a4b2..b9fda973f7 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -137,6 +137,8 @@ test_expect_success 'end-of-options is correctly eaten' '
test_expect_success 'populate workdir' '
mkdir a &&
+ echo "a files_named_a" >.gitattributes &&
+ git add .gitattributes &&
echo simple textfile >a/a &&
ten=0123456789 &&
hundred="$ten$ten$ten$ten$ten$ten$ten$ten$ten$ten" &&
@@ -450,6 +452,16 @@ test_expect_success 'allow pathspecs that resolve to the current directory' '
test_cmp expect actual
'
+test_expect_success 'attr pathspec in bare repo' '
+ test_expect_code 0 git --git-dir=bare.git archive -v HEAD \
+ ":(attr:files_named_a)" >/dev/null 2>actual &&
+ cat >expect <<-\EOF &&
+ a/
+ a/a
+ EOF
+ test_cmp expect actual
+'
+
# Pull the size and date of each entry in a tarfile using the system tar.
#
# We'll pull out only the year from the date; that avoids any question of
diff --git a/t/t5509-fetch-push-namespaces.sh b/t/t5509-fetch-push-namespaces.sh
index 05090feaf9..f029ae0d28 100755
--- a/t/t5509-fetch-push-namespaces.sh
+++ b/t/t5509-fetch-push-namespaces.sh
@@ -96,6 +96,7 @@ test_expect_success 'hide namespaced refs with transfer.hideRefs' '
'
test_expect_success 'check that transfer.hideRefs does not match unstripped refs' '
+ git -C pushee pack-refs --all &&
GIT_NAMESPACE=namespace \
git -C pushee -c transfer.hideRefs=refs/namespaces/namespace/refs/tags \
ls-remote "ext::git %s ." >actual &&
@@ -123,6 +124,14 @@ test_expect_success 'try to update a ref that is not hidden' '
git -C original push pushee-namespaced main
'
+test_expect_success 'git-receive-pack(1) with transfer.hideRefs does not match unstripped refs during advertisement' '
+ git -C pushee update-ref refs/namespaces/namespace/refs/heads/foo/1 refs/namespaces/namespace/refs/heads/main &&
+ git -C pushee pack-refs --all &&
+ test_config -C pushee transfer.hideRefs refs/namespaces/namespace/refs/heads/foo &&
+ GIT_TRACE_PACKET="$(pwd)/trace" git -C original push pushee-namespaced main &&
+ test_grep refs/heads/foo/1 trace
+'
+
test_expect_success 'try to update a hidden full ref' '
test_config -C pushee transfer.hideRefs "^refs/namespaces/namespace/refs/heads/main" &&
test_must_fail git -C original push pushee-namespaced main
diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
index d64b40e408..64b3491e4e 100755
--- a/t/t5512-ls-remote.sh
+++ b/t/t5512-ls-remote.sh
@@ -406,6 +406,7 @@ test_expect_success 'v0 clients can handle multiple symrefs' '
test_expect_success 'helper with refspec capability fails gracefully' '
mkdir test-bin &&
write_script test-bin/git-remote-foo <<-EOF &&
+ read capabilities
echo import
echo refspec ${SQ}*:*${SQ}
EOF
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
index 7b5ab0eae1..ceb3336a5c 100755
--- a/t/t5551-http-fetch-smart.sh
+++ b/t/t5551-http-fetch-smart.sh
@@ -186,6 +186,28 @@ test_expect_success 'clone from password-protected repository' '
test_cmp expect actual
'
+test_expect_success 'credential.interactive=false skips askpass' '
+ set_askpass bogus nonsense &&
+ (
+ GIT_TRACE2_EVENT="$(pwd)/interactive-true" &&
+ export GIT_TRACE2_EVENT &&
+ test_must_fail git clone --bare "$HTTPD_URL/auth/smart/repo.git" interactive-true-dir &&
+ test_region credential interactive interactive-true &&
+
+ GIT_TRACE2_EVENT="$(pwd)/interactive-false" &&
+ export GIT_TRACE2_EVENT &&
+ test_must_fail git -c credential.interactive=false \
+ clone --bare "$HTTPD_URL/auth/smart/repo.git" interactive-false-dir &&
+ test_region ! credential interactive interactive-false &&
+
+ GIT_TRACE2_EVENT="$(pwd)/interactive-never" &&
+ export GIT_TRACE2_EVENT &&
+ test_must_fail git -c credential.interactive=never \
+ clone --bare "$HTTPD_URL/auth/smart/repo.git" interactive-never-dir &&
+ test_region ! credential interactive interactive-never
+ )
+'
+
test_expect_success 'clone from auth-only-for-push repository' '
echo two >expect &&
set_askpass wrong &&
diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index 20f43f7b7d..d21877150e 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -344,4 +344,15 @@ test_expect_success 'fetch tag' '
compare_refs local v1.0 server v1.0
'
+test_expect_success 'totally broken helper reports failure message' '
+ write_script git-remote-broken <<-\EOF &&
+ read cap_cmd
+ exit 1
+ EOF
+ test_must_fail \
+ env PATH="$PWD:$PATH" \
+ git clone broken://example.com/foo.git 2>stderr &&
+ grep aborted stderr
+'
+
test_done
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index 8d15713cc6..b3163629c5 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -5,6 +5,7 @@
test_description='for-each-ref test'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
GNUPGHOME_NOT_USED=$GNUPGHOME
. "$TEST_DIRECTORY"/lib-gpg.sh
@@ -1560,6 +1561,25 @@ test_trailer_option '%(trailers:separator,key_value_separator) changes both sepa
Reviewed-by,A U Thor <author@example.com>,Signed-off-by,A U Thor <author@example.com>
EOF
+test_expect_success 'multiple %(trailers) use their own options' '
+ git tag -F - tag-with-trailers <<-\EOF &&
+ body
+
+ one: foo
+ one: bar
+ two: baz
+ two: qux
+ EOF
+ t1="%(trailers:key=one,key_value_separator=W,separator=X)" &&
+ t2="%(trailers:key=two,key_value_separator=Y,separator=Z)" &&
+ git for-each-ref --format="$t1%0a$t2" refs/tags/tag-with-trailers >actual &&
+ cat >expect <<-\EOF &&
+ oneWfooXoneWbar
+ twoYbazZtwoYqux
+ EOF
+ test_cmp expect actual
+'
+
test_failing_trailer_option () {
title=$1 option=$2
cat >expect
@@ -1835,6 +1855,24 @@ sig_crlf="$(printf "%s" "$sig" | append_cr; echo dummy)"
sig_crlf=${sig_crlf%dummy}
test_atom refs/tags/fake-sig-crlf contents:signature "$sig_crlf"
+test_expect_success 'set up tag with signature and trailers' '
+ git tag -F - fake-sig-trailer <<-\EOF
+ this is the subject
+
+ this is the body
+
+ My-Trailer: foo
+ -----BEGIN PGP SIGNATURE-----
+
+ not a real signature, but we just care about the
+ subject/body/trailer parsing.
+ -----END PGP SIGNATURE-----
+ EOF
+'
+
+# use "separator=" here to suppress the terminating newline
+test_atom refs/tags/fake-sig-trailer trailers:separator= 'My-Trailer: foo'
+
test_expect_success 'git for-each-ref --stdin: empty' '
>in &&
git for-each-ref --format="%(refname)" --stdin <in >actual &&
@@ -2003,8 +2041,7 @@ test_expect_success GPG 'show good signature with custom format' '
--format="$GRADE_FORMAT" >actual &&
test_cmp expect actual
'
-test_expect_success GPGSSH 'show good signature with custom format
- with ssh' '
+test_expect_success GPGSSH 'show good signature with custom format with ssh' '
test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
FINGERPRINT=$(ssh-keygen -lf "${GPGSSH_KEY_PRIMARY}" | awk "{print \$2;}") &&
cat >expect.tmpl <<-\EOF &&
diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
index 163c378cfd..7f44d3c3f2 100755
--- a/t/t6302-for-each-ref-filter.sh
+++ b/t/t6302-for-each-ref-filter.sh
@@ -2,6 +2,7 @@
test_description='test for-each-refs usage of ref-filter APIs'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-gpg.sh
diff --git a/t/t7422-submodule-output.sh b/t/t7422-submodule-output.sh
index ab946ec940..c1686d6bb5 100755
--- a/t/t7422-submodule-output.sh
+++ b/t/t7422-submodule-output.sh
@@ -167,4 +167,11 @@ do
'
done
+test_expect_success !MINGW 'git submodule status --recursive propagates SIGPIPE' '
+ { git submodule status --recursive 2>err; echo $?>status; } |
+ grep -q X/S &&
+ test_must_be_empty err &&
+ test_match_signal 13 "$(cat status)"
+'
+
test_done
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index c62c42848a..a66d0e089d 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -826,6 +826,9 @@ test_expect_success 'start and stop Linux/systemd maintenance' '
test_systemd_analyze_verify "systemd/user/git-maintenance@daily.service" &&
test_systemd_analyze_verify "systemd/user/git-maintenance@weekly.service" &&
+ grep "core.askPass=true" "systemd/user/git-maintenance@.service" &&
+ grep "credential.interactive=false" "systemd/user/git-maintenance@.service" &&
+
printf -- "--user enable --now git-maintenance@%s.timer\n" hourly daily weekly >expect &&
test_cmp expect args &&
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index df5336bb7e..e2430f7bfa 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -1324,7 +1324,7 @@ test_expect_success $PREREQ 'cc list is sanitized' '
Reviewed-by: Füñný Nâmé <odd_?=mail@example.com>
Reported-by: bugger on Jira
Reported-by: Douglas Reporter <doug@example.com> [from Jira profile]
- BugID: 12345
+ BugID: 12345should-not-appear
Co-developed-by: "C. O. Developer" <codev@example.com>
Signed-off-by: A. U. Thor <thor.au@example.com>
EOF
@@ -1337,7 +1337,7 @@ test_expect_success $PREREQ 'cc list is sanitized' '
" <odd_?=mail@example.com>" actual-show-all-headers &&
test_grep "^(body) Ignoring Reported-by .* bugger on Jira" actual-show-all-headers &&
test_grep "^(body) Adding cc: Douglas Reporter <doug@example.com>" actual-show-all-headers &&
- test_grep ! "12345" actual-show-all-headers &&
+ test_grep ! "12345should-not-appear" actual-show-all-headers &&
test_grep "^(body) Adding cc: \"C. O. Developer\" <codev@example.com>" actual-show-all-headers &&
test_grep "^(body) Adding cc: \"A. U. Thor\" <thor.au@example.com>" actual-show-all-headers
'
diff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh
index e8613990e1..027235d61a 100755
--- a/t/t9210-scalar.sh
+++ b/t/t9210-scalar.sh
@@ -194,8 +194,11 @@ test_expect_success 'scalar reconfigure' '
scalar reconfigure one &&
test true = "$(git -C one/src config core.preloadIndex)" &&
git -C one/src config core.preloadIndex false &&
- scalar reconfigure -a &&
- test true = "$(git -C one/src config core.preloadIndex)"
+ rm one/src/cron.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/reconfigure" scalar reconfigure -a &&
+ test_path_is_file one/src/cron.txt &&
+ test true = "$(git -C one/src config core.preloadIndex)" &&
+ test_subcommand git maintenance start <reconfigure
'
test_expect_success 'scalar reconfigure --all with includeIf.onbranch' '
diff --git a/t/t9700-perl-git.sh b/t/t9700-perl-git.sh
index ccc8212d73..4431697122 100755
--- a/t/t9700-perl-git.sh
+++ b/t/t9700-perl-git.sh
@@ -45,7 +45,8 @@ test_expect_success 'set up test repository' '
'
test_expect_success 'set up bare repository' '
- git init --bare bare.git
+ git init --bare bare.git &&
+ git -C bare.git --work-tree=. commit --allow-empty -m "bare commit"
'
test_expect_success 'use t9700/test.pl to test Git.pm' '
diff --git a/t/t9700/test.pl b/t/t9700/test.pl
index d8e85482ab..2e1d50d4d1 100755
--- a/t/t9700/test.pl
+++ b/t/t9700/test.pl
@@ -147,6 +147,11 @@ close TEMPFILE3;
unlink $tmpfile3;
chdir($abs_repo_dir);
+# open alternate bare repo
+my $r4 = Git->repository(Directory => "$abs_repo_dir/bare.git");
+is($r4->command_oneline(qw(log --format=%s)), "bare commit",
+ "log of bare repo works");
+
# unquoting paths
is(Git::unquote_path('abc'), 'abc', 'unquote unquoted path');
is(Git::unquote_path('"abc def"'), 'abc def', 'unquote simple quoted path');
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 64bd36531c..e718efe4c6 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -1615,7 +1615,7 @@ if test "${GIT_TEST_CHAIN_LINT:-1}" != 0 &&
test "${GIT_TEST_EXT_CHAIN_LINT:-1}" != 0
then
"$PERL_PATH" "$TEST_DIRECTORY/chainlint.pl" "$0" ||
- BUG "lint error (see '?!...!? annotations above)"
+ BUG "lint error (see 'LINT' annotations above)"
fi
# Last-minute variable setup
diff --git a/t/unit-tests/.gitignore b/t/unit-tests/.gitignore
index 5e56e040ec..d0632ec7f9 100644
--- a/t/unit-tests/.gitignore
+++ b/t/unit-tests/.gitignore
@@ -1 +1,3 @@
/bin
+/clar.suite
+/clar-decls.h
diff --git a/t/unit-tests/clar-generate.awk b/t/unit-tests/clar-generate.awk
new file mode 100644
index 0000000000..ab71ce6c9f
--- /dev/null
+++ b/t/unit-tests/clar-generate.awk
@@ -0,0 +1,50 @@
+function add_suite(suite, initialize, cleanup, count) {
+ if (!suite) return
+ suite_count++
+ callback_count += count
+ suites = suites " {\n"
+ suites = suites " \"" suite "\",\n"
+ suites = suites " " initialize ",\n"
+ suites = suites " " cleanup ",\n"
+ suites = suites " _clar_cb_" suite ", " count ", 1\n"
+ suites = suites " },\n"
+}
+
+BEGIN {
+ suites = "static struct clar_suite _clar_suites[] = {\n"
+}
+
+{
+ print
+ name = $3; sub(/\(.*$/, "", name)
+ suite = name; sub(/^test_/, "", suite); sub(/__.*$/, "", suite)
+ short_name = name; sub(/^.*__/, "", short_name)
+ cb = "{ \"" short_name "\", &" name " }"
+ if (suite != prev_suite) {
+ add_suite(prev_suite, initialize, cleanup, count)
+ if (callbacks) callbacks = callbacks "};\n"
+ callbacks = callbacks "static const struct clar_func _clar_cb_" suite "[] = {\n"
+ initialize = "{ NULL, NULL }"
+ cleanup = "{ NULL, NULL }"
+ count = 0
+ prev_suite = suite
+ }
+ if (short_name == "initialize") {
+ initialize = cb
+ } else if (short_name == "cleanup") {
+ cleanup = cb
+ } else {
+ callbacks = callbacks " " cb ",\n"
+ count++
+ }
+}
+
+END {
+ add_suite(suite, initialize, cleanup, count)
+ suites = suites "};"
+ if (callbacks) callbacks = callbacks "};"
+ print callbacks
+ print suites
+ print "static const size_t _clar_suite_count = " suite_count ";"
+ print "static const size_t _clar_callback_count = " callback_count ";"
+}
diff --git a/t/unit-tests/clar/.github/workflows/ci.yml b/t/unit-tests/clar/.github/workflows/ci.yml
new file mode 100644
index 0000000000..b1ac2de460
--- /dev/null
+++ b/t/unit-tests/clar/.github/workflows/ci.yml
@@ -0,0 +1,23 @@
+name: CI
+
+on:
+ push:
+ branches: [ main ]
+ pull_request:
+ branches: [ main ]
+
+jobs:
+ build:
+ strategy:
+ matrix:
+ os: [ ubuntu-latest, macos-latest ]
+
+ runs-on: ${{ matrix.os }}
+
+ steps:
+ - name: Check out
+ uses: actions/checkout@v2
+ - name: Build
+ run: |
+ cd test
+ make
diff --git a/t/unit-tests/clar/COPYING b/t/unit-tests/clar/COPYING
new file mode 100644
index 0000000000..8983817f0c
--- /dev/null
+++ b/t/unit-tests/clar/COPYING
@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) 2011-2015 Vicent Marti
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/t/unit-tests/clar/README.md b/t/unit-tests/clar/README.md
new file mode 100644
index 0000000000..a8961c5f10
--- /dev/null
+++ b/t/unit-tests/clar/README.md
@@ -0,0 +1,329 @@
+Come out and Clar
+=================
+
+In Catalan, "clar" means clear, easy to perceive. Using clar will make it
+easy to test and make clear the quality of your code.
+
+> _Historical note_
+>
+> Originally the clar project was named "clay" because the word "test" has its
+> roots in the latin word *"testum"*, meaning "earthen pot", and *"testa"*,
+> meaning "piece of burned clay"?
+>
+> This is because historically, testing implied melting metal in a pot to
+> check its quality. Clay is what tests are made of.
+
+## Quick Usage Overview
+
+Clar is a minimal C unit testing framework. It's been written to replace the
+old framework in [libgit2][libgit2], but it's both very versatile and
+straightforward to use.
+
+Can you count to funk?
+
+- **Zero: Initialize test directory**
+
+ ~~~~ sh
+ $ mkdir tests
+ $ cp -r $CLAR_ROOT/clar* tests
+ $ cp $CLAR_ROOT/test/clar_test.h tests
+ $ cp $CLAR_ROOT/test/main.c.sample tests/main.c
+ ~~~~
+
+- **One: Write some tests**
+
+ File: tests/adding.c:
+
+ ~~~~ c
+ /* adding.c for the "Adding" suite */
+ #include "clar.h"
+
+ static int *answer;
+
+ void test_adding__initialize(void)
+ {
+ answer = malloc(sizeof(int));
+ cl_assert_(answer != NULL, "No memory left?");
+ *answer = 42;
+ }
+
+ void test_adding__cleanup(void)
+ {
+ free(answer);
+ }
+
+ void test_adding__make_sure_math_still_works(void)
+ {
+ cl_assert_(5 > 3, "Five should probably be greater than three");
+ cl_assert_(-5 < 2, "Negative numbers are small, I think");
+ cl_assert_(*answer == 42, "The universe is doing OK. And the initializer too.");
+ }
+ ~~~~~
+
+- **Two: Build the test executable**
+
+ ~~~~ sh
+ $ cd tests
+ $ $CLAR_PATH/generate.py .
+ Written `clar.suite` (1 suites)
+ $ gcc -I. clar.c main.c adding.c -o testit
+ ~~~~
+
+- **Funk: Funk it.**
+
+ ~~~~ sh
+ $ ./testit
+ ~~~~
+
+## The Clar Test Suite
+
+Writing a test suite is pretty straightforward. Each test suite is a `*.c`
+file with a descriptive name: this encourages modularity.
+
+Each test suite has optional initialize and cleanup methods. These methods
+will be called before and after running **each** test in the suite, even if
+such test fails. As a rule of thumb, if a test needs a different initializer
+or cleanup method than another test in the same module, that means it
+doesn't belong in that module. Keep that in mind when grouping tests
+together.
+
+The `initialize` and `cleanup` methods have the following syntax, with
+`suitename` being the current suite name, e.g. `adding` for the `adding.c`
+suite.
+
+~~~~ c
+void test_suitename__initialize(void)
+{
+ /* init */
+}
+
+void test_suitename__cleanup(void)
+{
+ /* cleanup */
+}
+~~~~
+
+These methods are encouraged to use static, global variables to store the state
+that will be used by all tests inside the suite.
+
+~~~~ c
+static git_repository *_repository;
+
+void test_status__initialize(void)
+{
+ create_tmp_repo(STATUS_REPO);
+ git_repository_open(_repository, STATUS_REPO);
+}
+
+void test_status__cleanup(void)
+{
+ git_repository_close(_repository);
+ git_path_rm(STATUS_REPO);
+}
+
+void test_status__simple_test(void)
+{
+ /* do something with _repository */
+}
+~~~~
+
+Writing the actual tests is just as straightforward. Tests have the
+`void test_suitename__test_name(void)` signature, and they should **not**
+be static. Clar will automatically detect and list them.
+
+Tests are run as they appear on their original suites: they have no return
+value. A test is considered "passed" if it doesn't raise any errors. Check
+the "Clar API" section to see the various helper functions to check and
+raise errors during test execution.
+
+__Caution:__ If you use assertions inside of `test_suitename__initialize`,
+make sure that you do not rely on `__initialize` being completely run
+inside your `test_suitename__cleanup` function. Otherwise you might
+encounter ressource cleanup twice.
+
+## How does Clar work?
+
+To use Clar:
+
+1. copy the Clar boilerplate to your test directory
+2. copy (and probably modify) the sample `main.c` (from
+ `$CLAR_PATH/test/main.c.sample`)
+3. run the Clar mixer (a.k.a. `generate.py`) to scan your test directory and
+ write out the test suite metadata.
+4. compile your test files and the Clar boilerplate into a single test
+ executable
+5. run the executable to test!
+
+The Clar boilerplate gives you a set of useful test assertions and features
+(like accessing or making sandbox copies of fixture data). It consists of
+the `clar.c` and `clar.h` files, plus the code in the `clar/` subdirectory.
+You should not need to edit these files.
+
+The sample `main.c` (i.e. `$CLAR_PATH/test/main.c.sample`) file invokes
+`clar_test(argc, argv)` to run the tests. Usually, you will edit this file
+to perform any framework specific initialization and teardown that you need.
+
+The Clar mixer (`generate.py`) recursively scans your test directory for
+any `.c` files, parses them, and writes the `clar.suite` file with all of
+the metadata about your tests. When you build, the `clar.suite` file is
+included into `clar.c`.
+
+The mixer can be run with **Python 2.5, 2.6, 2.7, 3.0, 3.1, 3.2 and PyPy 1.6**.
+
+Commandline usage of the mixer is as follows:
+
+ $ ./generate.py .
+
+Where `.` is the folder where all the test suites can be found. The mixer
+will automatically locate all the relevant source files and build the
+testing metadata. The metadata will be written to `clar.suite`, in the same
+folder as all the test suites. This file is included by `clar.c` and so
+must be accessible via `#include` when building the test executable.
+
+ $ gcc -I. clar.c main.c suite1.c test2.c -o run_tests
+
+**Note that the Clar mixer only needs to be ran when adding new tests to a
+suite, in order to regenerate the metadata**. As a result, the `clar.suite`
+file can be checked into version control if you wish to be able to build
+your test suite without having to re-run the mixer.
+
+This is handy when e.g. generating tests in a local computer, and then
+building and testing them on an embedded device or a platform where Python
+is not available.
+
+### Fixtures
+
+Clar can create sandboxed fixtures for you to use in your test. You'll need to compile *clar.c* with an additional `CFLAG`, `-DCLAR_FIXTURE_PATH`. This should be an absolute path to your fixtures directory.
+
+Once that's done, you can use the fixture API as defined below.
+
+## The Clar API
+
+Clar makes the following methods available from all functions in a test
+suite.
+
+- `cl_must_pass(call)`, `cl_must_pass_(call, message)`: Verify that the given
+ function call passes, in the POSIX sense (returns a value greater or equal
+ to 0).
+
+- `cl_must_fail(call)`, `cl_must_fail_(call, message)`: Verify that the given
+ function call fails, in the POSIX sense (returns a value less than 0).
+
+- `cl_assert(expr)`, `cl_assert_(expr, message)`: Verify that `expr` is true.
+
+- `cl_check_pass(call)`, `cl_check_pass_(call, message)`: Verify that the
+ given function call passes, in the POSIX sense (returns a value greater or
+ equal to 0). If the function call doesn't succeed, a test failure will be
+ logged but the test's execution will continue.
+
+- `cl_check_fail(call)`, `cl_check_fail_(call, message)`: Verify that the
+ given function call fails, in the POSIX sense (returns a value less than
+ 0). If the function call doesn't fail, a test failure will be logged but
+ the test's execution will continue.
+
+- `cl_check(expr)`: Verify that `expr` is true. If `expr` is not
+ true, a test failure will be logged but the test's execution will continue.
+
+- `cl_fail(message)`: Fail the current test with the given message.
+
+- `cl_warning(message)`: Issue a warning. This warning will be
+ logged as a test failure but the test's execution will continue.
+
+- `cl_set_cleanup(void (*cleanup)(void *), void *opaque)`: Set the cleanup
+ method for a single test. This method will be called with `opaque` as its
+ argument before the test returns (even if the test has failed).
+ If a global cleanup method is also available, the local cleanup will be
+ called first, and then the global.
+
+- `cl_assert_equal_i(int,int)`: Verify that two integer values are equal.
+ The advantage of this over a simple `cl_assert` is that it will format
+ a much nicer error report if the values are not equal.
+
+- `cl_assert_equal_s(const char *,const char *)`: Verify that two strings
+ are equal. The expected value can also be NULL and this will correctly
+ test for that.
+
+- `cl_fixture_sandbox(const char *)`: Sets up a sandbox for a fixture
+ so that you can mutate the file directly.
+
+- `cl_fixture_cleanup(const char *)`: Tears down the previous fixture
+ sandbox.
+
+- `cl_fixture(const char *)`: Gets the full path to a fixture file.
+
+Please do note that these methods are *always* available whilst running a
+test, even when calling auxiliary/static functions inside the same file.
+
+It's strongly encouraged to perform test assertions in auxiliary methods,
+instead of returning error values. This is considered good Clar style.
+
+Style Example:
+
+~~~~ c
+/*
+ * Bad style: auxiliary functions return an error code
+ */
+
+static int check_string(const char *str)
+{
+ const char *aux = process_string(str);
+
+ if (aux == NULL)
+ return -1;
+
+ return strcmp(my_function(aux), str) == 0 ? 0 : -1;
+}
+
+void test_example__a_test_with_auxiliary_methods(void)
+{
+ cl_must_pass_(
+ check_string("foo"),
+ "String differs after processing"
+ );
+
+ cl_must_pass_(
+ check_string("bar"),
+ "String differs after processing"
+ );
+}
+~~~~
+
+~~~~ c
+/*
+ * Good style: auxiliary functions perform assertions
+ */
+
+static void check_string(const char *str)
+{
+ const char *aux = process_string(str);
+
+ cl_assert_(
+ aux != NULL,
+ "String processing failed"
+ );
+
+ cl_assert_(
+ strcmp(my_function(aux), str) == 0,
+ "String differs after processing"
+ );
+}
+
+void test_example__a_test_with_auxiliary_methods(void)
+{
+ check_string("foo");
+ check_string("bar");
+}
+~~~~
+
+About Clar
+==========
+
+Clar has been written from scratch by [Vicent Martí](https://github.com/vmg),
+to replace the old testing framework in [libgit2][libgit2].
+
+Do you know what languages are *in* on the SF startup scene? Node.js *and*
+Latin. Follow [@vmg](https://www.twitter.com/vmg) on Twitter to
+receive more lessons on word etymology. You can be hip too.
+
+
+[libgit2]: https://github.com/libgit2/libgit2
diff --git a/t/unit-tests/clar/clar.c b/t/unit-tests/clar/clar.c
new file mode 100644
index 0000000000..cef0f023c2
--- /dev/null
+++ b/t/unit-tests/clar/clar.c
@@ -0,0 +1,842 @@
+/*
+ * Copyright (c) Vicent Marti. All rights reserved.
+ *
+ * This file is part of clar, distributed under the ISC license.
+ * For full terms see the included COPYING file.
+ */
+#include <assert.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdarg.h>
+#include <wchar.h>
+#include <time.h>
+
+/* required for sandboxing */
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <io.h>
+# include <direct.h>
+
+# define _MAIN_CC __cdecl
+
+# ifndef stat
+# define stat(path, st) _stat(path, st)
+# endif
+# ifndef mkdir
+# define mkdir(path, mode) _mkdir(path)
+# endif
+# ifndef chdir
+# define chdir(path) _chdir(path)
+# endif
+# ifndef access
+# define access(path, mode) _access(path, mode)
+# endif
+# ifndef strdup
+# define strdup(str) _strdup(str)
+# endif
+# ifndef strcasecmp
+# define strcasecmp(a,b) _stricmp(a,b)
+# endif
+
+# ifndef __MINGW32__
+# pragma comment(lib, "shell32")
+# ifndef strncpy
+# define strncpy(to, from, to_size) strncpy_s(to, to_size, from, _TRUNCATE)
+# endif
+# ifndef W_OK
+# define W_OK 02
+# endif
+# ifndef S_ISDIR
+# define S_ISDIR(x) ((x & _S_IFDIR) != 0)
+# endif
+# define p_snprintf(buf,sz,fmt,...) _snprintf_s(buf,sz,_TRUNCATE,fmt,__VA_ARGS__)
+# else
+# define p_snprintf snprintf
+# endif
+
+# ifndef PRIuZ
+# define PRIuZ "Iu"
+# endif
+# ifndef PRIxZ
+# define PRIxZ "Ix"
+# endif
+
+# if defined(_MSC_VER) || (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
+ typedef struct stat STAT_T;
+# else
+ typedef struct _stat STAT_T;
+# endif
+#else
+# include <sys/wait.h> /* waitpid(2) */
+# include <unistd.h>
+# define _MAIN_CC
+# define p_snprintf snprintf
+# ifndef PRIuZ
+# define PRIuZ "zu"
+# endif
+# ifndef PRIxZ
+# define PRIxZ "zx"
+# endif
+ typedef struct stat STAT_T;
+#endif
+
+#define MAX(x, y) (((x) > (y)) ? (x) : (y))
+
+#include "clar.h"
+
+static void fs_rm(const char *_source);
+static void fs_copy(const char *_source, const char *dest);
+
+#ifdef CLAR_FIXTURE_PATH
+static const char *
+fixture_path(const char *base, const char *fixture_name);
+#endif
+
+struct clar_error {
+ const char *file;
+ const char *function;
+ size_t line_number;
+ const char *error_msg;
+ char *description;
+
+ struct clar_error *next;
+};
+
+struct clar_explicit {
+ size_t suite_idx;
+ const char *filter;
+
+ struct clar_explicit *next;
+};
+
+struct clar_report {
+ const char *test;
+ int test_number;
+ const char *suite;
+
+ enum cl_test_status status;
+ time_t start;
+ double elapsed;
+
+ struct clar_error *errors;
+ struct clar_error *last_error;
+
+ struct clar_report *next;
+};
+
+struct clar_summary {
+ const char *filename;
+ FILE *fp;
+};
+
+static struct {
+ enum cl_test_status test_status;
+
+ const char *active_test;
+ const char *active_suite;
+
+ int total_skipped;
+ int total_errors;
+
+ int tests_ran;
+ int suites_ran;
+
+ enum cl_output_format output_format;
+
+ int report_errors_only;
+ int exit_on_error;
+ int verbosity;
+
+ int write_summary;
+ char *summary_filename;
+ struct clar_summary *summary;
+
+ struct clar_explicit *explicit;
+ struct clar_explicit *last_explicit;
+
+ struct clar_report *reports;
+ struct clar_report *last_report;
+
+ void (*local_cleanup)(void *);
+ void *local_cleanup_payload;
+
+ jmp_buf trampoline;
+ int trampoline_enabled;
+
+ cl_trace_cb *pfn_trace_cb;
+ void *trace_payload;
+
+} _clar;
+
+struct clar_func {
+ const char *name;
+ void (*ptr)(void);
+};
+
+struct clar_suite {
+ const char *name;
+ struct clar_func initialize;
+ struct clar_func cleanup;
+ const struct clar_func *tests;
+ size_t test_count;
+ int enabled;
+};
+
+/* From clar_print_*.c */
+static void clar_print_init(int test_count, int suite_count, const char *suite_names);
+static void clar_print_shutdown(int test_count, int suite_count, int error_count);
+static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error);
+static void clar_print_ontest(const char *suite_name, const char *test_name, int test_number, enum cl_test_status failed);
+static void clar_print_onsuite(const char *suite_name, int suite_index);
+static void clar_print_onabort(const char *msg, ...);
+
+/* From clar_sandbox.c */
+static void clar_unsandbox(void);
+static int clar_sandbox(void);
+
+/* From summary.h */
+static struct clar_summary *clar_summary_init(const char *filename);
+static int clar_summary_shutdown(struct clar_summary *fp);
+
+/* Load the declarations for the test suite */
+#include "clar.suite"
+
+
+#define CL_TRACE(ev) \
+ do { \
+ if (_clar.pfn_trace_cb) \
+ _clar.pfn_trace_cb(ev, \
+ _clar.active_suite, \
+ _clar.active_test, \
+ _clar.trace_payload); \
+ } while (0)
+
+void cl_trace_register(cl_trace_cb *cb, void *payload)
+{
+ _clar.pfn_trace_cb = cb;
+ _clar.trace_payload = payload;
+}
+
+
+/* Core test functions */
+static void
+clar_report_errors(struct clar_report *report)
+{
+ struct clar_error *error;
+ int i = 1;
+
+ for (error = report->errors; error; error = error->next)
+ clar_print_error(i++, _clar.last_report, error);
+}
+
+static void
+clar_report_all(void)
+{
+ struct clar_report *report;
+ struct clar_error *error;
+ int i = 1;
+
+ for (report = _clar.reports; report; report = report->next) {
+ if (report->status != CL_TEST_FAILURE)
+ continue;
+
+ for (error = report->errors; error; error = error->next)
+ clar_print_error(i++, report, error);
+ }
+}
+
+#ifdef WIN32
+# define clar_time DWORD
+
+static void clar_time_now(clar_time *out)
+{
+ *out = GetTickCount();
+}
+
+static double clar_time_diff(clar_time *start, clar_time *end)
+{
+ return ((double)*end - (double)*start) / 1000;
+}
+#else
+# include <sys/time.h>
+
+# define clar_time struct timeval
+
+static void clar_time_now(clar_time *out)
+{
+ struct timezone tz;
+
+ gettimeofday(out, &tz);
+}
+
+static double clar_time_diff(clar_time *start, clar_time *end)
+{
+ return ((double)end->tv_sec + (double)end->tv_usec / 1.0E6) -
+ ((double)start->tv_sec + (double)start->tv_usec / 1.0E6);
+}
+#endif
+
+static void
+clar_run_test(
+ const struct clar_suite *suite,
+ const struct clar_func *test,
+ const struct clar_func *initialize,
+ const struct clar_func *cleanup)
+{
+ clar_time start, end;
+
+ _clar.trampoline_enabled = 1;
+
+ CL_TRACE(CL_TRACE__TEST__BEGIN);
+
+ _clar.last_report->start = time(NULL);
+ clar_time_now(&start);
+
+ if (setjmp(_clar.trampoline) == 0) {
+ if (initialize->ptr != NULL)
+ initialize->ptr();
+
+ CL_TRACE(CL_TRACE__TEST__RUN_BEGIN);
+ test->ptr();
+ CL_TRACE(CL_TRACE__TEST__RUN_END);
+ }
+
+ clar_time_now(&end);
+
+ _clar.trampoline_enabled = 0;
+
+ if (_clar.last_report->status == CL_TEST_NOTRUN)
+ _clar.last_report->status = CL_TEST_OK;
+
+ _clar.last_report->elapsed = clar_time_diff(&start, &end);
+
+ if (_clar.local_cleanup != NULL)
+ _clar.local_cleanup(_clar.local_cleanup_payload);
+
+ if (cleanup->ptr != NULL)
+ cleanup->ptr();
+
+ CL_TRACE(CL_TRACE__TEST__END);
+
+ _clar.tests_ran++;
+
+ /* remove any local-set cleanup methods */
+ _clar.local_cleanup = NULL;
+ _clar.local_cleanup_payload = NULL;
+
+ if (_clar.report_errors_only) {
+ clar_report_errors(_clar.last_report);
+ } else {
+ clar_print_ontest(suite->name, test->name, _clar.tests_ran, _clar.last_report->status);
+ }
+}
+
+static void
+clar_run_suite(const struct clar_suite *suite, const char *filter)
+{
+ const struct clar_func *test = suite->tests;
+ size_t i, matchlen;
+ struct clar_report *report;
+ int exact = 0;
+
+ if (!suite->enabled)
+ return;
+
+ if (_clar.exit_on_error && _clar.total_errors)
+ return;
+
+ if (!_clar.report_errors_only)
+ clar_print_onsuite(suite->name, ++_clar.suites_ran);
+
+ _clar.active_suite = suite->name;
+ _clar.active_test = NULL;
+ CL_TRACE(CL_TRACE__SUITE_BEGIN);
+
+ if (filter) {
+ size_t suitelen = strlen(suite->name);
+ matchlen = strlen(filter);
+ if (matchlen <= suitelen) {
+ filter = NULL;
+ } else {
+ filter += suitelen;
+ while (*filter == ':')
+ ++filter;
+ matchlen = strlen(filter);
+
+ if (matchlen && filter[matchlen - 1] == '$') {
+ exact = 1;
+ matchlen--;
+ }
+ }
+ }
+
+ for (i = 0; i < suite->test_count; ++i) {
+ if (filter && strncmp(test[i].name, filter, matchlen))
+ continue;
+
+ if (exact && strlen(test[i].name) != matchlen)
+ continue;
+
+ _clar.active_test = test[i].name;
+
+ report = calloc(1, sizeof(struct clar_report));
+ report->suite = _clar.active_suite;
+ report->test = _clar.active_test;
+ report->test_number = _clar.tests_ran;
+ report->status = CL_TEST_NOTRUN;
+
+ if (_clar.reports == NULL)
+ _clar.reports = report;
+
+ if (_clar.last_report != NULL)
+ _clar.last_report->next = report;
+
+ _clar.last_report = report;
+
+ clar_run_test(suite, &test[i], &suite->initialize, &suite->cleanup);
+
+ if (_clar.exit_on_error && _clar.total_errors)
+ return;
+ }
+
+ _clar.active_test = NULL;
+ CL_TRACE(CL_TRACE__SUITE_END);
+}
+
+static void
+clar_usage(const char *arg)
+{
+ printf("Usage: %s [options]\n\n", arg);
+ printf("Options:\n");
+ printf(" -sname Run only the suite with `name` (can go to individual test name)\n");
+ printf(" -iname Include the suite with `name`\n");
+ printf(" -xname Exclude the suite with `name`\n");
+ printf(" -v Increase verbosity (show suite names)\n");
+ printf(" -q Only report tests that had an error\n");
+ printf(" -Q Quit as soon as a test fails\n");
+ printf(" -t Display results in tap format\n");
+ printf(" -l Print suite names\n");
+ printf(" -r[filename] Write summary file (to the optional filename)\n");
+ exit(-1);
+}
+
+static void
+clar_parse_args(int argc, char **argv)
+{
+ int i;
+
+ /* Verify options before execute */
+ for (i = 1; i < argc; ++i) {
+ char *argument = argv[i];
+
+ if (argument[0] != '-' || argument[1] == '\0'
+ || strchr("sixvqQtlr", argument[1]) == NULL) {
+ clar_usage(argv[0]);
+ }
+ }
+
+ for (i = 1; i < argc; ++i) {
+ char *argument = argv[i];
+
+ switch (argument[1]) {
+ case 's':
+ case 'i':
+ case 'x': { /* given suite name */
+ int offset = (argument[2] == '=') ? 3 : 2, found = 0;
+ char action = argument[1];
+ size_t j, arglen, suitelen, cmplen;
+
+ argument += offset;
+ arglen = strlen(argument);
+
+ if (arglen == 0)
+ clar_usage(argv[0]);
+
+ for (j = 0; j < _clar_suite_count; ++j) {
+ suitelen = strlen(_clar_suites[j].name);
+ cmplen = (arglen < suitelen) ? arglen : suitelen;
+
+ if (strncmp(argument, _clar_suites[j].name, cmplen) == 0) {
+ int exact = (arglen >= suitelen);
+
+ /* Do we have a real suite prefix separated by a
+ * trailing '::' or just a matching substring? */
+ if (arglen > suitelen && (argument[suitelen] != ':'
+ || argument[suitelen + 1] != ':'))
+ continue;
+
+ ++found;
+
+ if (!exact)
+ _clar.verbosity = MAX(_clar.verbosity, 1);
+
+ switch (action) {
+ case 's': {
+ struct clar_explicit *explicit =
+ calloc(1, sizeof(struct clar_explicit));
+ assert(explicit);
+
+ explicit->suite_idx = j;
+ explicit->filter = argument;
+
+ if (_clar.explicit == NULL)
+ _clar.explicit = explicit;
+
+ if (_clar.last_explicit != NULL)
+ _clar.last_explicit->next = explicit;
+
+ _clar_suites[j].enabled = 1;
+ _clar.last_explicit = explicit;
+ break;
+ }
+ case 'i': _clar_suites[j].enabled = 1; break;
+ case 'x': _clar_suites[j].enabled = 0; break;
+ }
+
+ if (exact)
+ break;
+ }
+ }
+
+ if (!found) {
+ clar_print_onabort("No suite matching '%s' found.\n", argument);
+ exit(-1);
+ }
+ break;
+ }
+
+ case 'q':
+ _clar.report_errors_only = 1;
+ break;
+
+ case 'Q':
+ _clar.exit_on_error = 1;
+ break;
+
+ case 't':
+ _clar.output_format = CL_OUTPUT_TAP;
+ break;
+
+ case 'l': {
+ size_t j;
+ printf("Test suites (use -s<name> to run just one):\n");
+ for (j = 0; j < _clar_suite_count; ++j)
+ printf(" %3d: %s\n", (int)j, _clar_suites[j].name);
+
+ exit(0);
+ }
+
+ case 'v':
+ _clar.verbosity++;
+ break;
+
+ case 'r':
+ _clar.write_summary = 1;
+ free(_clar.summary_filename);
+ _clar.summary_filename = *(argument + 2) ? strdup(argument + 2) : NULL;
+ break;
+
+ default:
+ assert(!"Unexpected commandline argument!");
+ }
+ }
+}
+
+void
+clar_test_init(int argc, char **argv)
+{
+ const char *summary_env;
+
+ if (argc > 1)
+ clar_parse_args(argc, argv);
+
+ clar_print_init(
+ (int)_clar_callback_count,
+ (int)_clar_suite_count,
+ ""
+ );
+
+ if (!_clar.summary_filename &&
+ (summary_env = getenv("CLAR_SUMMARY")) != NULL) {
+ _clar.write_summary = 1;
+ _clar.summary_filename = strdup(summary_env);
+ }
+
+ if (_clar.write_summary && !_clar.summary_filename)
+ _clar.summary_filename = strdup("summary.xml");
+
+ if (_clar.write_summary &&
+ !(_clar.summary = clar_summary_init(_clar.summary_filename))) {
+ clar_print_onabort("Failed to open the summary file\n");
+ exit(-1);
+ }
+
+ if (clar_sandbox() < 0) {
+ clar_print_onabort("Failed to sandbox the test runner.\n");
+ exit(-1);
+ }
+}
+
+int
+clar_test_run(void)
+{
+ size_t i;
+ struct clar_explicit *explicit;
+
+ if (_clar.explicit) {
+ for (explicit = _clar.explicit; explicit; explicit = explicit->next)
+ clar_run_suite(&_clar_suites[explicit->suite_idx], explicit->filter);
+ } else {
+ for (i = 0; i < _clar_suite_count; ++i)
+ clar_run_suite(&_clar_suites[i], NULL);
+ }
+
+ return _clar.total_errors;
+}
+
+void
+clar_test_shutdown(void)
+{
+ struct clar_explicit *explicit, *explicit_next;
+ struct clar_report *report, *report_next;
+
+ clar_print_shutdown(
+ _clar.tests_ran,
+ (int)_clar_suite_count,
+ _clar.total_errors
+ );
+
+ clar_unsandbox();
+
+ if (_clar.write_summary && clar_summary_shutdown(_clar.summary) < 0) {
+ clar_print_onabort("Failed to write the summary file\n");
+ exit(-1);
+ }
+
+ for (explicit = _clar.explicit; explicit; explicit = explicit_next) {
+ explicit_next = explicit->next;
+ free(explicit);
+ }
+
+ for (report = _clar.reports; report; report = report_next) {
+ report_next = report->next;
+ free(report);
+ }
+
+ free(_clar.summary_filename);
+}
+
+int
+clar_test(int argc, char **argv)
+{
+ int errors;
+
+ clar_test_init(argc, argv);
+ errors = clar_test_run();
+ clar_test_shutdown();
+
+ return errors;
+}
+
+static void abort_test(void)
+{
+ if (!_clar.trampoline_enabled) {
+ clar_print_onabort(
+ "Fatal error: a cleanup method raised an exception.");
+ clar_report_errors(_clar.last_report);
+ exit(-1);
+ }
+
+ CL_TRACE(CL_TRACE__TEST__LONGJMP);
+ longjmp(_clar.trampoline, -1);
+}
+
+void clar__skip(void)
+{
+ _clar.last_report->status = CL_TEST_SKIP;
+ _clar.total_skipped++;
+ abort_test();
+}
+
+void clar__fail(
+ const char *file,
+ const char *function,
+ size_t line,
+ const char *error_msg,
+ const char *description,
+ int should_abort)
+{
+ struct clar_error *error = calloc(1, sizeof(struct clar_error));
+
+ if (_clar.last_report->errors == NULL)
+ _clar.last_report->errors = error;
+
+ if (_clar.last_report->last_error != NULL)
+ _clar.last_report->last_error->next = error;
+
+ _clar.last_report->last_error = error;
+
+ error->file = file;
+ error->function = function;
+ error->line_number = line;
+ error->error_msg = error_msg;
+
+ if (description != NULL)
+ error->description = strdup(description);
+
+ _clar.total_errors++;
+ _clar.last_report->status = CL_TEST_FAILURE;
+
+ if (should_abort)
+ abort_test();
+}
+
+void clar__assert(
+ int condition,
+ const char *file,
+ const char *function,
+ size_t line,
+ const char *error_msg,
+ const char *description,
+ int should_abort)
+{
+ if (condition)
+ return;
+
+ clar__fail(file, function, line, error_msg, description, should_abort);
+}
+
+void clar__assert_equal(
+ const char *file,
+ const char *function,
+ size_t line,
+ const char *err,
+ int should_abort,
+ const char *fmt,
+ ...)
+{
+ va_list args;
+ char buf[4096];
+ int is_equal = 1;
+
+ va_start(args, fmt);
+
+ if (!strcmp("%s", fmt)) {
+ const char *s1 = va_arg(args, const char *);
+ const char *s2 = va_arg(args, const char *);
+ is_equal = (!s1 || !s2) ? (s1 == s2) : !strcmp(s1, s2);
+
+ if (!is_equal) {
+ if (s1 && s2) {
+ int pos;
+ for (pos = 0; s1[pos] == s2[pos] && s1[pos] && s2[pos]; ++pos)
+ /* find differing byte offset */;
+ p_snprintf(buf, sizeof(buf), "'%s' != '%s' (at byte %d)",
+ s1, s2, pos);
+ } else {
+ p_snprintf(buf, sizeof(buf), "'%s' != '%s'", s1, s2);
+ }
+ }
+ }
+ else if(!strcmp("%.*s", fmt)) {
+ const char *s1 = va_arg(args, const char *);
+ const char *s2 = va_arg(args, const char *);
+ int len = va_arg(args, int);
+ is_equal = (!s1 || !s2) ? (s1 == s2) : !strncmp(s1, s2, len);
+
+ if (!is_equal) {
+ if (s1 && s2) {
+ int pos;
+ for (pos = 0; s1[pos] == s2[pos] && pos < len; ++pos)
+ /* find differing byte offset */;
+ p_snprintf(buf, sizeof(buf), "'%.*s' != '%.*s' (at byte %d)",
+ len, s1, len, s2, pos);
+ } else {
+ p_snprintf(buf, sizeof(buf), "'%.*s' != '%.*s'", len, s1, len, s2);
+ }
+ }
+ }
+ else if (!strcmp("%ls", fmt)) {
+ const wchar_t *wcs1 = va_arg(args, const wchar_t *);
+ const wchar_t *wcs2 = va_arg(args, const wchar_t *);
+ is_equal = (!wcs1 || !wcs2) ? (wcs1 == wcs2) : !wcscmp(wcs1, wcs2);
+
+ if (!is_equal) {
+ if (wcs1 && wcs2) {
+ int pos;
+ for (pos = 0; wcs1[pos] == wcs2[pos] && wcs1[pos] && wcs2[pos]; ++pos)
+ /* find differing byte offset */;
+ p_snprintf(buf, sizeof(buf), "'%ls' != '%ls' (at byte %d)",
+ wcs1, wcs2, pos);
+ } else {
+ p_snprintf(buf, sizeof(buf), "'%ls' != '%ls'", wcs1, wcs2);
+ }
+ }
+ }
+ else if(!strcmp("%.*ls", fmt)) {
+ const wchar_t *wcs1 = va_arg(args, const wchar_t *);
+ const wchar_t *wcs2 = va_arg(args, const wchar_t *);
+ int len = va_arg(args, int);
+ is_equal = (!wcs1 || !wcs2) ? (wcs1 == wcs2) : !wcsncmp(wcs1, wcs2, len);
+
+ if (!is_equal) {
+ if (wcs1 && wcs2) {
+ int pos;
+ for (pos = 0; wcs1[pos] == wcs2[pos] && pos < len; ++pos)
+ /* find differing byte offset */;
+ p_snprintf(buf, sizeof(buf), "'%.*ls' != '%.*ls' (at byte %d)",
+ len, wcs1, len, wcs2, pos);
+ } else {
+ p_snprintf(buf, sizeof(buf), "'%.*ls' != '%.*ls'", len, wcs1, len, wcs2);
+ }
+ }
+ }
+ else if (!strcmp("%"PRIuZ, fmt) || !strcmp("%"PRIxZ, fmt)) {
+ size_t sz1 = va_arg(args, size_t), sz2 = va_arg(args, size_t);
+ is_equal = (sz1 == sz2);
+ if (!is_equal) {
+ int offset = p_snprintf(buf, sizeof(buf), fmt, sz1);
+ strncat(buf, " != ", sizeof(buf) - offset);
+ p_snprintf(buf + offset + 4, sizeof(buf) - offset - 4, fmt, sz2);
+ }
+ }
+ else if (!strcmp("%p", fmt)) {
+ void *p1 = va_arg(args, void *), *p2 = va_arg(args, void *);
+ is_equal = (p1 == p2);
+ if (!is_equal)
+ p_snprintf(buf, sizeof(buf), "%p != %p", p1, p2);
+ }
+ else {
+ int i1 = va_arg(args, int), i2 = va_arg(args, int);
+ is_equal = (i1 == i2);
+ if (!is_equal) {
+ int offset = p_snprintf(buf, sizeof(buf), fmt, i1);
+ strncat(buf, " != ", sizeof(buf) - offset);
+ p_snprintf(buf + offset + 4, sizeof(buf) - offset - 4, fmt, i2);
+ }
+ }
+
+ va_end(args);
+
+ if (!is_equal)
+ clar__fail(file, function, line, err, buf, should_abort);
+}
+
+void cl_set_cleanup(void (*cleanup)(void *), void *opaque)
+{
+ _clar.local_cleanup = cleanup;
+ _clar.local_cleanup_payload = opaque;
+}
+
+#include "clar/sandbox.h"
+#include "clar/fixtures.h"
+#include "clar/fs.h"
+#include "clar/print.h"
+#include "clar/summary.h"
diff --git a/t/unit-tests/clar/clar.h b/t/unit-tests/clar/clar.h
new file mode 100644
index 0000000000..8c22382bd5
--- /dev/null
+++ b/t/unit-tests/clar/clar.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) Vicent Marti. All rights reserved.
+ *
+ * This file is part of clar, distributed under the ISC license.
+ * For full terms see the included COPYING file.
+ */
+#ifndef __CLAR_TEST_H__
+#define __CLAR_TEST_H__
+
+#include <stdlib.h>
+
+enum cl_test_status {
+ CL_TEST_OK,
+ CL_TEST_FAILURE,
+ CL_TEST_SKIP,
+ CL_TEST_NOTRUN,
+};
+
+enum cl_output_format {
+ CL_OUTPUT_CLAP,
+ CL_OUTPUT_TAP,
+};
+
+/** Setup clar environment */
+void clar_test_init(int argc, char *argv[]);
+int clar_test_run(void);
+void clar_test_shutdown(void);
+
+/** One shot setup & run */
+int clar_test(int argc, char *argv[]);
+
+const char *clar_sandbox_path(void);
+
+void cl_set_cleanup(void (*cleanup)(void *), void *opaque);
+void cl_fs_cleanup(void);
+
+/**
+ * cl_trace_* is a hook to provide a simple global tracing
+ * mechanism.
+ *
+ * The goal here is to let main() provide clar-proper
+ * with a callback to optionally write log info for
+ * test operations into the same stream used by their
+ * actual tests. This would let them print test names
+ * and maybe performance data as they choose.
+ *
+ * The goal is NOT to alter the flow of control or to
+ * override test selection/skipping. (So the callback
+ * does not return a value.)
+ *
+ * The goal is NOT to duplicate the existing
+ * pass/fail/skip reporting. (So the callback
+ * does not accept a status/errorcode argument.)
+ *
+ */
+typedef enum cl_trace_event {
+ CL_TRACE__SUITE_BEGIN,
+ CL_TRACE__SUITE_END,
+ CL_TRACE__TEST__BEGIN,
+ CL_TRACE__TEST__END,
+ CL_TRACE__TEST__RUN_BEGIN,
+ CL_TRACE__TEST__RUN_END,
+ CL_TRACE__TEST__LONGJMP,
+} cl_trace_event;
+
+typedef void (cl_trace_cb)(
+ cl_trace_event ev,
+ const char *suite_name,
+ const char *test_name,
+ void *payload);
+
+/**
+ * Register a callback into CLAR to send global trace events.
+ * Pass NULL to disable.
+ */
+void cl_trace_register(cl_trace_cb *cb, void *payload);
+
+
+#ifdef CLAR_FIXTURE_PATH
+const char *cl_fixture(const char *fixture_name);
+void cl_fixture_sandbox(const char *fixture_name);
+void cl_fixture_cleanup(const char *fixture_name);
+const char *cl_fixture_basename(const char *fixture_name);
+#endif
+
+/**
+ * Assertion macros with explicit error message
+ */
+#define cl_must_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __func__, __LINE__, "Function call failed: " #expr, desc, 1)
+#define cl_must_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __func__, __LINE__, "Expected function call to fail: " #expr, desc, 1)
+#define cl_assert_(expr, desc) clar__assert((expr) != 0, __FILE__, __func__, __LINE__, "Expression is not true: " #expr, desc, 1)
+
+/**
+ * Check macros with explicit error message
+ */
+#define cl_check_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __func__, __LINE__, "Function call failed: " #expr, desc, 0)
+#define cl_check_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __func__, __LINE__, "Expected function call to fail: " #expr, desc, 0)
+#define cl_check_(expr, desc) clar__assert((expr) != 0, __FILE__, __func__, __LINE__, "Expression is not true: " #expr, desc, 0)
+
+/**
+ * Assertion macros with no error message
+ */
+#define cl_must_pass(expr) cl_must_pass_(expr, NULL)
+#define cl_must_fail(expr) cl_must_fail_(expr, NULL)
+#define cl_assert(expr) cl_assert_(expr, NULL)
+
+/**
+ * Check macros with no error message
+ */
+#define cl_check_pass(expr) cl_check_pass_(expr, NULL)
+#define cl_check_fail(expr) cl_check_fail_(expr, NULL)
+#define cl_check(expr) cl_check_(expr, NULL)
+
+/**
+ * Forced failure/warning
+ */
+#define cl_fail(desc) clar__fail(__FILE__, __func__, __LINE__, "Test failed.", desc, 1)
+#define cl_warning(desc) clar__fail(__FILE__, __func__, __LINE__, "Warning during test execution:", desc, 0)
+
+#define cl_skip() clar__skip()
+
+/**
+ * Typed assertion macros
+ */
+#define cl_assert_equal_s(s1,s2) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2, 1, "%s", (s1), (s2))
+#define cl_assert_equal_s_(s1,s2,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%s", (s1), (s2))
+
+#define cl_assert_equal_wcs(wcs1,wcs2) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2, 1, "%ls", (wcs1), (wcs2))
+#define cl_assert_equal_wcs_(wcs1,wcs2,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%ls", (wcs1), (wcs2))
+
+#define cl_assert_equal_strn(s1,s2,len) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2, 1, "%.*s", (s1), (s2), (int)(len))
+#define cl_assert_equal_strn_(s1,s2,len,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%.*s", (s1), (s2), (int)(len))
+
+#define cl_assert_equal_wcsn(wcs1,wcs2,len) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2, 1, "%.*ls", (wcs1), (wcs2), (int)(len))
+#define cl_assert_equal_wcsn_(wcs1,wcs2,len,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%.*ls", (wcs1), (wcs2), (int)(len))
+
+#define cl_assert_equal_i(i1,i2) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2))
+#define cl_assert_equal_i_(i1,i2,note) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2 " (" #note ")", 1, "%d", (i1), (i2))
+#define cl_assert_equal_i_fmt(i1,i2,fmt) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2, 1, (fmt), (int)(i1), (int)(i2))
+
+#define cl_assert_equal_b(b1,b2) clar__assert_equal(__FILE__,__func__,__LINE__,#b1 " != " #b2, 1, "%d", (int)((b1) != 0),(int)((b2) != 0))
+
+#define cl_assert_equal_p(p1,p2) clar__assert_equal(__FILE__,__func__,__LINE__,"Pointer mismatch: " #p1 " != " #p2, 1, "%p", (p1), (p2))
+
+void clar__skip(void);
+
+void clar__fail(
+ const char *file,
+ const char *func,
+ size_t line,
+ const char *error,
+ const char *description,
+ int should_abort);
+
+void clar__assert(
+ int condition,
+ const char *file,
+ const char *func,
+ size_t line,
+ const char *error,
+ const char *description,
+ int should_abort);
+
+void clar__assert_equal(
+ const char *file,
+ const char *func,
+ size_t line,
+ const char *err,
+ int should_abort,
+ const char *fmt,
+ ...);
+
+#endif
diff --git a/t/unit-tests/clar/clar/fixtures.h b/t/unit-tests/clar/clar/fixtures.h
new file mode 100644
index 0000000000..6ec6423484
--- /dev/null
+++ b/t/unit-tests/clar/clar/fixtures.h
@@ -0,0 +1,50 @@
+#ifdef CLAR_FIXTURE_PATH
+static const char *
+fixture_path(const char *base, const char *fixture_name)
+{
+ static char _path[4096];
+ size_t root_len;
+
+ root_len = strlen(base);
+ strncpy(_path, base, sizeof(_path));
+
+ if (_path[root_len - 1] != '/')
+ _path[root_len++] = '/';
+
+ if (fixture_name[0] == '/')
+ fixture_name++;
+
+ strncpy(_path + root_len,
+ fixture_name,
+ sizeof(_path) - root_len);
+
+ return _path;
+}
+
+const char *cl_fixture(const char *fixture_name)
+{
+ return fixture_path(CLAR_FIXTURE_PATH, fixture_name);
+}
+
+void cl_fixture_sandbox(const char *fixture_name)
+{
+ fs_copy(cl_fixture(fixture_name), _clar_path);
+}
+
+const char *cl_fixture_basename(const char *fixture_name)
+{
+ const char *p;
+
+ for (p = fixture_name; *p; p++) {
+ if (p[0] == '/' && p[1] && p[1] != '/')
+ fixture_name = p+1;
+ }
+
+ return fixture_name;
+}
+
+void cl_fixture_cleanup(const char *fixture_name)
+{
+ fs_rm(fixture_path(_clar_path, cl_fixture_basename(fixture_name)));
+}
+#endif
diff --git a/t/unit-tests/clar/clar/fs.h b/t/unit-tests/clar/clar/fs.h
new file mode 100644
index 0000000000..8b206179fc
--- /dev/null
+++ b/t/unit-tests/clar/clar/fs.h
@@ -0,0 +1,524 @@
+/*
+ * By default, use a read/write loop to copy files on POSIX systems.
+ * On Linux, use sendfile by default as it's slightly faster. On
+ * macOS, we avoid fcopyfile by default because it's slightly slower.
+ */
+#undef USE_FCOPYFILE
+#define USE_SENDFILE 1
+
+#ifdef _WIN32
+
+#ifdef CLAR_WIN32_LONGPATHS
+# define CLAR_MAX_PATH 4096
+#else
+# define CLAR_MAX_PATH MAX_PATH
+#endif
+
+#define RM_RETRY_COUNT 5
+#define RM_RETRY_DELAY 10
+
+#ifdef __MINGW32__
+
+/* These security-enhanced functions are not available
+ * in MinGW, so just use the vanilla ones */
+#define wcscpy_s(a, b, c) wcscpy((a), (c))
+#define wcscat_s(a, b, c) wcscat((a), (c))
+
+#endif /* __MINGW32__ */
+
+static int
+fs__dotordotdot(WCHAR *_tocheck)
+{
+ return _tocheck[0] == '.' &&
+ (_tocheck[1] == '\0' ||
+ (_tocheck[1] == '.' && _tocheck[2] == '\0'));
+}
+
+static int
+fs_rmdir_rmdir(WCHAR *_wpath)
+{
+ unsigned retries = 1;
+
+ while (!RemoveDirectoryW(_wpath)) {
+ /* Only retry when we have retries remaining, and the
+ * error was ERROR_DIR_NOT_EMPTY. */
+ if (retries++ > RM_RETRY_COUNT ||
+ ERROR_DIR_NOT_EMPTY != GetLastError())
+ return -1;
+
+ /* Give whatever has a handle to a child item some time
+ * to release it before trying again */
+ Sleep(RM_RETRY_DELAY * retries * retries);
+ }
+
+ return 0;
+}
+
+static void translate_path(WCHAR *path, size_t path_size)
+{
+ size_t path_len, i;
+
+ if (wcsncmp(path, L"\\\\?\\", 4) == 0)
+ return;
+
+ path_len = wcslen(path);
+ cl_assert(path_size > path_len + 4);
+
+ for (i = path_len; i > 0; i--) {
+ WCHAR c = path[i - 1];
+
+ if (c == L'/')
+ path[i + 3] = L'\\';
+ else
+ path[i + 3] = path[i - 1];
+ }
+
+ path[0] = L'\\';
+ path[1] = L'\\';
+ path[2] = L'?';
+ path[3] = L'\\';
+ path[path_len + 4] = L'\0';
+}
+
+static void
+fs_rmdir_helper(WCHAR *_wsource)
+{
+ WCHAR buffer[CLAR_MAX_PATH];
+ HANDLE find_handle;
+ WIN32_FIND_DATAW find_data;
+ size_t buffer_prefix_len;
+
+ /* Set up the buffer and capture the length */
+ wcscpy_s(buffer, CLAR_MAX_PATH, _wsource);
+ translate_path(buffer, CLAR_MAX_PATH);
+ wcscat_s(buffer, CLAR_MAX_PATH, L"\\");
+ buffer_prefix_len = wcslen(buffer);
+
+ /* FindFirstFile needs a wildcard to match multiple items */
+ wcscat_s(buffer, CLAR_MAX_PATH, L"*");
+ find_handle = FindFirstFileW(buffer, &find_data);
+ cl_assert(INVALID_HANDLE_VALUE != find_handle);
+
+ do {
+ /* FindFirstFile/FindNextFile gives back . and ..
+ * entries at the beginning */
+ if (fs__dotordotdot(find_data.cFileName))
+ continue;
+
+ wcscpy_s(buffer + buffer_prefix_len, CLAR_MAX_PATH - buffer_prefix_len, find_data.cFileName);
+
+ if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes)
+ fs_rmdir_helper(buffer);
+ else {
+ /* If set, the +R bit must be cleared before deleting */
+ if (FILE_ATTRIBUTE_READONLY & find_data.dwFileAttributes)
+ cl_assert(SetFileAttributesW(buffer, find_data.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY));
+
+ cl_assert(DeleteFileW(buffer));
+ }
+ }
+ while (FindNextFileW(find_handle, &find_data));
+
+ /* Ensure that we successfully completed the enumeration */
+ cl_assert(ERROR_NO_MORE_FILES == GetLastError());
+
+ /* Close the find handle */
+ FindClose(find_handle);
+
+ /* Now that the directory is empty, remove it */
+ cl_assert(0 == fs_rmdir_rmdir(_wsource));
+}
+
+static int
+fs_rm_wait(WCHAR *_wpath)
+{
+ unsigned retries = 1;
+ DWORD last_error;
+
+ do {
+ if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(_wpath))
+ last_error = GetLastError();
+ else
+ last_error = ERROR_SUCCESS;
+
+ /* Is the item gone? */
+ if (ERROR_FILE_NOT_FOUND == last_error ||
+ ERROR_PATH_NOT_FOUND == last_error)
+ return 0;
+
+ Sleep(RM_RETRY_DELAY * retries * retries);
+ }
+ while (retries++ <= RM_RETRY_COUNT);
+
+ return -1;
+}
+
+static void
+fs_rm(const char *_source)
+{
+ WCHAR wsource[CLAR_MAX_PATH];
+ DWORD attrs;
+
+ /* The input path is UTF-8. Convert it to wide characters
+ * for use with the Windows API */
+ cl_assert(MultiByteToWideChar(CP_UTF8,
+ MB_ERR_INVALID_CHARS,
+ _source,
+ -1, /* Indicates NULL termination */
+ wsource,
+ CLAR_MAX_PATH));
+
+ translate_path(wsource, CLAR_MAX_PATH);
+
+ /* Does the item exist? If not, we have no work to do */
+ attrs = GetFileAttributesW(wsource);
+
+ if (INVALID_FILE_ATTRIBUTES == attrs)
+ return;
+
+ if (FILE_ATTRIBUTE_DIRECTORY & attrs)
+ fs_rmdir_helper(wsource);
+ else {
+ /* The item is a file. Strip the +R bit */
+ if (FILE_ATTRIBUTE_READONLY & attrs)
+ cl_assert(SetFileAttributesW(wsource, attrs & ~FILE_ATTRIBUTE_READONLY));
+
+ cl_assert(DeleteFileW(wsource));
+ }
+
+ /* Wait for the DeleteFile or RemoveDirectory call to complete */
+ cl_assert(0 == fs_rm_wait(wsource));
+}
+
+static void
+fs_copydir_helper(WCHAR *_wsource, WCHAR *_wdest)
+{
+ WCHAR buf_source[CLAR_MAX_PATH], buf_dest[CLAR_MAX_PATH];
+ HANDLE find_handle;
+ WIN32_FIND_DATAW find_data;
+ size_t buf_source_prefix_len, buf_dest_prefix_len;
+
+ wcscpy_s(buf_source, CLAR_MAX_PATH, _wsource);
+ wcscat_s(buf_source, CLAR_MAX_PATH, L"\\");
+ translate_path(buf_source, CLAR_MAX_PATH);
+ buf_source_prefix_len = wcslen(buf_source);
+
+ wcscpy_s(buf_dest, CLAR_MAX_PATH, _wdest);
+ wcscat_s(buf_dest, CLAR_MAX_PATH, L"\\");
+ translate_path(buf_dest, CLAR_MAX_PATH);
+ buf_dest_prefix_len = wcslen(buf_dest);
+
+ /* Get an enumerator for the items in the source. */
+ wcscat_s(buf_source, CLAR_MAX_PATH, L"*");
+ find_handle = FindFirstFileW(buf_source, &find_data);
+ cl_assert(INVALID_HANDLE_VALUE != find_handle);
+
+ /* Create the target directory. */
+ cl_assert(CreateDirectoryW(_wdest, NULL));
+
+ do {
+ /* FindFirstFile/FindNextFile gives back . and ..
+ * entries at the beginning */
+ if (fs__dotordotdot(find_data.cFileName))
+ continue;
+
+ wcscpy_s(buf_source + buf_source_prefix_len, CLAR_MAX_PATH - buf_source_prefix_len, find_data.cFileName);
+ wcscpy_s(buf_dest + buf_dest_prefix_len, CLAR_MAX_PATH - buf_dest_prefix_len, find_data.cFileName);
+
+ if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes)
+ fs_copydir_helper(buf_source, buf_dest);
+ else
+ cl_assert(CopyFileW(buf_source, buf_dest, TRUE));
+ }
+ while (FindNextFileW(find_handle, &find_data));
+
+ /* Ensure that we successfully completed the enumeration */
+ cl_assert(ERROR_NO_MORE_FILES == GetLastError());
+
+ /* Close the find handle */
+ FindClose(find_handle);
+}
+
+static void
+fs_copy(const char *_source, const char *_dest)
+{
+ WCHAR wsource[CLAR_MAX_PATH], wdest[CLAR_MAX_PATH];
+ DWORD source_attrs, dest_attrs;
+ HANDLE find_handle;
+ WIN32_FIND_DATAW find_data;
+
+ /* The input paths are UTF-8. Convert them to wide characters
+ * for use with the Windows API. */
+ cl_assert(MultiByteToWideChar(CP_UTF8,
+ MB_ERR_INVALID_CHARS,
+ _source,
+ -1,
+ wsource,
+ CLAR_MAX_PATH));
+
+ cl_assert(MultiByteToWideChar(CP_UTF8,
+ MB_ERR_INVALID_CHARS,
+ _dest,
+ -1,
+ wdest,
+ CLAR_MAX_PATH));
+
+ translate_path(wsource, CLAR_MAX_PATH);
+ translate_path(wdest, CLAR_MAX_PATH);
+
+ /* Check the source for existence */
+ source_attrs = GetFileAttributesW(wsource);
+ cl_assert(INVALID_FILE_ATTRIBUTES != source_attrs);
+
+ /* Check the target for existence */
+ dest_attrs = GetFileAttributesW(wdest);
+
+ if (INVALID_FILE_ATTRIBUTES != dest_attrs) {
+ /* Target exists; append last path part of source to target.
+ * Use FindFirstFile to parse the path */
+ find_handle = FindFirstFileW(wsource, &find_data);
+ cl_assert(INVALID_HANDLE_VALUE != find_handle);
+ wcscat_s(wdest, CLAR_MAX_PATH, L"\\");
+ wcscat_s(wdest, CLAR_MAX_PATH, find_data.cFileName);
+ FindClose(find_handle);
+
+ /* Check the new target for existence */
+ cl_assert(INVALID_FILE_ATTRIBUTES == GetFileAttributesW(wdest));
+ }
+
+ if (FILE_ATTRIBUTE_DIRECTORY & source_attrs)
+ fs_copydir_helper(wsource, wdest);
+ else
+ cl_assert(CopyFileW(wsource, wdest, TRUE));
+}
+
+void
+cl_fs_cleanup(void)
+{
+#ifdef CLAR_FIXTURE_PATH
+ fs_rm(fixture_path(_clar_path, "*"));
+#else
+ ((void)fs_copy); /* unused */
+#endif
+}
+
+#else
+
+#include <errno.h>
+#include <string.h>
+#include <limits.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if defined(__linux__)
+# include <sys/sendfile.h>
+#endif
+
+#if defined(__APPLE__)
+# include <copyfile.h>
+#endif
+
+static void basename_r(const char **out, int *out_len, const char *in)
+{
+ size_t in_len = strlen(in), start_pos;
+
+ for (in_len = strlen(in); in_len; in_len--) {
+ if (in[in_len - 1] != '/')
+ break;
+ }
+
+ for (start_pos = in_len; start_pos; start_pos--) {
+ if (in[start_pos - 1] == '/')
+ break;
+ }
+
+ cl_assert(in_len - start_pos < INT_MAX);
+
+ if (in_len - start_pos > 0) {
+ *out = &in[start_pos];
+ *out_len = (in_len - start_pos);
+ } else {
+ *out = "/";
+ *out_len = 1;
+ }
+}
+
+static char *joinpath(const char *dir, const char *base, int base_len)
+{
+ char *out;
+ int len;
+
+ if (base_len == -1) {
+ size_t bl = strlen(base);
+
+ cl_assert(bl < INT_MAX);
+ base_len = (int)bl;
+ }
+
+ len = strlen(dir) + base_len + 2;
+ cl_assert(len > 0);
+
+ cl_assert(out = malloc(len));
+ cl_assert(snprintf(out, len, "%s/%.*s", dir, base_len, base) < len);
+
+ return out;
+}
+
+static void
+fs_copydir_helper(const char *source, const char *dest, int dest_mode)
+{
+ DIR *source_dir;
+ struct dirent *d;
+
+ mkdir(dest, dest_mode);
+
+ cl_assert_(source_dir = opendir(source), "Could not open source dir");
+ while ((d = (errno = 0, readdir(source_dir))) != NULL) {
+ char *child;
+
+ if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
+ continue;
+
+ child = joinpath(source, d->d_name, -1);
+ fs_copy(child, dest);
+ free(child);
+ }
+
+ cl_assert_(errno == 0, "Failed to iterate source dir");
+
+ closedir(source_dir);
+}
+
+static void
+fs_copyfile_helper(const char *source, size_t source_len, const char *dest, int dest_mode)
+{
+ int in, out;
+
+ cl_must_pass((in = open(source, O_RDONLY)));
+ cl_must_pass((out = open(dest, O_WRONLY|O_CREAT|O_TRUNC, dest_mode)));
+
+#if USE_FCOPYFILE && defined(__APPLE__)
+ ((void)(source_len)); /* unused */
+ cl_must_pass(fcopyfile(in, out, 0, COPYFILE_DATA));
+#elif USE_SENDFILE && defined(__linux__)
+ {
+ ssize_t ret = 0;
+
+ while (source_len && (ret = sendfile(out, in, NULL, source_len)) > 0) {
+ source_len -= (size_t)ret;
+ }
+ cl_assert(ret >= 0);
+ }
+#else
+ {
+ char buf[131072];
+ ssize_t ret;
+
+ ((void)(source_len)); /* unused */
+
+ while ((ret = read(in, buf, sizeof(buf))) > 0) {
+ size_t len = (size_t)ret;
+
+ while (len && (ret = write(out, buf, len)) > 0) {
+ cl_assert(ret <= (ssize_t)len);
+ len -= ret;
+ }
+ cl_assert(ret >= 0);
+ }
+ cl_assert(ret == 0);
+ }
+#endif
+
+ close(in);
+ close(out);
+}
+
+static void
+fs_copy(const char *source, const char *_dest)
+{
+ char *dbuf = NULL;
+ const char *dest = NULL;
+ struct stat source_st, dest_st;
+
+ cl_must_pass_(lstat(source, &source_st), "Failed to stat copy source");
+
+ if (lstat(_dest, &dest_st) == 0) {
+ const char *base;
+ int base_len;
+
+ /* Target exists and is directory; append basename */
+ cl_assert(S_ISDIR(dest_st.st_mode));
+
+ basename_r(&base, &base_len, source);
+ cl_assert(base_len < INT_MAX);
+
+ dbuf = joinpath(_dest, base, base_len);
+ dest = dbuf;
+ } else if (errno != ENOENT) {
+ cl_fail("Cannot copy; cannot stat destination");
+ } else {
+ dest = _dest;
+ }
+
+ if (S_ISDIR(source_st.st_mode)) {
+ fs_copydir_helper(source, dest, source_st.st_mode);
+ } else {
+ fs_copyfile_helper(source, source_st.st_size, dest, source_st.st_mode);
+ }
+
+ free(dbuf);
+}
+
+static void
+fs_rmdir_helper(const char *path)
+{
+ DIR *dir;
+ struct dirent *d;
+
+ cl_assert_(dir = opendir(path), "Could not open dir");
+ while ((d = (errno = 0, readdir(dir))) != NULL) {
+ char *child;
+
+ if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
+ continue;
+
+ child = joinpath(path, d->d_name, -1);
+ fs_rm(child);
+ free(child);
+ }
+
+ cl_assert_(errno == 0, "Failed to iterate source dir");
+ closedir(dir);
+
+ cl_must_pass_(rmdir(path), "Could not remove directory");
+}
+
+static void
+fs_rm(const char *path)
+{
+ struct stat st;
+
+ if (lstat(path, &st)) {
+ if (errno == ENOENT)
+ return;
+
+ cl_fail("Cannot copy; cannot stat destination");
+ }
+
+ if (S_ISDIR(st.st_mode)) {
+ fs_rmdir_helper(path);
+ } else {
+ cl_must_pass(unlink(path));
+ }
+}
+
+void
+cl_fs_cleanup(void)
+{
+ clar_unsandbox();
+ clar_sandbox();
+}
+#endif
diff --git a/t/unit-tests/clar/clar/print.h b/t/unit-tests/clar/clar/print.h
new file mode 100644
index 0000000000..c17e2f693b
--- /dev/null
+++ b/t/unit-tests/clar/clar/print.h
@@ -0,0 +1,211 @@
+/* clap: clar protocol, the traditional clar output format */
+
+static void clar_print_clap_init(int test_count, int suite_count, const char *suite_names)
+{
+ (void)test_count;
+ printf("Loaded %d suites: %s\n", (int)suite_count, suite_names);
+ printf("Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')\n");
+}
+
+static void clar_print_clap_shutdown(int test_count, int suite_count, int error_count)
+{
+ (void)test_count;
+ (void)suite_count;
+ (void)error_count;
+
+ printf("\n\n");
+ clar_report_all();
+}
+
+static void clar_print_clap_error(int num, const struct clar_report *report, const struct clar_error *error)
+{
+ printf(" %d) Failure:\n", num);
+
+ printf("%s::%s [%s:%"PRIuZ"]\n",
+ report->suite,
+ report->test,
+ error->file,
+ error->line_number);
+
+ printf(" %s\n", error->error_msg);
+
+ if (error->description != NULL)
+ printf(" %s\n", error->description);
+
+ printf("\n");
+ fflush(stdout);
+}
+
+static void clar_print_clap_ontest(const char *suite_name, const char *test_name, int test_number, enum cl_test_status status)
+{
+ (void)test_name;
+ (void)test_number;
+
+ if (_clar.verbosity > 1) {
+ printf("%s::%s: ", suite_name, test_name);
+
+ switch (status) {
+ case CL_TEST_OK: printf("ok\n"); break;
+ case CL_TEST_FAILURE: printf("fail\n"); break;
+ case CL_TEST_SKIP: printf("skipped"); break;
+ case CL_TEST_NOTRUN: printf("notrun"); break;
+ }
+ } else {
+ switch (status) {
+ case CL_TEST_OK: printf("."); break;
+ case CL_TEST_FAILURE: printf("F"); break;
+ case CL_TEST_SKIP: printf("S"); break;
+ case CL_TEST_NOTRUN: printf("N"); break;
+ }
+
+ fflush(stdout);
+ }
+}
+
+static void clar_print_clap_onsuite(const char *suite_name, int suite_index)
+{
+ if (_clar.verbosity == 1)
+ printf("\n%s", suite_name);
+
+ (void)suite_index;
+}
+
+static void clar_print_clap_onabort(const char *fmt, va_list arg)
+{
+ vfprintf(stderr, fmt, arg);
+}
+
+/* tap: test anywhere protocol format */
+
+static void clar_print_tap_init(int test_count, int suite_count, const char *suite_names)
+{
+ (void)test_count;
+ (void)suite_count;
+ (void)suite_names;
+ printf("TAP version 13\n");
+}
+
+static void clar_print_tap_shutdown(int test_count, int suite_count, int error_count)
+{
+ (void)suite_count;
+ (void)error_count;
+
+ printf("1..%d\n", test_count);
+}
+
+static void clar_print_tap_error(int num, const struct clar_report *report, const struct clar_error *error)
+{
+ (void)num;
+ (void)report;
+ (void)error;
+}
+
+static void print_escaped(const char *str)
+{
+ char *c;
+
+ while ((c = strchr(str, '\'')) != NULL) {
+ printf("%.*s", (int)(c - str), str);
+ printf("''");
+ str = c + 1;
+ }
+
+ printf("%s", str);
+}
+
+static void clar_print_tap_ontest(const char *suite_name, const char *test_name, int test_number, enum cl_test_status status)
+{
+ const struct clar_error *error = _clar.last_report->errors;
+
+ (void)test_name;
+ (void)test_number;
+
+ switch(status) {
+ case CL_TEST_OK:
+ printf("ok %d - %s::%s\n", test_number, suite_name, test_name);
+ break;
+ case CL_TEST_FAILURE:
+ printf("not ok %d - %s::%s\n", test_number, suite_name, test_name);
+
+ printf(" ---\n");
+ printf(" reason: |\n");
+ printf(" %s\n", error->error_msg);
+
+ if (error->description)
+ printf(" %s\n", error->description);
+
+ printf(" at:\n");
+ printf(" file: '"); print_escaped(error->file); printf("'\n");
+ printf(" line: %" PRIuZ "\n", error->line_number);
+ printf(" function: '%s'\n", error->function);
+ printf(" ---\n");
+
+ break;
+ case CL_TEST_SKIP:
+ case CL_TEST_NOTRUN:
+ printf("ok %d - # SKIP %s::%s\n", test_number, suite_name, test_name);
+ break;
+ }
+
+ fflush(stdout);
+}
+
+static void clar_print_tap_onsuite(const char *suite_name, int suite_index)
+{
+ printf("# start of suite %d: %s\n", suite_index, suite_name);
+}
+
+static void clar_print_tap_onabort(const char *fmt, va_list arg)
+{
+ printf("Bail out! ");
+ vprintf(fmt, arg);
+ fflush(stdout);
+}
+
+/* indirection between protocol output selection */
+
+#define PRINT(FN, ...) do { \
+ switch (_clar.output_format) { \
+ case CL_OUTPUT_CLAP: \
+ clar_print_clap_##FN (__VA_ARGS__); \
+ break; \
+ case CL_OUTPUT_TAP: \
+ clar_print_tap_##FN (__VA_ARGS__); \
+ break; \
+ default: \
+ abort(); \
+ } \
+ } while (0)
+
+static void clar_print_init(int test_count, int suite_count, const char *suite_names)
+{
+ PRINT(init, test_count, suite_count, suite_names);
+}
+
+static void clar_print_shutdown(int test_count, int suite_count, int error_count)
+{
+ PRINT(shutdown, test_count, suite_count, error_count);
+}
+
+static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error)
+{
+ PRINT(error, num, report, error);
+}
+
+static void clar_print_ontest(const char *suite_name, const char *test_name, int test_number, enum cl_test_status status)
+{
+ PRINT(ontest, suite_name, test_name, test_number, status);
+}
+
+static void clar_print_onsuite(const char *suite_name, int suite_index)
+{
+ PRINT(onsuite, suite_name, suite_index);
+}
+
+static void clar_print_onabort(const char *msg, ...)
+{
+ va_list argp;
+ va_start(argp, msg);
+ PRINT(onabort, msg, argp);
+ va_end(argp);
+}
diff --git a/t/unit-tests/clar/clar/sandbox.h b/t/unit-tests/clar/clar/sandbox.h
new file mode 100644
index 0000000000..e25057b7c4
--- /dev/null
+++ b/t/unit-tests/clar/clar/sandbox.h
@@ -0,0 +1,159 @@
+#ifdef __APPLE__
+#include <sys/syslimits.h>
+#endif
+
+static char _clar_path[4096 + 1];
+
+static int
+is_valid_tmp_path(const char *path)
+{
+ STAT_T st;
+
+ if (stat(path, &st) != 0)
+ return 0;
+
+ if (!S_ISDIR(st.st_mode))
+ return 0;
+
+ return (access(path, W_OK) == 0);
+}
+
+static int
+find_tmp_path(char *buffer, size_t length)
+{
+#ifndef _WIN32
+ static const size_t var_count = 5;
+ static const char *env_vars[] = {
+ "CLAR_TMP", "TMPDIR", "TMP", "TEMP", "USERPROFILE"
+ };
+
+ size_t i;
+
+ for (i = 0; i < var_count; ++i) {
+ const char *env = getenv(env_vars[i]);
+ if (!env)
+ continue;
+
+ if (is_valid_tmp_path(env)) {
+#ifdef __APPLE__
+ if (length >= PATH_MAX && realpath(env, buffer) != NULL)
+ return 0;
+#endif
+ strncpy(buffer, env, length - 1);
+ buffer[length - 1] = '\0';
+ return 0;
+ }
+ }
+
+ /* If the environment doesn't say anything, try to use /tmp */
+ if (is_valid_tmp_path("/tmp")) {
+#ifdef __APPLE__
+ if (length >= PATH_MAX && realpath("/tmp", buffer) != NULL)
+ return 0;
+#endif
+ strncpy(buffer, "/tmp", length - 1);
+ buffer[length - 1] = '\0';
+ return 0;
+ }
+
+#else
+ DWORD env_len = GetEnvironmentVariable("CLAR_TMP", buffer, (DWORD)length);
+ if (env_len > 0 && env_len < (DWORD)length)
+ return 0;
+
+ if (GetTempPath((DWORD)length, buffer))
+ return 0;
+#endif
+
+ /* This system doesn't like us, try to use the current directory */
+ if (is_valid_tmp_path(".")) {
+ strncpy(buffer, ".", length - 1);
+ buffer[length - 1] = '\0';
+ return 0;
+ }
+
+ return -1;
+}
+
+static void clar_unsandbox(void)
+{
+ if (_clar_path[0] == '\0')
+ return;
+
+ cl_must_pass(chdir(".."));
+
+ fs_rm(_clar_path);
+}
+
+static int build_sandbox_path(void)
+{
+#ifdef CLAR_TMPDIR
+ const char path_tail[] = CLAR_TMPDIR "_XXXXXX";
+#else
+ const char path_tail[] = "clar_tmp_XXXXXX";
+#endif
+
+ size_t len;
+
+ if (find_tmp_path(_clar_path, sizeof(_clar_path)) < 0)
+ return -1;
+
+ len = strlen(_clar_path);
+
+#ifdef _WIN32
+ { /* normalize path to POSIX forward slashes */
+ size_t i;
+ for (i = 0; i < len; ++i) {
+ if (_clar_path[i] == '\\')
+ _clar_path[i] = '/';
+ }
+ }
+#endif
+
+ if (_clar_path[len - 1] != '/') {
+ _clar_path[len++] = '/';
+ }
+
+ strncpy(_clar_path + len, path_tail, sizeof(_clar_path) - len);
+
+#if defined(__MINGW32__)
+ if (_mktemp(_clar_path) == NULL)
+ return -1;
+
+ if (mkdir(_clar_path, 0700) != 0)
+ return -1;
+#elif defined(__TANDEM)
+ if (mktemp(_clar_path) == NULL)
+ return -1;
+
+ if (mkdir(_clar_path, 0700) != 0)
+ return -1;
+#elif defined(_WIN32)
+ if (_mktemp_s(_clar_path, sizeof(_clar_path)) != 0)
+ return -1;
+
+ if (mkdir(_clar_path, 0700) != 0)
+ return -1;
+#else
+ if (mkdtemp(_clar_path) == NULL)
+ return -1;
+#endif
+
+ return 0;
+}
+
+static int clar_sandbox(void)
+{
+ if (_clar_path[0] == '\0' && build_sandbox_path() < 0)
+ return -1;
+
+ if (chdir(_clar_path) != 0)
+ return -1;
+
+ return 0;
+}
+
+const char *clar_sandbox_path(void)
+{
+ return _clar_path;
+}
diff --git a/t/unit-tests/clar/clar/summary.h b/t/unit-tests/clar/clar/summary.h
new file mode 100644
index 0000000000..4dd352e28b
--- /dev/null
+++ b/t/unit-tests/clar/clar/summary.h
@@ -0,0 +1,143 @@
+
+#include <stdio.h>
+#include <time.h>
+
+static int clar_summary_close_tag(
+ struct clar_summary *summary, const char *tag, int indent)
+{
+ const char *indt;
+
+ if (indent == 0) indt = "";
+ else if (indent == 1) indt = "\t";
+ else indt = "\t\t";
+
+ return fprintf(summary->fp, "%s</%s>\n", indt, tag);
+}
+
+static int clar_summary_testsuites(struct clar_summary *summary)
+{
+ return fprintf(summary->fp, "<testsuites>\n");
+}
+
+static int clar_summary_testsuite(struct clar_summary *summary,
+ int idn, const char *name, time_t timestamp,
+ int test_count, int fail_count, int error_count)
+{
+ struct tm *tm = localtime(&timestamp);
+ char iso_dt[20];
+
+ if (strftime(iso_dt, sizeof(iso_dt), "%Y-%m-%dT%H:%M:%S", tm) == 0)
+ return -1;
+
+ return fprintf(summary->fp, "\t<testsuite"
+ " id=\"%d\""
+ " name=\"%s\""
+ " hostname=\"localhost\""
+ " timestamp=\"%s\""
+ " tests=\"%d\""
+ " failures=\"%d\""
+ " errors=\"%d\">\n",
+ idn, name, iso_dt, test_count, fail_count, error_count);
+}
+
+static int clar_summary_testcase(struct clar_summary *summary,
+ const char *name, const char *classname, double elapsed)
+{
+ return fprintf(summary->fp,
+ "\t\t<testcase name=\"%s\" classname=\"%s\" time=\"%.2f\">\n",
+ name, classname, elapsed);
+}
+
+static int clar_summary_failure(struct clar_summary *summary,
+ const char *type, const char *message, const char *desc)
+{
+ return fprintf(summary->fp,
+ "\t\t\t<failure type=\"%s\"><![CDATA[%s\n%s]]></failure>\n",
+ type, message, desc);
+}
+
+static int clar_summary_skipped(struct clar_summary *summary)
+{
+ return fprintf(summary->fp, "\t\t\t<skipped />\n");
+}
+
+struct clar_summary *clar_summary_init(const char *filename)
+{
+ struct clar_summary *summary;
+ FILE *fp;
+
+ if ((fp = fopen(filename, "w")) == NULL) {
+ perror("fopen");
+ return NULL;
+ }
+
+ if ((summary = malloc(sizeof(struct clar_summary))) == NULL) {
+ perror("malloc");
+ fclose(fp);
+ return NULL;
+ }
+
+ summary->filename = filename;
+ summary->fp = fp;
+
+ return summary;
+}
+
+int clar_summary_shutdown(struct clar_summary *summary)
+{
+ struct clar_report *report;
+ const char *last_suite = NULL;
+
+ if (clar_summary_testsuites(summary) < 0)
+ goto on_error;
+
+ report = _clar.reports;
+ while (report != NULL) {
+ struct clar_error *error = report->errors;
+
+ if (last_suite == NULL || strcmp(last_suite, report->suite) != 0) {
+ if (clar_summary_testsuite(summary, 0, report->suite,
+ report->start, _clar.tests_ran, _clar.total_errors, 0) < 0)
+ goto on_error;
+ }
+
+ last_suite = report->suite;
+
+ clar_summary_testcase(summary, report->test, report->suite, report->elapsed);
+
+ while (error != NULL) {
+ if (clar_summary_failure(summary, "assert",
+ error->error_msg, error->description) < 0)
+ goto on_error;
+
+ error = error->next;
+ }
+
+ if (report->status == CL_TEST_SKIP)
+ clar_summary_skipped(summary);
+
+ if (clar_summary_close_tag(summary, "testcase", 2) < 0)
+ goto on_error;
+
+ report = report->next;
+
+ if (!report || strcmp(last_suite, report->suite) != 0) {
+ if (clar_summary_close_tag(summary, "testsuite", 1) < 0)
+ goto on_error;
+ }
+ }
+
+ if (clar_summary_close_tag(summary, "testsuites", 0) < 0 ||
+ fclose(summary->fp) != 0)
+ goto on_error;
+
+ printf("written summary file to %s\n", summary->filename);
+
+ free(summary);
+ return 0;
+
+on_error:
+ fclose(summary->fp);
+ free(summary);
+ return -1;
+}
diff --git a/t/unit-tests/clar/generate.py b/t/unit-tests/clar/generate.py
new file mode 100755
index 0000000000..80996ac3e7
--- /dev/null
+++ b/t/unit-tests/clar/generate.py
@@ -0,0 +1,266 @@
+#!/usr/bin/env python
+#
+# Copyright (c) Vicent Marti. All rights reserved.
+#
+# This file is part of clar, distributed under the ISC license.
+# For full terms see the included COPYING file.
+#
+
+from __future__ import with_statement
+from string import Template
+import re, fnmatch, os, sys, codecs, pickle
+
+class Module(object):
+ class Template(object):
+ def __init__(self, module):
+ self.module = module
+
+ def _render_callback(self, cb):
+ if not cb:
+ return ' { NULL, NULL }'
+ return ' { "%s", &%s }' % (cb['short_name'], cb['symbol'])
+
+ class DeclarationTemplate(Template):
+ def render(self):
+ out = "\n".join("extern %s;" % cb['declaration'] for cb in self.module.callbacks) + "\n"
+
+ for initializer in self.module.initializers:
+ out += "extern %s;\n" % initializer['declaration']
+
+ if self.module.cleanup:
+ out += "extern %s;\n" % self.module.cleanup['declaration']
+
+ return out
+
+ class CallbacksTemplate(Template):
+ def render(self):
+ out = "static const struct clar_func _clar_cb_%s[] = {\n" % self.module.name
+ out += ",\n".join(self._render_callback(cb) for cb in self.module.callbacks)
+ out += "\n};\n"
+ return out
+
+ class InfoTemplate(Template):
+ def render(self):
+ templates = []
+
+ initializers = self.module.initializers
+ if len(initializers) == 0:
+ initializers = [ None ]
+
+ for initializer in initializers:
+ name = self.module.clean_name()
+ if initializer and initializer['short_name'].startswith('initialize_'):
+ variant = initializer['short_name'][len('initialize_'):]
+ name += " (%s)" % variant.replace('_', ' ')
+
+ template = Template(
+ r"""
+ {
+ "${clean_name}",
+ ${initialize},
+ ${cleanup},
+ ${cb_ptr}, ${cb_count}, ${enabled}
+ }"""
+ ).substitute(
+ clean_name = name,
+ initialize = self._render_callback(initializer),
+ cleanup = self._render_callback(self.module.cleanup),
+ cb_ptr = "_clar_cb_%s" % self.module.name,
+ cb_count = len(self.module.callbacks),
+ enabled = int(self.module.enabled)
+ )
+ templates.append(template)
+
+ return ','.join(templates)
+
+ def __init__(self, name):
+ self.name = name
+
+ self.mtime = None
+ self.enabled = True
+ self.modified = False
+
+ def clean_name(self):
+ return self.name.replace("_", "::")
+
+ def _skip_comments(self, text):
+ SKIP_COMMENTS_REGEX = re.compile(
+ r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
+ re.DOTALL | re.MULTILINE)
+
+ def _replacer(match):
+ s = match.group(0)
+ return "" if s.startswith('/') else s
+
+ return re.sub(SKIP_COMMENTS_REGEX, _replacer, text)
+
+ def parse(self, contents):
+ TEST_FUNC_REGEX = r"^(void\s+(test_%s__(\w+))\s*\(\s*void\s*\))\s*\{"
+
+ contents = self._skip_comments(contents)
+ regex = re.compile(TEST_FUNC_REGEX % self.name, re.MULTILINE)
+
+ self.callbacks = []
+ self.initializers = []
+ self.cleanup = None
+
+ for (declaration, symbol, short_name) in regex.findall(contents):
+ data = {
+ "short_name" : short_name,
+ "declaration" : declaration,
+ "symbol" : symbol
+ }
+
+ if short_name.startswith('initialize'):
+ self.initializers.append(data)
+ elif short_name == 'cleanup':
+ self.cleanup = data
+ else:
+ self.callbacks.append(data)
+
+ return self.callbacks != []
+
+ def refresh(self, path):
+ self.modified = False
+
+ try:
+ st = os.stat(path)
+
+ # Not modified
+ if st.st_mtime == self.mtime:
+ return True
+
+ self.modified = True
+ self.mtime = st.st_mtime
+
+ with codecs.open(path, encoding='utf-8') as fp:
+ raw_content = fp.read()
+
+ except IOError:
+ return False
+
+ return self.parse(raw_content)
+
+class TestSuite(object):
+
+ def __init__(self, path, output):
+ self.path = path
+ self.output = output
+
+ def should_generate(self, path):
+ if not os.path.isfile(path):
+ return True
+
+ if any(module.modified for module in self.modules.values()):
+ return True
+
+ return False
+
+ def find_modules(self):
+ modules = []
+ for root, _, files in os.walk(self.path):
+ module_root = root[len(self.path):]
+ module_root = [c for c in module_root.split(os.sep) if c]
+
+ tests_in_module = fnmatch.filter(files, "*.c")
+
+ for test_file in tests_in_module:
+ full_path = os.path.join(root, test_file)
+ module_name = "_".join(module_root + [test_file[:-2]]).replace("-", "_")
+
+ modules.append((full_path, module_name))
+
+ return modules
+
+ def load_cache(self):
+ path = os.path.join(self.output, '.clarcache')
+ cache = {}
+
+ try:
+ fp = open(path, 'rb')
+ cache = pickle.load(fp)
+ fp.close()
+ except (IOError, ValueError):
+ pass
+
+ return cache
+
+ def save_cache(self):
+ path = os.path.join(self.output, '.clarcache')
+ with open(path, 'wb') as cache:
+ pickle.dump(self.modules, cache)
+
+ def load(self, force = False):
+ module_data = self.find_modules()
+ self.modules = {} if force else self.load_cache()
+
+ for path, name in module_data:
+ if name not in self.modules:
+ self.modules[name] = Module(name)
+
+ if not self.modules[name].refresh(path):
+ del self.modules[name]
+
+ def disable(self, excluded):
+ for exclude in excluded:
+ for module in self.modules.values():
+ name = module.clean_name()
+ if name.startswith(exclude):
+ module.enabled = False
+ module.modified = True
+
+ def suite_count(self):
+ return sum(max(1, len(m.initializers)) for m in self.modules.values())
+
+ def callback_count(self):
+ return sum(len(module.callbacks) for module in self.modules.values())
+
+ def write(self):
+ output = os.path.join(self.output, 'clar.suite')
+
+ if not self.should_generate(output):
+ return False
+
+ with open(output, 'w') as data:
+ modules = sorted(self.modules.values(), key=lambda module: module.name)
+
+ for module in modules:
+ t = Module.DeclarationTemplate(module)
+ data.write(t.render())
+
+ for module in modules:
+ t = Module.CallbacksTemplate(module)
+ data.write(t.render())
+
+ suites = "static struct clar_suite _clar_suites[] = {" + ','.join(
+ Module.InfoTemplate(module).render() for module in modules
+ ) + "\n};\n"
+
+ data.write(suites)
+
+ data.write("static const size_t _clar_suite_count = %d;\n" % self.suite_count())
+ data.write("static const size_t _clar_callback_count = %d;\n" % self.callback_count())
+
+ self.save_cache()
+ return True
+
+if __name__ == '__main__':
+ from optparse import OptionParser
+
+ parser = OptionParser()
+ parser.add_option('-f', '--force', action="store_true", dest='force', default=False)
+ parser.add_option('-x', '--exclude', dest='excluded', action='append', default=[])
+ parser.add_option('-o', '--output', dest='output')
+
+ options, args = parser.parse_args()
+ if len(args) > 1:
+ print("More than one path given")
+ sys.exit(1)
+
+ path = args.pop() if args else '.'
+ output = options.output or path
+ suite = TestSuite(path, output)
+ suite.load(options.force)
+ suite.disable(options.excluded)
+ if suite.write():
+ print("Written `clar.suite` (%d tests in %d suites)" % (suite.callback_count(), suite.suite_count()))
diff --git a/t/unit-tests/clar/test/.gitignore b/t/unit-tests/clar/test/.gitignore
new file mode 100644
index 0000000000..a477d0c40c
--- /dev/null
+++ b/t/unit-tests/clar/test/.gitignore
@@ -0,0 +1,4 @@
+clar.suite
+.clarcache
+clar_test
+*.o
diff --git a/t/unit-tests/clar/test/Makefile b/t/unit-tests/clar/test/Makefile
new file mode 100644
index 0000000000..93c6b2ad32
--- /dev/null
+++ b/t/unit-tests/clar/test/Makefile
@@ -0,0 +1,39 @@
+#
+# Copyright (c) Vicent Marti. All rights reserved.
+#
+# This file is part of clar, distributed under the ISC license.
+# For full terms see the included COPYING file.
+#
+
+#
+# Set up the path to the clar sources and to the fixtures directory
+#
+# The fixture path needs to be an absolute path so it can be used
+# even after we have chdir'ed into the test directory while testing.
+#
+CURRENT_MAKEFILE := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
+TEST_DIRECTORY := $(abspath $(dir $(CURRENT_MAKEFILE)))
+CLAR_PATH := $(dir $(TEST_DIRECTORY))
+CLAR_FIXTURE_PATH := $(TEST_DIRECTORY)/resources/
+
+CFLAGS=-g -I.. -I. -Wall -DCLAR_FIXTURE_PATH=\"$(CLAR_FIXTURE_PATH)\"
+
+.PHONY: clean
+
+# list the objects that go into our test
+objects = main.o sample.o
+
+# build the test executable itself
+clar_test: $(objects) clar_test.h clar.suite $(CLAR_PATH)clar.c
+ $(CC) $(CFLAGS) -o $@ "$(CLAR_PATH)clar.c" $(objects)
+
+# test object files depend on clar macros
+$(objects) : $(CLAR_PATH)clar.h
+
+# build the clar.suite file of test metadata
+clar.suite:
+ python "$(CLAR_PATH)generate.py" .
+
+# remove all generated files
+clean:
+ $(RM) -rf *.o clar.suite .clarcache clar_test clar_test.dSYM
diff --git a/t/unit-tests/clar/test/clar_test.h b/t/unit-tests/clar/test/clar_test.h
new file mode 100644
index 0000000000..0fcaa639aa
--- /dev/null
+++ b/t/unit-tests/clar/test/clar_test.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) Vicent Marti. All rights reserved.
+ *
+ * This file is part of clar, distributed under the ISC license.
+ * For full terms see the included COPYING file.
+ */
+#ifndef __CLAR_TEST__
+#define __CLAR_TEST__
+
+/* Import the standard clar helper functions */
+#include "clar.h"
+
+/* Your custom shared includes / defines here */
+extern int global_test_counter;
+
+#endif
diff --git a/t/unit-tests/clar/test/main.c b/t/unit-tests/clar/test/main.c
new file mode 100644
index 0000000000..59e56ad255
--- /dev/null
+++ b/t/unit-tests/clar/test/main.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) Vicent Marti. All rights reserved.
+ *
+ * This file is part of clar, distributed under the ISC license.
+ * For full terms see the included COPYING file.
+ */
+
+#include "clar_test.h"
+
+/*
+ * Sample main() for clar tests.
+ *
+ * You should write your own main routine for clar tests that does specific
+ * setup and teardown as necessary for your application. The only required
+ * line is the call to `clar_test(argc, argv)`, which will execute the test
+ * suite. If you want to check the return value of the test application,
+ * your main() should return the same value returned by clar_test().
+ */
+
+int global_test_counter = 0;
+
+#ifdef _WIN32
+int __cdecl main(int argc, char *argv[])
+#else
+int main(int argc, char *argv[])
+#endif
+{
+ int ret;
+
+ /* Your custom initialization here */
+ global_test_counter = 0;
+
+ /* Run the test suite */
+ ret = clar_test(argc, argv);
+
+ /* Your custom cleanup here */
+ cl_assert_equal_i(8, global_test_counter);
+
+ return ret;
+}
diff --git a/t/unit-tests/clar/test/main.c.sample b/t/unit-tests/clar/test/main.c.sample
new file mode 100644
index 0000000000..a4d91b72fa
--- /dev/null
+++ b/t/unit-tests/clar/test/main.c.sample
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) Vicent Marti. All rights reserved.
+ *
+ * This file is part of clar, distributed under the ISC license.
+ * For full terms see the included COPYING file.
+ */
+
+#include "clar_test.h"
+
+/*
+ * Minimal main() for clar tests.
+ *
+ * Modify this with any application specific setup or teardown that you need.
+ * The only required line is the call to `clar_test(argc, argv)`, which will
+ * execute the test suite. If you want to check the return value of the test
+ * application, main() should return the same value returned by clar_test().
+ */
+
+#ifdef _WIN32
+int __cdecl main(int argc, char *argv[])
+#else
+int main(int argc, char *argv[])
+#endif
+{
+ /* Run the test suite */
+ return clar_test(argc, argv);
+}
diff --git a/t/unit-tests/clar/test/resources/test/file b/t/unit-tests/clar/test/resources/test/file
new file mode 100644
index 0000000000..220f4aa98a
--- /dev/null
+++ b/t/unit-tests/clar/test/resources/test/file
@@ -0,0 +1 @@
+File
diff --git a/t/unit-tests/clar/test/sample.c b/t/unit-tests/clar/test/sample.c
new file mode 100644
index 0000000000..faa1209262
--- /dev/null
+++ b/t/unit-tests/clar/test/sample.c
@@ -0,0 +1,84 @@
+#include "clar_test.h"
+#include <sys/stat.h>
+
+static int file_size(const char *filename)
+{
+ struct stat st;
+
+ if (stat(filename, &st) == 0)
+ return (int)st.st_size;
+ return -1;
+}
+
+void test_sample__initialize(void)
+{
+ global_test_counter++;
+}
+
+void test_sample__cleanup(void)
+{
+ cl_fixture_cleanup("test");
+
+ cl_assert(file_size("test/file") == -1);
+}
+
+void test_sample__1(void)
+{
+ cl_assert(1);
+ cl_must_pass(0); /* 0 == success */
+ cl_must_fail(-1); /* <0 == failure */
+ cl_must_pass(-1); /* demonstrate a failing call */
+}
+
+void test_sample__2(void)
+{
+ cl_fixture_sandbox("test");
+
+ cl_assert(file_size("test/nonexistent") == -1);
+ cl_assert(file_size("test/file") > 0);
+ cl_assert(100 == 101);
+}
+
+void test_sample__strings(void)
+{
+ const char *actual = "expected";
+ cl_assert_equal_s("expected", actual);
+ cl_assert_equal_s_("expected", actual, "second try with annotation");
+ cl_assert_equal_s_("mismatched", actual, "this one fails");
+}
+
+void test_sample__strings_with_length(void)
+{
+ const char *actual = "expected";
+ cl_assert_equal_strn("expected_", actual, 8);
+ cl_assert_equal_strn("exactly", actual, 2);
+ cl_assert_equal_strn_("expected_", actual, 8, "with annotation");
+ cl_assert_equal_strn_("exactly", actual, 3, "this one fails");
+}
+
+void test_sample__int(void)
+{
+ int value = 100;
+ cl_assert_equal_i(100, value);
+ cl_assert_equal_i_(101, value, "extra note on failing test");
+}
+
+void test_sample__int_fmt(void)
+{
+ int value = 100;
+ cl_assert_equal_i_fmt(022, value, "%04o");
+}
+
+void test_sample__bool(void)
+{
+ int value = 100;
+ cl_assert_equal_b(1, value); /* test equality as booleans */
+ cl_assert_equal_b(0, value);
+}
+
+void test_sample__ptr(void)
+{
+ const char *actual = "expected";
+ cl_assert_equal_p(actual, actual); /* pointers to same object */
+ cl_assert_equal_p(&actual, actual);
+}
diff --git a/t/unit-tests/t-ctype.c b/t/unit-tests/ctype.c
index 6043f0d9bc..32e65867cd 100644
--- a/t/unit-tests/t-ctype.c
+++ b/t/unit-tests/ctype.c
@@ -1,16 +1,16 @@
-#include "test-lib.h"
+#include "unit-test.h"
#define TEST_CHAR_CLASS(class, string) do { \
size_t len = ARRAY_SIZE(string) - 1 + \
BUILD_ASSERT_OR_ZERO(ARRAY_SIZE(string) > 0) + \
BUILD_ASSERT_OR_ZERO(sizeof(string[0]) == sizeof(char)); \
- if_test (#class " works") { \
- for (int i = 0; i < 256; i++) { \
- if (!check_int(class(i), ==, !!memchr(string, i, len)))\
- test_msg(" i: 0x%02x", i); \
- } \
- check(!class(EOF)); \
+ for (int i = 0; i < 256; i++) { \
+ int actual = class(i), expect = !!memchr(string, i, len); \
+ if (actual != expect) \
+ cl_failf("0x%02x is classified incorrectly: expected %d, got %d", \
+ i, expect, actual); \
} \
+ cl_assert(!class(EOF)); \
} while (0)
#define DIGIT "0123456789"
@@ -31,21 +31,72 @@
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" \
"\x7f"
-int cmd_main(int argc UNUSED, const char **argv UNUSED) {
+void test_ctype__isspace(void)
+{
TEST_CHAR_CLASS(isspace, " \n\r\t");
+}
+
+void test_ctype__isdigit(void)
+{
TEST_CHAR_CLASS(isdigit, DIGIT);
+}
+
+void test_ctype__isalpha(void)
+{
TEST_CHAR_CLASS(isalpha, LOWER UPPER);
+}
+
+void test_ctype__isalnum(void)
+{
TEST_CHAR_CLASS(isalnum, LOWER UPPER DIGIT);
+}
+
+void test_ctype__is_glob_special(void)
+{
TEST_CHAR_CLASS(is_glob_special, "*?[\\");
+}
+
+void test_ctype__is_regex_special(void)
+{
TEST_CHAR_CLASS(is_regex_special, "$()*+.?[\\^{|");
+}
+
+void test_ctype__is_pathspec_magic(void)
+{
TEST_CHAR_CLASS(is_pathspec_magic, "!\"#%&',-/:;<=>@_`~");
+}
+
+void test_ctype__isascii(void)
+{
TEST_CHAR_CLASS(isascii, ASCII);
+}
+
+void test_ctype__islower(void)
+{
TEST_CHAR_CLASS(islower, LOWER);
+}
+
+void test_ctype__isupper(void)
+{
TEST_CHAR_CLASS(isupper, UPPER);
+}
+
+void test_ctype__iscntrl(void)
+{
TEST_CHAR_CLASS(iscntrl, CNTRL);
+}
+
+void test_ctype__ispunct(void)
+{
TEST_CHAR_CLASS(ispunct, PUNCT);
+}
+
+void test_ctype__isxdigit(void)
+{
TEST_CHAR_CLASS(isxdigit, DIGIT "abcdefABCDEF");
- TEST_CHAR_CLASS(isprint, LOWER UPPER DIGIT PUNCT " ");
+}
- return test_done();
+void test_ctype__isprint(void)
+{
+ TEST_CHAR_CLASS(isprint, LOWER UPPER DIGIT PUNCT " ");
}
diff --git a/t/unit-tests/lib-reftable.c b/t/unit-tests/lib-reftable.c
new file mode 100644
index 0000000000..ab1fa44a28
--- /dev/null
+++ b/t/unit-tests/lib-reftable.c
@@ -0,0 +1,93 @@
+#include "lib-reftable.h"
+#include "test-lib.h"
+#include "reftable/constants.h"
+#include "reftable/writer.h"
+
+void t_reftable_set_hash(uint8_t *p, int i, uint32_t id)
+{
+ memset(p, (uint8_t)i, hash_size(id));
+}
+
+static ssize_t strbuf_writer_write(void *b, const void *data, size_t sz)
+{
+ strbuf_add(b, data, sz);
+ return sz;
+}
+
+static int strbuf_writer_flush(void *arg UNUSED)
+{
+ return 0;
+}
+
+struct reftable_writer *t_reftable_strbuf_writer(struct strbuf *buf,
+ struct reftable_write_options *opts)
+{
+ return reftable_new_writer(&strbuf_writer_write,
+ &strbuf_writer_flush,
+ buf, opts);
+}
+
+void t_reftable_write_to_buf(struct strbuf *buf,
+ struct reftable_ref_record *refs,
+ size_t nrefs,
+ struct reftable_log_record *logs,
+ size_t nlogs,
+ struct reftable_write_options *_opts)
+{
+ struct reftable_write_options opts = { 0 };
+ const struct reftable_stats *stats;
+ struct reftable_writer *writer;
+ uint64_t min = 0xffffffff;
+ uint64_t max = 0;
+ int ret;
+
+ if (_opts)
+ opts = *_opts;
+
+ for (size_t i = 0; i < nrefs; i++) {
+ uint64_t ui = refs[i].update_index;
+ if (ui > max)
+ max = ui;
+ if (ui < min)
+ min = ui;
+ }
+ for (size_t i = 0; i < nlogs; i++) {
+ uint64_t ui = logs[i].update_index;
+ if (ui > max)
+ max = ui;
+ if (ui < min)
+ min = ui;
+ }
+
+ writer = t_reftable_strbuf_writer(buf, &opts);
+ reftable_writer_set_limits(writer, min, max);
+
+ if (nrefs) {
+ ret = reftable_writer_add_refs(writer, refs, nrefs);
+ check_int(ret, ==, 0);
+ }
+
+ if (nlogs) {
+ ret = reftable_writer_add_logs(writer, logs, nlogs);
+ check_int(ret, ==, 0);
+ }
+
+ ret = reftable_writer_close(writer);
+ check_int(ret, ==, 0);
+
+ stats = reftable_writer_stats(writer);
+ for (size_t i = 0; i < stats->ref_stats.blocks; i++) {
+ size_t off = i * (opts.block_size ? opts.block_size
+ : DEFAULT_BLOCK_SIZE);
+ if (!off)
+ off = header_size(opts.hash_id == GIT_SHA256_FORMAT_ID ? 2 : 1);
+ check_char(buf->buf[off], ==, 'r');
+ }
+
+ if (nrefs)
+ check_int(stats->ref_stats.blocks, >, 0);
+ if (nlogs)
+ check_int(stats->log_stats.blocks, >, 0);
+
+ reftable_writer_free(writer);
+}
diff --git a/t/unit-tests/lib-reftable.h b/t/unit-tests/lib-reftable.h
new file mode 100644
index 0000000000..d115419084
--- /dev/null
+++ b/t/unit-tests/lib-reftable.h
@@ -0,0 +1,20 @@
+#ifndef LIB_REFTABLE_H
+#define LIB_REFTABLE_H
+
+#include "git-compat-util.h"
+#include "strbuf.h"
+#include "reftable/reftable-writer.h"
+
+void t_reftable_set_hash(uint8_t *p, int i, uint32_t id);
+
+struct reftable_writer *t_reftable_strbuf_writer(struct strbuf *buf,
+ struct reftable_write_options *opts);
+
+void t_reftable_write_to_buf(struct strbuf *buf,
+ struct reftable_ref_record *refs,
+ size_t nrecords,
+ struct reftable_log_record *logs,
+ size_t nlogs,
+ struct reftable_write_options *opts);
+
+#endif
diff --git a/t/unit-tests/strvec.c b/t/unit-tests/strvec.c
new file mode 100644
index 0000000000..bf4c0cb172
--- /dev/null
+++ b/t/unit-tests/strvec.c
@@ -0,0 +1,241 @@
+#include "unit-test.h"
+#include "strbuf.h"
+#include "strvec.h"
+
+#define check_strvec(vec, ...) \
+ do { \
+ const char *expect[] = { __VA_ARGS__ }; \
+ size_t expect_len = ARRAY_SIZE(expect); \
+ cl_assert(expect_len > 0); \
+ cl_assert_equal_p(expect[expect_len - 1], NULL); \
+ cl_assert_equal_i((vec)->nr, expect_len - 1); \
+ cl_assert((vec)->nr <= (vec)->alloc); \
+ for (size_t i = 0; i < expect_len; i++) \
+ cl_assert_equal_s((vec)->v[i], expect[i]); \
+ } while (0)
+
+void test_strvec__init(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ cl_assert_equal_p(vec.v, empty_strvec);
+ cl_assert_equal_i(vec.nr, 0);
+ cl_assert_equal_i(vec.alloc, 0);
+}
+
+void test_strvec__dynamic_init(void)
+{
+ struct strvec vec;
+
+ strvec_init(&vec);
+ cl_assert_equal_p(vec.v, empty_strvec);
+ cl_assert_equal_i(vec.nr, 0);
+ cl_assert_equal_i(vec.alloc, 0);
+}
+
+void test_strvec__clear(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_push(&vec, "foo");
+ strvec_clear(&vec);
+ cl_assert_equal_p(vec.v, empty_strvec);
+ cl_assert_equal_i(vec.nr, 0);
+ cl_assert_equal_i(vec.alloc, 0);
+}
+
+void test_strvec__push(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_push(&vec, "foo");
+ check_strvec(&vec, "foo", NULL);
+
+ strvec_push(&vec, "bar");
+ check_strvec(&vec, "foo", "bar", NULL);
+
+ strvec_clear(&vec);
+}
+
+void test_strvec__pushf(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_pushf(&vec, "foo: %d", 1);
+ check_strvec(&vec, "foo: 1", NULL);
+ strvec_clear(&vec);
+}
+
+void test_strvec__pushl(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
+ check_strvec(&vec, "foo", "bar", "baz", NULL);
+ strvec_clear(&vec);
+}
+
+void test_strvec__pushv(void)
+{
+ const char *strings[] = {
+ "foo", "bar", "baz", NULL,
+ };
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_pushv(&vec, strings);
+ check_strvec(&vec, "foo", "bar", "baz", NULL);
+
+ strvec_clear(&vec);
+}
+
+void test_strvec__replace_at_head(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
+ strvec_replace(&vec, 0, "replaced");
+ check_strvec(&vec, "replaced", "bar", "baz", NULL);
+ strvec_clear(&vec);
+}
+
+void test_strvec__replace_at_tail(void)
+{
+ struct strvec vec = STRVEC_INIT;
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
+ strvec_replace(&vec, 2, "replaced");
+ check_strvec(&vec, "foo", "bar", "replaced", NULL);
+ strvec_clear(&vec);
+}
+
+void test_strvec__replace_in_between(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
+ strvec_replace(&vec, 1, "replaced");
+ check_strvec(&vec, "foo", "replaced", "baz", NULL);
+ strvec_clear(&vec);
+}
+
+void test_strvec__replace_with_substring(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_pushl(&vec, "foo", NULL);
+ strvec_replace(&vec, 0, vec.v[0] + 1);
+ check_strvec(&vec, "oo", NULL);
+ strvec_clear(&vec);
+}
+
+void test_strvec__remove_at_head(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
+ strvec_remove(&vec, 0);
+ check_strvec(&vec, "bar", "baz", NULL);
+ strvec_clear(&vec);
+}
+
+void test_strvec__remove_at_tail(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
+ strvec_remove(&vec, 2);
+ check_strvec(&vec, "foo", "bar", NULL);
+ strvec_clear(&vec);
+}
+
+void test_strvec__remove_in_between(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
+ strvec_remove(&vec, 1);
+ check_strvec(&vec, "foo", "baz", NULL);
+ strvec_clear(&vec);
+}
+
+void test_strvec__pop_empty_array(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_pop(&vec);
+ check_strvec(&vec, NULL);
+ strvec_clear(&vec);
+}
+
+void test_strvec__pop_non_empty_array(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
+ strvec_pop(&vec);
+ check_strvec(&vec, "foo", "bar", NULL);
+ strvec_clear(&vec);
+}
+
+void test_strvec__split_empty_string(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_split(&vec, "");
+ check_strvec(&vec, NULL);
+ strvec_clear(&vec);
+}
+
+void test_strvec__split_single_item(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_split(&vec, "foo");
+ check_strvec(&vec, "foo", NULL);
+ strvec_clear(&vec);
+}
+
+void test_strvec__split_multiple_items(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_split(&vec, "foo bar baz");
+ check_strvec(&vec, "foo", "bar", "baz", NULL);
+ strvec_clear(&vec);
+}
+
+void test_strvec__split_whitespace_only(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_split(&vec, " \t\n");
+ check_strvec(&vec, NULL);
+ strvec_clear(&vec);
+}
+
+void test_strvec__split_multiple_consecutive_whitespaces(void)
+{
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_split(&vec, "foo\n\t bar");
+ check_strvec(&vec, "foo", "bar", NULL);
+ strvec_clear(&vec);
+}
+
+void test_strvec__detach(void)
+{
+ struct strvec vec = STRVEC_INIT;
+ const char **detached;
+
+ strvec_push(&vec, "foo");
+
+ detached = strvec_detach(&vec);
+ cl_assert_equal_s(detached[0], "foo");
+ cl_assert_equal_p(detached[1], NULL);
+
+ cl_assert_equal_p(vec.v, empty_strvec);
+ cl_assert_equal_i(vec.nr, 0);
+ cl_assert_equal_i(vec.alloc, 0);
+
+ free((char *) detached[0]);
+ free(detached);
+}
diff --git a/t/unit-tests/t-reftable-merged.c b/t/unit-tests/t-reftable-merged.c
index e9d100a01e..19e54bdfb8 100644
--- a/t/unit-tests/t-reftable-merged.c
+++ b/t/unit-tests/t-reftable-merged.c
@@ -7,6 +7,7 @@ https://developers.google.com/open-source/licenses/bsd
*/
#include "test-lib.h"
+#include "lib-reftable.h"
#include "reftable/blocksource.h"
#include "reftable/constants.h"
#include "reftable/merged.h"
@@ -15,77 +16,6 @@ https://developers.google.com/open-source/licenses/bsd
#include "reftable/reftable-merged.h"
#include "reftable/reftable-writer.h"
-static ssize_t strbuf_add_void(void *b, const void *data, const size_t sz)
-{
- strbuf_add(b, data, sz);
- return sz;
-}
-
-static int noop_flush(void *arg UNUSED)
-{
- return 0;
-}
-
-static void write_test_table(struct strbuf *buf,
- struct reftable_ref_record refs[], const size_t n)
-{
- uint64_t min = 0xffffffff;
- uint64_t max = 0;
- size_t i;
- int err;
-
- struct reftable_write_options opts = {
- .block_size = 256,
- };
- struct reftable_writer *w = NULL;
- for (i = 0; i < n; i++) {
- uint64_t ui = refs[i].update_index;
- if (ui > max)
- max = ui;
- if (ui < min)
- min = ui;
- }
-
- w = reftable_new_writer(&strbuf_add_void, &noop_flush, buf, &opts);
- reftable_writer_set_limits(w, min, max);
-
- for (i = 0; i < n; i++) {
- uint64_t before = refs[i].update_index;
- int n = reftable_writer_add_ref(w, &refs[i]);
- check_int(n, ==, 0);
- check_int(before, ==, refs[i].update_index);
- }
-
- err = reftable_writer_close(w);
- check(!err);
-
- reftable_writer_free(w);
-}
-
-static void write_test_log_table(struct strbuf *buf, struct reftable_log_record logs[],
- const size_t n, const uint64_t update_index)
-{
- int err;
-
- struct reftable_write_options opts = {
- .block_size = 256,
- .exact_log_message = 1,
- };
- struct reftable_writer *w = NULL;
- w = reftable_new_writer(&strbuf_add_void, &noop_flush, buf, &opts);
- reftable_writer_set_limits(w, update_index, update_index);
-
- for (size_t i = 0; i < n; i++) {
- int err = reftable_writer_add_log(w, &logs[i]);
- check(!err);
- }
-
- err = reftable_writer_close(w);
- check(!err);
-
- reftable_writer_free(w);
-}
-
static struct reftable_merged_table *
merged_table_from_records(struct reftable_ref_record **refs,
struct reftable_block_source **source,
@@ -93,13 +23,16 @@ merged_table_from_records(struct reftable_ref_record **refs,
struct strbuf *buf, const size_t n)
{
struct reftable_merged_table *mt = NULL;
+ struct reftable_write_options opts = {
+ .block_size = 256,
+ };
int err;
REFTABLE_CALLOC_ARRAY(*readers, n);
REFTABLE_CALLOC_ARRAY(*source, n);
for (size_t i = 0; i < n; i++) {
- write_test_table(&buf[i], refs[i], sizes[i]);
+ t_reftable_write_to_buf(&buf[i], refs[i], sizes[i], NULL, 0, &opts);
block_source_from_strbuf(&(*source)[i], &buf[i]);
err = reftable_reader_new(&(*readers)[i], &(*source)[i],
@@ -261,6 +194,81 @@ static void t_merged_refs(void)
reftable_free(bs);
}
+static void t_merged_seek_multiple_times(void)
+{
+ struct reftable_ref_record r1[] = {
+ {
+ .refname = (char *) "a",
+ .update_index = 1,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 1 },
+ },
+ {
+ .refname = (char *) "c",
+ .update_index = 1,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 2 },
+ }
+ };
+ struct reftable_ref_record r2[] = {
+ {
+ .refname = (char *) "b",
+ .update_index = 2,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 3 },
+ },
+ {
+ .refname = (char *) "d",
+ .update_index = 2,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 4 },
+ },
+ };
+ struct reftable_ref_record *refs[] = {
+ r1, r2,
+ };
+ size_t sizes[] = {
+ ARRAY_SIZE(r1), ARRAY_SIZE(r2),
+ };
+ struct strbuf bufs[] = {
+ STRBUF_INIT, STRBUF_INIT,
+ };
+ struct reftable_block_source *sources = NULL;
+ struct reftable_reader **readers = NULL;
+ struct reftable_ref_record rec = { 0 };
+ struct reftable_iterator it = { 0 };
+ struct reftable_merged_table *mt;
+
+ mt = merged_table_from_records(refs, &sources, &readers, sizes, bufs, 2);
+ merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
+
+ for (size_t i = 0; i < 5; i++) {
+ int err = reftable_iterator_seek_ref(&it, "c");
+ check(!err);
+
+ err = reftable_iterator_next_ref(&it, &rec);
+ check(!err);
+ err = reftable_ref_record_equal(&rec, &r1[1], GIT_SHA1_RAWSZ);
+ check(err == 1);
+
+ err = reftable_iterator_next_ref(&it, &rec);
+ check(!err);
+ err = reftable_ref_record_equal(&rec, &r2[1], GIT_SHA1_RAWSZ);
+ check(err == 1);
+
+ err = reftable_iterator_next_ref(&it, &rec);
+ check(err > 0);
+ }
+
+ for (size_t i = 0; i < ARRAY_SIZE(bufs); i++)
+ strbuf_release(&bufs[i]);
+ readers_destroy(readers, ARRAY_SIZE(refs));
+ reftable_ref_record_release(&rec);
+ reftable_iterator_destroy(&it);
+ reftable_merged_table_free(mt);
+ reftable_free(sources);
+}
+
static struct reftable_merged_table *
merged_table_from_log_records(struct reftable_log_record **logs,
struct reftable_block_source **source,
@@ -268,13 +276,17 @@ merged_table_from_log_records(struct reftable_log_record **logs,
struct strbuf *buf, const size_t n)
{
struct reftable_merged_table *mt = NULL;
+ struct reftable_write_options opts = {
+ .block_size = 256,
+ .exact_log_message = 1,
+ };
int err;
REFTABLE_CALLOC_ARRAY(*readers, n);
REFTABLE_CALLOC_ARRAY(*source, n);
for (size_t i = 0; i < n; i++) {
- write_test_log_table(&buf[i], logs[i], sizes[i], i + 1);
+ t_reftable_write_to_buf(&buf[i], NULL, 0, logs[i], sizes[i], &opts);
block_source_from_strbuf(&(*source)[i], &buf[i]);
err = reftable_reader_new(&(*readers)[i], &(*source)[i],
@@ -402,9 +414,7 @@ static void t_default_write_opts(void)
{
struct reftable_write_options opts = { 0 };
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
-
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
struct reftable_ref_record rec = {
.refname = (char *) "master",
.update_index = 1,
@@ -448,6 +458,7 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
TEST(t_default_write_opts(), "merged table with default write opts");
TEST(t_merged_logs(), "merged table with multiple log updates for same ref");
TEST(t_merged_refs(), "merged table with multiple updates to same ref");
+ TEST(t_merged_seek_multiple_times(), "merged table can seek multiple times");
TEST(t_merged_single_record(), "ref ocurring in only one record can be fetched");
return test_done();
diff --git a/t/unit-tests/t-reftable-reader.c b/t/unit-tests/t-reftable-reader.c
new file mode 100644
index 0000000000..eea86966c0
--- /dev/null
+++ b/t/unit-tests/t-reftable-reader.c
@@ -0,0 +1,96 @@
+#include "test-lib.h"
+#include "lib-reftable.h"
+#include "reftable/blocksource.h"
+#include "reftable/reader.h"
+
+static int t_reader_seek_once(void)
+{
+ struct reftable_ref_record records[] = {
+ {
+ .refname = (char *) "refs/heads/main",
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 42 },
+ },
+ };
+ struct reftable_block_source source = { 0 };
+ struct reftable_ref_record ref = { 0 };
+ struct reftable_iterator it = { 0 };
+ struct reftable_reader *reader;
+ struct strbuf buf = STRBUF_INIT;
+ int ret;
+
+ t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);
+ block_source_from_strbuf(&source, &buf);
+
+ ret = reftable_reader_new(&reader, &source, "name");
+ check(!ret);
+
+ reftable_reader_init_ref_iterator(reader, &it);
+ ret = reftable_iterator_seek_ref(&it, "");
+ check(!ret);
+ ret = reftable_iterator_next_ref(&it, &ref);
+ check(!ret);
+
+ ret = reftable_ref_record_equal(&ref, &records[0], GIT_SHA1_RAWSZ);
+ check_int(ret, ==, 1);
+
+ ret = reftable_iterator_next_ref(&it, &ref);
+ check_int(ret, ==, 1);
+
+ reftable_ref_record_release(&ref);
+ reftable_iterator_destroy(&it);
+ reftable_reader_decref(reader);
+ strbuf_release(&buf);
+ return 0;
+}
+
+static int t_reader_reseek(void)
+{
+ struct reftable_ref_record records[] = {
+ {
+ .refname = (char *) "refs/heads/main",
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 42 },
+ },
+ };
+ struct reftable_block_source source = { 0 };
+ struct reftable_ref_record ref = { 0 };
+ struct reftable_iterator it = { 0 };
+ struct reftable_reader *reader;
+ struct strbuf buf = STRBUF_INIT;
+ int ret;
+
+ t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL);
+ block_source_from_strbuf(&source, &buf);
+
+ ret = reftable_reader_new(&reader, &source, "name");
+ check(!ret);
+
+ reftable_reader_init_ref_iterator(reader, &it);
+
+ for (size_t i = 0; i < 5; i++) {
+ ret = reftable_iterator_seek_ref(&it, "");
+ check(!ret);
+ ret = reftable_iterator_next_ref(&it, &ref);
+ check(!ret);
+
+ ret = reftable_ref_record_equal(&ref, &records[0], GIT_SHA1_RAWSZ);
+ check_int(ret, ==, 1);
+
+ ret = reftable_iterator_next_ref(&it, &ref);
+ check_int(ret, ==, 1);
+ }
+
+ reftable_ref_record_release(&ref);
+ reftable_iterator_destroy(&it);
+ reftable_reader_decref(reader);
+ strbuf_release(&buf);
+ return 0;
+}
+
+int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
+{
+ TEST(t_reader_seek_once(), "reader can seek once");
+ TEST(t_reader_reseek(), "reader can reseek multiple times");
+ return test_done();
+}
diff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c
index 82bfaf3287..e1b235a5f1 100644
--- a/t/unit-tests/t-reftable-readwrite.c
+++ b/t/unit-tests/t-reftable-readwrite.c
@@ -7,6 +7,7 @@ https://developers.google.com/open-source/licenses/bsd
*/
#include "test-lib.h"
+#include "lib-reftable.h"
#include "reftable/basics.h"
#include "reftable/blocksource.h"
#include "reftable/reader.h"
@@ -15,22 +16,6 @@ https://developers.google.com/open-source/licenses/bsd
static const int update_index = 5;
-static void set_test_hash(uint8_t *p, int i)
-{
- memset(p, (uint8_t)i, hash_size(GIT_SHA1_FORMAT_ID));
-}
-
-static ssize_t strbuf_add_void(void *b, const void *data, size_t sz)
-{
- strbuf_add(b, data, sz);
- return sz;
-}
-
-static int noop_flush(void *arg UNUSED)
-{
- return 0;
-}
-
static void t_buffer(void)
{
struct strbuf buf = STRBUF_INIT;
@@ -62,61 +47,34 @@ static void write_table(char ***names, struct strbuf *buf, int N,
.block_size = block_size,
.hash_id = hash_id,
};
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, buf, &opts);
- struct reftable_ref_record ref = { 0 };
- int i = 0, n;
- struct reftable_log_record log = { 0 };
- const struct reftable_stats *stats = NULL;
+ struct reftable_ref_record *refs;
+ struct reftable_log_record *logs;
+ int i;
REFTABLE_CALLOC_ARRAY(*names, N + 1);
+ REFTABLE_CALLOC_ARRAY(refs, N);
+ REFTABLE_CALLOC_ARRAY(logs, N);
- reftable_writer_set_limits(w, update_index, update_index);
for (i = 0; i < N; i++) {
- char name[100];
- int n;
-
- snprintf(name, sizeof(name), "refs/heads/branch%02d", i);
-
- ref.refname = name;
- ref.update_index = update_index;
- ref.value_type = REFTABLE_REF_VAL1;
- set_test_hash(ref.value.val1, i);
- (*names)[i] = xstrdup(name);
-
- n = reftable_writer_add_ref(w, &ref);
- check_int(n, ==, 0);
+ refs[i].refname = (*names)[i] = xstrfmt("refs/heads/branch%02d", i);
+ refs[i].update_index = update_index;
+ refs[i].value_type = REFTABLE_REF_VAL1;
+ t_reftable_set_hash(refs[i].value.val1, i, GIT_SHA1_FORMAT_ID);
}
for (i = 0; i < N; i++) {
- char name[100];
- int n;
-
- snprintf(name, sizeof(name), "refs/heads/branch%02d", i);
-
- log.refname = name;
- log.update_index = update_index;
- log.value_type = REFTABLE_LOG_UPDATE;
- set_test_hash(log.value.update.new_hash, i);
- log.value.update.message = (char *) "message";
-
- n = reftable_writer_add_log(w, &log);
- check_int(n, ==, 0);
+ logs[i].refname = (*names)[i];
+ logs[i].update_index = update_index;
+ logs[i].value_type = REFTABLE_LOG_UPDATE;
+ t_reftable_set_hash(logs[i].value.update.new_hash, i,
+ GIT_SHA1_FORMAT_ID);
+ logs[i].value.update.message = (char *) "message";
}
- n = reftable_writer_close(w);
- check_int(n, ==, 0);
-
- stats = reftable_writer_stats(w);
- for (i = 0; i < stats->ref_stats.blocks; i++) {
- int off = i * opts.block_size;
- if (!off)
- off = header_size((hash_id == GIT_SHA256_FORMAT_ID) ? 2 : 1);
- check_char(buf->buf[off], ==, 'r');
- }
+ t_reftable_write_to_buf(buf, refs, N, logs, N, &opts);
- check_int(stats->log_stats.blocks, >, 0);
- reftable_writer_free(w);
+ free(refs);
+ free(logs);
}
static void t_log_buffer_size(void)
@@ -138,8 +96,7 @@ static void t_log_buffer_size(void)
.time = 0x5e430672,
.message = (char *) "commit: 9\n",
} } };
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
/* This tests buffer extension for log compression. Must use a random
hash, to ensure that the compressed part is larger than the original.
@@ -181,8 +138,7 @@ static void t_log_overflow(void)
},
},
};
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
memset(msg, 'x', sizeof(msg) - 1);
reftable_writer_set_limits(w, update_index, update_index);
@@ -208,8 +164,7 @@ static void t_log_write_read(void)
struct reftable_reader *reader;
struct reftable_block_source source = { 0 };
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
const struct reftable_stats *stats = NULL;
reftable_writer_set_limits(w, 0, N);
for (i = 0; i < N; i++) {
@@ -229,8 +184,10 @@ static void t_log_write_read(void)
log.refname = names[i];
log.update_index = i;
log.value_type = REFTABLE_LOG_UPDATE;
- set_test_hash(log.value.update.old_hash, i);
- set_test_hash(log.value.update.new_hash, i + 1);
+ t_reftable_set_hash(log.value.update.old_hash, i,
+ GIT_SHA1_FORMAT_ID);
+ t_reftable_set_hash(log.value.update.new_hash, i + 1,
+ GIT_SHA1_FORMAT_ID);
err = reftable_writer_add_log(w, &log);
check(!err);
@@ -297,8 +254,7 @@ static void t_log_zlib_corruption(void)
struct reftable_reader *reader;
struct reftable_block_source source = { 0 };
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
const struct reftable_stats *stats = NULL;
char message[100] = { 0 };
int err, i, n;
@@ -528,15 +484,12 @@ static void t_table_refs_for(int indexed)
int err;
struct reftable_reader *reader;
struct reftable_block_source source = { 0 };
-
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
-
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
struct reftable_iterator it = { 0 };
int j;
- set_test_hash(want_hash, 4);
+ t_reftable_set_hash(want_hash, 4, GIT_SHA1_FORMAT_ID);
for (i = 0; i < N; i++) {
uint8_t hash[GIT_SHA1_RAWSZ];
@@ -552,8 +505,10 @@ static void t_table_refs_for(int indexed)
ref.refname = name;
ref.value_type = REFTABLE_REF_VAL2;
- set_test_hash(ref.value.val2.value, i / 4);
- set_test_hash(ref.value.val2.target_value, 3 + i / 4);
+ t_reftable_set_hash(ref.value.val2.value, i / 4,
+ GIT_SHA1_FORMAT_ID);
+ t_reftable_set_hash(ref.value.val2.target_value, 3 + i / 4,
+ GIT_SHA1_FORMAT_ID);
/* 80 bytes / entry, so 3 entries per block. Yields 17
*/
@@ -618,8 +573,7 @@ static void t_write_empty_table(void)
{
struct reftable_write_options opts = { 0 };
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
struct reftable_block_source source = { 0 };
struct reftable_reader *rd = NULL;
struct reftable_ref_record rec = { 0 };
@@ -657,8 +611,7 @@ static void t_write_object_id_min_length(void)
.block_size = 75,
};
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
struct reftable_ref_record ref = {
.update_index = 1,
.value_type = REFTABLE_REF_VAL1,
@@ -692,8 +645,7 @@ static void t_write_object_id_length(void)
.block_size = 75,
};
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
struct reftable_ref_record ref = {
.update_index = 1,
.value_type = REFTABLE_REF_VAL1,
@@ -726,8 +678,7 @@ static void t_write_empty_key(void)
{
struct reftable_write_options opts = { 0 };
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
struct reftable_ref_record ref = {
.refname = (char *) "",
.update_index = 1,
@@ -749,8 +700,7 @@ static void t_write_key_order(void)
{
struct reftable_write_options opts = { 0 };
struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts);
struct reftable_ref_record refs[2] = {
{
.refname = (char *) "b",
@@ -798,7 +748,7 @@ static void t_write_multiple_indices(void)
struct reftable_reader *reader;
int err, i;
- writer = reftable_new_writer(&strbuf_add_void, &noop_flush, &writer_buf, &opts);
+ writer = t_reftable_strbuf_writer(&writer_buf, &opts);
reftable_writer_set_limits(writer, 1, 1);
for (i = 0; i < 100; i++) {
struct reftable_ref_record ref = {
@@ -876,7 +826,7 @@ static void t_write_multi_level_index(void)
struct reftable_reader *reader;
int err;
- writer = reftable_new_writer(&strbuf_add_void, &noop_flush, &writer_buf, &opts);
+ writer = t_reftable_strbuf_writer(&writer_buf, &opts);
reftable_writer_set_limits(writer, 1, 1);
for (size_t i = 0; i < 200; i++) {
struct reftable_ref_record ref = {
diff --git a/reftable/stack_test.c b/t/unit-tests/t-reftable-stack.c
index 89cb2be19f..31d563d992 100644
--- a/reftable/stack_test.c
+++ b/t/unit-tests/t-reftable-stack.c
@@ -6,20 +6,12 @@ license that can be found in the LICENSE file or at
https://developers.google.com/open-source/licenses/bsd
*/
-#include "stack.h"
-
-#include "system.h"
-
-#include "copy.h"
-#include "reftable-reader.h"
-#include "merged.h"
-#include "basics.h"
-#include "record.h"
-#include "test_framework.h"
-#include "reftable-tests.h"
-#include "reader.h"
-
-#include <sys/types.h>
+#include "test-lib.h"
+#include "lib-reftable.h"
+#include "reftable/merged.h"
+#include "reftable/reader.h"
+#include "reftable/reftable-error.h"
+#include "reftable/stack.h"
#include <dirent.h>
static void clear_dir(const char *dirname)
@@ -73,34 +65,34 @@ static char *get_tmp_template(int linenumber)
static char *get_tmp_dir(int linenumber)
{
char *dir = get_tmp_template(linenumber);
- EXPECT(mkdtemp(dir));
+ check(mkdtemp(dir) != NULL);
return dir;
}
-static void test_read_file(void)
+static void t_read_file(void)
{
char *fn = get_tmp_template(__LINE__);
- int fd = mkstemp(fn);
+ struct tempfile *tmp = mks_tempfile(fn);
+ int fd = get_tempfile_fd(tmp);
char out[1024] = "line1\n\nline2\nline3";
int n, err;
char **names = NULL;
const char *want[] = { "line1", "line2", "line3" };
- int i = 0;
- EXPECT(fd > 0);
+ check_int(fd, >, 0);
n = write_in_full(fd, out, strlen(out));
- EXPECT(n == strlen(out));
+ check_int(n, ==, strlen(out));
err = close(fd);
- EXPECT(err >= 0);
+ check_int(err, >=, 0);
err = read_lines(fn, &names);
- EXPECT_ERR(err);
+ check(!err);
- for (i = 0; names[i]; i++) {
- EXPECT(0 == strcmp(want[i], names[i]));
- }
+ for (size_t i = 0; names[i]; i++)
+ check_str(want[i], names[i]);
free_names(names);
(void) remove(fn);
+ delete_tempfile(&tmp);
}
static int write_test_ref(struct reftable_writer *wr, void *arg)
@@ -127,12 +119,12 @@ static void write_n_ref_tables(struct reftable_stack *st,
};
strbuf_reset(&buf);
- strbuf_addf(&buf, "refs/heads/branch-%04u", (unsigned) i);
+ strbuf_addf(&buf, "refs/heads/branch-%04"PRIuMAX, (uintmax_t)i);
ref.refname = buf.buf;
- set_test_hash(ref.value.val1, i);
+ t_reftable_set_hash(ref.value.val1, i, GIT_SHA1_FORMAT_ID);
err = reftable_stack_add(st, &write_test_ref, &ref);
- EXPECT_ERR(err);
+ check(!err);
}
st->opts.disable_auto_compact = disable_auto_compact;
@@ -152,7 +144,7 @@ static int write_test_log(struct reftable_writer *wr, void *arg)
return reftable_writer_add_log(wr, wla->log);
}
-static void test_reftable_stack_add_one(void)
+static void t_reftable_stack_add_one(void)
{
char *dir = get_tmp_dir(__LINE__);
struct strbuf scratch = STRBUF_INIT;
@@ -168,25 +160,25 @@ static void test_reftable_stack_add_one(void)
.value_type = REFTABLE_REF_SYMREF,
.value.symref = (char *) "master",
};
- struct reftable_ref_record dest = { NULL };
+ struct reftable_ref_record dest = { 0 };
struct stat stat_result = { 0 };
err = reftable_new_stack(&st, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
- err = reftable_stack_add(st, &write_test_ref, &ref);
- EXPECT_ERR(err);
+ err = reftable_stack_add(st, write_test_ref, &ref);
+ check(!err);
err = reftable_stack_read_ref(st, ref.refname, &dest);
- EXPECT_ERR(err);
- EXPECT(0 == strcmp("master", dest.value.symref));
- EXPECT(st->readers_len > 0);
+ check(!err);
+ check(reftable_ref_record_equal(&ref, &dest, GIT_SHA1_RAWSZ));
+ check_int(st->readers_len, >, 0);
#ifndef GIT_WINDOWS_NATIVE
strbuf_addstr(&scratch, dir);
strbuf_addstr(&scratch, "/tables.list");
err = stat(scratch.buf, &stat_result);
- EXPECT(!err);
- EXPECT((stat_result.st_mode & 0777) == opts.default_permissions);
+ check(!err);
+ check_int((stat_result.st_mode & 0777), ==, opts.default_permissions);
strbuf_reset(&scratch);
strbuf_addstr(&scratch, dir);
@@ -194,8 +186,8 @@ static void test_reftable_stack_add_one(void)
/* do not try at home; not an external API for reftable. */
strbuf_addstr(&scratch, st->readers[0]->name);
err = stat(scratch.buf, &stat_result);
- EXPECT(!err);
- EXPECT((stat_result.st_mode & 0777) == opts.default_permissions);
+ check(!err);
+ check_int((stat_result.st_mode & 0777), ==, opts.default_permissions);
#else
(void) stat_result;
#endif
@@ -207,7 +199,7 @@ static void test_reftable_stack_add_one(void)
umask(mask);
}
-static void test_reftable_stack_uptodate(void)
+static void t_reftable_stack_uptodate(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_stack *st1 = NULL;
@@ -233,28 +225,28 @@ static void test_reftable_stack_uptodate(void)
by creating two stacks for the same directory.
*/
err = reftable_new_stack(&st1, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
err = reftable_new_stack(&st2, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
- err = reftable_stack_add(st1, &write_test_ref, &ref1);
- EXPECT_ERR(err);
+ err = reftable_stack_add(st1, write_test_ref, &ref1);
+ check(!err);
- err = reftable_stack_add(st2, &write_test_ref, &ref2);
- EXPECT(err == REFTABLE_OUTDATED_ERROR);
+ err = reftable_stack_add(st2, write_test_ref, &ref2);
+ check_int(err, ==, REFTABLE_OUTDATED_ERROR);
err = reftable_stack_reload(st2);
- EXPECT_ERR(err);
+ check(!err);
- err = reftable_stack_add(st2, &write_test_ref, &ref2);
- EXPECT_ERR(err);
+ err = reftable_stack_add(st2, write_test_ref, &ref2);
+ check(!err);
reftable_stack_destroy(st1);
reftable_stack_destroy(st2);
clear_dir(dir);
}
-static void test_reftable_stack_transaction_api(void)
+static void t_reftable_stack_transaction_api(void)
{
char *dir = get_tmp_dir(__LINE__);
struct reftable_write_options opts = { 0 };
@@ -268,46 +260,109 @@ static void test_reftable_stack_transaction_api(void)
.value_type = REFTABLE_REF_SYMREF,
.value.symref = (char *) "master",
};
- struct reftable_ref_record dest = { NULL };
+ struct reftable_ref_record dest = { 0 };
err = reftable_new_stack(&st, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
reftable_addition_destroy(add);
- err = reftable_stack_new_addition(&add, st);
- EXPECT_ERR(err);
+ err = reftable_stack_new_addition(&add, st, 0);
+ check(!err);
- err = reftable_addition_add(add, &write_test_ref, &ref);
- EXPECT_ERR(err);
+ err = reftable_addition_add(add, write_test_ref, &ref);
+ check(!err);
err = reftable_addition_commit(add);
- EXPECT_ERR(err);
+ check(!err);
reftable_addition_destroy(add);
err = reftable_stack_read_ref(st, ref.refname, &dest);
- EXPECT_ERR(err);
- EXPECT(REFTABLE_REF_SYMREF == dest.value_type);
- EXPECT(0 == strcmp("master", dest.value.symref));
+ check(!err);
+ check_int(REFTABLE_REF_SYMREF, ==, dest.value_type);
+ check(reftable_ref_record_equal(&ref, &dest, GIT_SHA1_RAWSZ));
reftable_ref_record_release(&dest);
reftable_stack_destroy(st);
clear_dir(dir);
}
-static void test_reftable_stack_transaction_api_performs_auto_compaction(void)
+static void t_reftable_stack_transaction_with_reload(void)
+{
+ char *dir = get_tmp_dir(__LINE__);
+ struct reftable_stack *st1 = NULL, *st2 = NULL;
+ int err;
+ struct reftable_addition *add = NULL;
+ struct reftable_ref_record refs[2] = {
+ {
+ .refname = (char *) "refs/heads/a",
+ .update_index = 1,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { '1' },
+ },
+ {
+ .refname = (char *) "refs/heads/b",
+ .update_index = 2,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { '1' },
+ },
+ };
+ struct reftable_ref_record ref = { 0 };
+
+ err = reftable_new_stack(&st1, dir, NULL);
+ check(!err);
+ err = reftable_new_stack(&st2, dir, NULL);
+ check(!err);
+
+ err = reftable_stack_new_addition(&add, st1, 0);
+ check(!err);
+ err = reftable_addition_add(add, write_test_ref, &refs[0]);
+ check(!err);
+ err = reftable_addition_commit(add);
+ check(!err);
+ reftable_addition_destroy(add);
+
+ /*
+ * The second stack is now outdated, which we should notice. We do not
+ * create the addition and lock the stack by default, but allow the
+ * reload to happen when REFTABLE_STACK_NEW_ADDITION_RELOAD is set.
+ */
+ err = reftable_stack_new_addition(&add, st2, 0);
+ check_int(err, ==, REFTABLE_OUTDATED_ERROR);
+ err = reftable_stack_new_addition(&add, st2, REFTABLE_STACK_NEW_ADDITION_RELOAD);
+ check(!err);
+ err = reftable_addition_add(add, write_test_ref, &refs[1]);
+ check(!err);
+ err = reftable_addition_commit(add);
+ check(!err);
+ reftable_addition_destroy(add);
+
+ for (size_t i = 0; i < ARRAY_SIZE(refs); i++) {
+ err = reftable_stack_read_ref(st2, refs[i].refname, &ref);
+ check(!err);
+ check(reftable_ref_record_equal(&refs[i], &ref, GIT_SHA1_RAWSZ));
+ }
+
+ reftable_ref_record_release(&ref);
+ reftable_stack_destroy(st1);
+ reftable_stack_destroy(st2);
+ clear_dir(dir);
+}
+
+static void t_reftable_stack_transaction_api_performs_auto_compaction(void)
{
char *dir = get_tmp_dir(__LINE__);
struct reftable_write_options opts = {0};
struct reftable_addition *add = NULL;
struct reftable_stack *st = NULL;
- int i, n = 20, err;
+ size_t n = 20;
+ int err;
err = reftable_new_stack(&st, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
- for (i = 0; i <= n; i++) {
+ for (size_t i = 0; i <= n; i++) {
struct reftable_ref_record ref = {
.update_index = reftable_stack_next_update_index(st),
.value_type = REFTABLE_REF_SYMREF,
@@ -315,7 +370,7 @@ static void test_reftable_stack_transaction_api_performs_auto_compaction(void)
};
char name[100];
- snprintf(name, sizeof(name), "branch%04d", i);
+ snprintf(name, sizeof(name), "branch%04"PRIuMAX, (uintmax_t)i);
ref.refname = name;
/*
@@ -325,14 +380,14 @@ static void test_reftable_stack_transaction_api_performs_auto_compaction(void)
*/
st->opts.disable_auto_compact = i != n;
- err = reftable_stack_new_addition(&add, st);
- EXPECT_ERR(err);
+ err = reftable_stack_new_addition(&add, st, 0);
+ check(!err);
- err = reftable_addition_add(add, &write_test_ref, &ref);
- EXPECT_ERR(err);
+ err = reftable_addition_add(add, write_test_ref, &ref);
+ check(!err);
err = reftable_addition_commit(add);
- EXPECT_ERR(err);
+ check(!err);
reftable_addition_destroy(add);
@@ -342,16 +397,16 @@ static void test_reftable_stack_transaction_api_performs_auto_compaction(void)
* all tables in the stack.
*/
if (i != n)
- EXPECT(st->merged->readers_len == i + 1);
+ check_int(st->merged->readers_len, ==, i + 1);
else
- EXPECT(st->merged->readers_len == 1);
+ check_int(st->merged->readers_len, ==, 1);
}
reftable_stack_destroy(st);
clear_dir(dir);
}
-static void test_reftable_stack_auto_compaction_fails_gracefully(void)
+static void t_reftable_stack_auto_compaction_fails_gracefully(void)
{
struct reftable_ref_record ref = {
.refname = (char *) "refs/heads/master",
@@ -359,20 +414,20 @@ static void test_reftable_stack_auto_compaction_fails_gracefully(void)
.value_type = REFTABLE_REF_VAL1,
.value.val1 = {0x01},
};
- struct reftable_write_options opts = {0};
+ struct reftable_write_options opts = { 0 };
struct reftable_stack *st;
struct strbuf table_path = STRBUF_INIT;
char *dir = get_tmp_dir(__LINE__);
int err;
err = reftable_new_stack(&st, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
err = reftable_stack_add(st, write_test_ref, &ref);
- EXPECT_ERR(err);
- EXPECT(st->merged->readers_len == 1);
- EXPECT(st->stats.attempts == 0);
- EXPECT(st->stats.failures == 0);
+ check(!err);
+ check_int(st->merged->readers_len, ==, 1);
+ check_int(st->stats.attempts, ==, 0);
+ check_int(st->stats.failures, ==, 0);
/*
* Lock the newly written table such that it cannot be compacted.
@@ -384,10 +439,10 @@ static void test_reftable_stack_auto_compaction_fails_gracefully(void)
ref.update_index = 2;
err = reftable_stack_add(st, write_test_ref, &ref);
- EXPECT_ERR(err);
- EXPECT(st->merged->readers_len == 2);
- EXPECT(st->stats.attempts == 1);
- EXPECT(st->stats.failures == 1);
+ check(!err);
+ check_int(st->merged->readers_len, ==, 2);
+ check_int(st->stats.attempts, ==, 1);
+ check_int(st->stats.failures, ==, 1);
reftable_stack_destroy(st);
strbuf_release(&table_path);
@@ -399,7 +454,7 @@ static int write_error(struct reftable_writer *wr UNUSED, void *arg)
return *((int *)arg);
}
-static void test_reftable_stack_update_index_check(void)
+static void t_reftable_stack_update_index_check(void)
{
char *dir = get_tmp_dir(__LINE__);
struct reftable_write_options opts = { 0 };
@@ -419,18 +474,18 @@ static void test_reftable_stack_update_index_check(void)
};
err = reftable_new_stack(&st, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
- err = reftable_stack_add(st, &write_test_ref, &ref1);
- EXPECT_ERR(err);
+ err = reftable_stack_add(st, write_test_ref, &ref1);
+ check(!err);
- err = reftable_stack_add(st, &write_test_ref, &ref2);
- EXPECT(err == REFTABLE_API_ERROR);
+ err = reftable_stack_add(st, write_test_ref, &ref2);
+ check_int(err, ==, REFTABLE_API_ERROR);
reftable_stack_destroy(st);
clear_dir(dir);
}
-static void test_reftable_stack_lock_failure(void)
+static void t_reftable_stack_lock_failure(void)
{
char *dir = get_tmp_dir(__LINE__);
struct reftable_write_options opts = { 0 };
@@ -438,19 +493,18 @@ static void test_reftable_stack_lock_failure(void)
int err, i;
err = reftable_new_stack(&st, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
for (i = -1; i != REFTABLE_EMPTY_TABLE_ERROR; i--) {
- err = reftable_stack_add(st, &write_error, &i);
- EXPECT(err == i);
+ err = reftable_stack_add(st, write_error, &i);
+ check_int(err, ==, i);
}
reftable_stack_destroy(st);
clear_dir(dir);
}
-static void test_reftable_stack_add(void)
+static void t_reftable_stack_add(void)
{
- int i = 0;
int err = 0;
struct reftable_write_options opts = {
.exact_log_message = 1,
@@ -459,33 +513,33 @@ static void test_reftable_stack_add(void)
};
struct reftable_stack *st = NULL;
char *dir = get_tmp_dir(__LINE__);
- struct reftable_ref_record refs[2] = { { NULL } };
- struct reftable_log_record logs[2] = { { NULL } };
+ struct reftable_ref_record refs[2] = { 0 };
+ struct reftable_log_record logs[2] = { 0 };
struct strbuf path = STRBUF_INIT;
struct stat stat_result;
- int N = ARRAY_SIZE(refs);
+ size_t i, N = ARRAY_SIZE(refs);
err = reftable_new_stack(&st, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
for (i = 0; i < N; i++) {
char buf[256];
- snprintf(buf, sizeof(buf), "branch%02d", i);
+ snprintf(buf, sizeof(buf), "branch%02"PRIuMAX, (uintmax_t)i);
refs[i].refname = xstrdup(buf);
refs[i].update_index = i + 1;
refs[i].value_type = REFTABLE_REF_VAL1;
- set_test_hash(refs[i].value.val1, i);
+ t_reftable_set_hash(refs[i].value.val1, i, GIT_SHA1_FORMAT_ID);
logs[i].refname = xstrdup(buf);
logs[i].update_index = N + i + 1;
logs[i].value_type = REFTABLE_LOG_UPDATE;
logs[i].value.update.email = xstrdup("identity@invalid");
- set_test_hash(logs[i].value.update.new_hash, i);
+ t_reftable_set_hash(logs[i].value.update.new_hash, i, GIT_SHA1_FORMAT_ID);
}
for (i = 0; i < N; i++) {
- int err = reftable_stack_add(st, &write_test_ref, &refs[i]);
- EXPECT_ERR(err);
+ int err = reftable_stack_add(st, write_test_ref, &refs[i]);
+ check(!err);
}
for (i = 0; i < N; i++) {
@@ -493,28 +547,28 @@ static void test_reftable_stack_add(void)
.log = &logs[i],
.update_index = reftable_stack_next_update_index(st),
};
- int err = reftable_stack_add(st, &write_test_log, &arg);
- EXPECT_ERR(err);
+ int err = reftable_stack_add(st, write_test_log, &arg);
+ check(!err);
}
err = reftable_stack_compact_all(st, NULL);
- EXPECT_ERR(err);
+ check(!err);
for (i = 0; i < N; i++) {
- struct reftable_ref_record dest = { NULL };
+ struct reftable_ref_record dest = { 0 };
int err = reftable_stack_read_ref(st, refs[i].refname, &dest);
- EXPECT_ERR(err);
- EXPECT(reftable_ref_record_equal(&dest, refs + i,
+ check(!err);
+ check(reftable_ref_record_equal(&dest, refs + i,
GIT_SHA1_RAWSZ));
reftable_ref_record_release(&dest);
}
for (i = 0; i < N; i++) {
- struct reftable_log_record dest = { NULL };
+ struct reftable_log_record dest = { 0 };
int err = reftable_stack_read_log(st, refs[i].refname, &dest);
- EXPECT_ERR(err);
- EXPECT(reftable_log_record_equal(&dest, logs + i,
+ check(!err);
+ check(reftable_log_record_equal(&dest, logs + i,
GIT_SHA1_RAWSZ));
reftable_log_record_release(&dest);
}
@@ -523,8 +577,8 @@ static void test_reftable_stack_add(void)
strbuf_addstr(&path, dir);
strbuf_addstr(&path, "/tables.list");
err = stat(path.buf, &stat_result);
- EXPECT(!err);
- EXPECT((stat_result.st_mode & 0777) == opts.default_permissions);
+ check(!err);
+ check_int((stat_result.st_mode & 0777), ==, opts.default_permissions);
strbuf_reset(&path);
strbuf_addstr(&path, dir);
@@ -532,8 +586,8 @@ static void test_reftable_stack_add(void)
/* do not try at home; not an external API for reftable. */
strbuf_addstr(&path, st->readers[0]->name);
err = stat(path.buf, &stat_result);
- EXPECT(!err);
- EXPECT((stat_result.st_mode & 0777) == opts.default_permissions);
+ check(!err);
+ check_int((stat_result.st_mode & 0777), ==, opts.default_permissions);
#else
(void) stat_result;
#endif
@@ -548,7 +602,89 @@ static void test_reftable_stack_add(void)
clear_dir(dir);
}
-static void test_reftable_stack_log_normalize(void)
+static void t_reftable_stack_iterator(void)
+{
+ struct reftable_write_options opts = { 0 };
+ struct reftable_stack *st = NULL;
+ char *dir = get_tmp_dir(__LINE__);
+ struct reftable_ref_record refs[10] = { 0 };
+ struct reftable_log_record logs[10] = { 0 };
+ struct reftable_iterator it = { 0 };
+ size_t N = ARRAY_SIZE(refs), i;
+ int err;
+
+ err = reftable_new_stack(&st, dir, &opts);
+ check(!err);
+
+ for (i = 0; i < N; i++) {
+ refs[i].refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i);
+ refs[i].update_index = i + 1;
+ refs[i].value_type = REFTABLE_REF_VAL1;
+ t_reftable_set_hash(refs[i].value.val1, i, GIT_SHA1_FORMAT_ID);
+
+ logs[i].refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i);
+ logs[i].update_index = i + 1;
+ logs[i].value_type = REFTABLE_LOG_UPDATE;
+ logs[i].value.update.email = xstrdup("johndoe@invalid");
+ logs[i].value.update.message = xstrdup("commit\n");
+ t_reftable_set_hash(logs[i].value.update.new_hash, i, GIT_SHA1_FORMAT_ID);
+ }
+
+ for (i = 0; i < N; i++) {
+ err = reftable_stack_add(st, write_test_ref, &refs[i]);
+ check(!err);
+ }
+
+ for (i = 0; i < N; i++) {
+ struct write_log_arg arg = {
+ .log = &logs[i],
+ .update_index = reftable_stack_next_update_index(st),
+ };
+
+ err = reftable_stack_add(st, write_test_log, &arg);
+ check(!err);
+ }
+
+ reftable_stack_init_ref_iterator(st, &it);
+ reftable_iterator_seek_ref(&it, refs[0].refname);
+ for (i = 0; ; i++) {
+ struct reftable_ref_record ref = { 0 };
+
+ err = reftable_iterator_next_ref(&it, &ref);
+ if (err > 0)
+ break;
+ check(!err);
+ check(reftable_ref_record_equal(&ref, &refs[i], GIT_SHA1_RAWSZ));
+ reftable_ref_record_release(&ref);
+ }
+ check_int(i, ==, N);
+
+ reftable_iterator_destroy(&it);
+
+ reftable_stack_init_log_iterator(st, &it);
+ reftable_iterator_seek_log(&it, logs[0].refname);
+ for (i = 0; ; i++) {
+ struct reftable_log_record log = { 0 };
+
+ err = reftable_iterator_next_log(&it, &log);
+ if (err > 0)
+ break;
+ check(!err);
+ check(reftable_log_record_equal(&log, &logs[i], GIT_SHA1_RAWSZ));
+ reftable_log_record_release(&log);
+ }
+ check_int(i, ==, N);
+
+ reftable_stack_destroy(st);
+ reftable_iterator_destroy(&it);
+ for (i = 0; i < N; i++) {
+ reftable_ref_record_release(&refs[i]);
+ reftable_log_record_release(&logs[i]);
+ }
+ clear_dir(dir);
+}
+
+static void t_reftable_stack_log_normalize(void)
{
int err = 0;
struct reftable_write_options opts = {
@@ -576,27 +712,27 @@ static void test_reftable_stack_log_normalize(void)
};
err = reftable_new_stack(&st, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
input.value.update.message = (char *) "one\ntwo";
- err = reftable_stack_add(st, &write_test_log, &arg);
- EXPECT(err == REFTABLE_API_ERROR);
+ err = reftable_stack_add(st, write_test_log, &arg);
+ check_int(err, ==, REFTABLE_API_ERROR);
input.value.update.message = (char *) "one";
- err = reftable_stack_add(st, &write_test_log, &arg);
- EXPECT_ERR(err);
+ err = reftable_stack_add(st, write_test_log, &arg);
+ check(!err);
err = reftable_stack_read_log(st, input.refname, &dest);
- EXPECT_ERR(err);
- EXPECT(0 == strcmp(dest.value.update.message, "one\n"));
+ check(!err);
+ check_str(dest.value.update.message, "one\n");
input.value.update.message = (char *) "two\n";
arg.update_index = 2;
- err = reftable_stack_add(st, &write_test_log, &arg);
- EXPECT_ERR(err);
+ err = reftable_stack_add(st, write_test_log, &arg);
+ check(!err);
err = reftable_stack_read_log(st, input.refname, &dest);
- EXPECT_ERR(err);
- EXPECT(0 == strcmp(dest.value.update.message, "two\n"));
+ check(!err);
+ check_str(dest.value.update.message, "two\n");
/* cleanup */
reftable_stack_destroy(st);
@@ -604,21 +740,20 @@ static void test_reftable_stack_log_normalize(void)
clear_dir(dir);
}
-static void test_reftable_stack_tombstone(void)
+static void t_reftable_stack_tombstone(void)
{
- int i = 0;
char *dir = get_tmp_dir(__LINE__);
struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
int err;
- struct reftable_ref_record refs[2] = { { NULL } };
- struct reftable_log_record logs[2] = { { NULL } };
- int N = ARRAY_SIZE(refs);
- struct reftable_ref_record dest = { NULL };
- struct reftable_log_record log_dest = { NULL };
+ struct reftable_ref_record refs[2] = { 0 };
+ struct reftable_log_record logs[2] = { 0 };
+ size_t i, N = ARRAY_SIZE(refs);
+ struct reftable_ref_record dest = { 0 };
+ struct reftable_log_record log_dest = { 0 };
err = reftable_new_stack(&st, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
/* even entries add the refs, odd entries delete them. */
for (i = 0; i < N; i++) {
@@ -627,7 +762,8 @@ static void test_reftable_stack_tombstone(void)
refs[i].update_index = i + 1;
if (i % 2 == 0) {
refs[i].value_type = REFTABLE_REF_VAL1;
- set_test_hash(refs[i].value.val1, i);
+ t_reftable_set_hash(refs[i].value.val1, i,
+ GIT_SHA1_FORMAT_ID);
}
logs[i].refname = xstrdup(buf);
@@ -635,14 +771,15 @@ static void test_reftable_stack_tombstone(void)
logs[i].update_index = 42;
if (i % 2 == 0) {
logs[i].value_type = REFTABLE_LOG_UPDATE;
- set_test_hash(logs[i].value.update.new_hash, i);
+ t_reftable_set_hash(logs[i].value.update.new_hash, i,
+ GIT_SHA1_FORMAT_ID);
logs[i].value.update.email =
xstrdup("identity@invalid");
}
}
for (i = 0; i < N; i++) {
- int err = reftable_stack_add(st, &write_test_ref, &refs[i]);
- EXPECT_ERR(err);
+ int err = reftable_stack_add(st, write_test_ref, &refs[i]);
+ check(!err);
}
for (i = 0; i < N; i++) {
@@ -650,26 +787,26 @@ static void test_reftable_stack_tombstone(void)
.log = &logs[i],
.update_index = reftable_stack_next_update_index(st),
};
- int err = reftable_stack_add(st, &write_test_log, &arg);
- EXPECT_ERR(err);
+ int err = reftable_stack_add(st, write_test_log, &arg);
+ check(!err);
}
err = reftable_stack_read_ref(st, "branch", &dest);
- EXPECT(err == 1);
+ check_int(err, ==, 1);
reftable_ref_record_release(&dest);
err = reftable_stack_read_log(st, "branch", &log_dest);
- EXPECT(err == 1);
+ check_int(err, ==, 1);
reftable_log_record_release(&log_dest);
err = reftable_stack_compact_all(st, NULL);
- EXPECT_ERR(err);
+ check(!err);
err = reftable_stack_read_ref(st, "branch", &dest);
- EXPECT(err == 1);
+ check_int(err, ==, 1);
err = reftable_stack_read_log(st, "branch", &log_dest);
- EXPECT(err == 1);
+ check_int(err, ==, 1);
reftable_ref_record_release(&dest);
reftable_log_record_release(&log_dest);
@@ -682,7 +819,7 @@ static void test_reftable_stack_tombstone(void)
clear_dir(dir);
}
-static void test_reftable_stack_hash_id(void)
+static void t_reftable_stack_hash_id(void)
{
char *dir = get_tmp_dir(__LINE__);
struct reftable_write_options opts = { 0 };
@@ -699,76 +836,76 @@ static void test_reftable_stack_hash_id(void)
struct reftable_stack *st32 = NULL;
struct reftable_write_options opts_default = { 0 };
struct reftable_stack *st_default = NULL;
- struct reftable_ref_record dest = { NULL };
+ struct reftable_ref_record dest = { 0 };
err = reftable_new_stack(&st, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
- err = reftable_stack_add(st, &write_test_ref, &ref);
- EXPECT_ERR(err);
+ err = reftable_stack_add(st, write_test_ref, &ref);
+ check(!err);
/* can't read it with the wrong hash ID. */
err = reftable_new_stack(&st32, dir, &opts32);
- EXPECT(err == REFTABLE_FORMAT_ERROR);
+ check_int(err, ==, REFTABLE_FORMAT_ERROR);
/* check that we can read it back with default opts too. */
err = reftable_new_stack(&st_default, dir, &opts_default);
- EXPECT_ERR(err);
+ check(!err);
err = reftable_stack_read_ref(st_default, "master", &dest);
- EXPECT_ERR(err);
+ check(!err);
- EXPECT(reftable_ref_record_equal(&ref, &dest, GIT_SHA1_RAWSZ));
+ check(reftable_ref_record_equal(&ref, &dest, GIT_SHA1_RAWSZ));
reftable_ref_record_release(&dest);
reftable_stack_destroy(st);
reftable_stack_destroy(st_default);
clear_dir(dir);
}
-static void test_suggest_compaction_segment(void)
+static void t_suggest_compaction_segment(void)
{
uint64_t sizes[] = { 512, 64, 17, 16, 9, 9, 9, 16, 2, 16 };
struct segment min =
suggest_compaction_segment(sizes, ARRAY_SIZE(sizes), 2);
- EXPECT(min.start == 1);
- EXPECT(min.end == 10);
+ check_int(min.start, ==, 1);
+ check_int(min.end, ==, 10);
}
-static void test_suggest_compaction_segment_nothing(void)
+static void t_suggest_compaction_segment_nothing(void)
{
uint64_t sizes[] = { 64, 32, 16, 8, 4, 2 };
struct segment result =
suggest_compaction_segment(sizes, ARRAY_SIZE(sizes), 2);
- EXPECT(result.start == result.end);
+ check_int(result.start, ==, result.end);
}
-static void test_reflog_expire(void)
+static void t_reflog_expire(void)
{
char *dir = get_tmp_dir(__LINE__);
struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
- struct reftable_log_record logs[20] = { { NULL } };
- int N = ARRAY_SIZE(logs) - 1;
- int i = 0;
+ struct reftable_log_record logs[20] = { 0 };
+ size_t i, N = ARRAY_SIZE(logs) - 1;
int err;
struct reftable_log_expiry_config expiry = {
.time = 10,
};
- struct reftable_log_record log = { NULL };
+ struct reftable_log_record log = { 0 };
err = reftable_new_stack(&st, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
for (i = 1; i <= N; i++) {
char buf[256];
- snprintf(buf, sizeof(buf), "branch%02d", i);
+ snprintf(buf, sizeof(buf), "branch%02"PRIuMAX, (uintmax_t)i);
logs[i].refname = xstrdup(buf);
logs[i].update_index = i;
logs[i].value_type = REFTABLE_LOG_UPDATE;
logs[i].value.update.time = i;
logs[i].value.update.email = xstrdup("identity@invalid");
- set_test_hash(logs[i].value.update.new_hash, i);
+ t_reftable_set_hash(logs[i].value.update.new_hash, i,
+ GIT_SHA1_FORMAT_ID);
}
for (i = 1; i <= N; i++) {
@@ -776,37 +913,36 @@ static void test_reflog_expire(void)
.log = &logs[i],
.update_index = reftable_stack_next_update_index(st),
};
- int err = reftable_stack_add(st, &write_test_log, &arg);
- EXPECT_ERR(err);
+ int err = reftable_stack_add(st, write_test_log, &arg);
+ check(!err);
}
err = reftable_stack_compact_all(st, NULL);
- EXPECT_ERR(err);
+ check(!err);
err = reftable_stack_compact_all(st, &expiry);
- EXPECT_ERR(err);
+ check(!err);
err = reftable_stack_read_log(st, logs[9].refname, &log);
- EXPECT(err == 1);
+ check_int(err, ==, 1);
err = reftable_stack_read_log(st, logs[11].refname, &log);
- EXPECT_ERR(err);
+ check(!err);
expiry.min_update_index = 15;
err = reftable_stack_compact_all(st, &expiry);
- EXPECT_ERR(err);
+ check(!err);
err = reftable_stack_read_log(st, logs[14].refname, &log);
- EXPECT(err == 1);
+ check_int(err, ==, 1);
err = reftable_stack_read_log(st, logs[16].refname, &log);
- EXPECT_ERR(err);
+ check(!err);
/* cleanup */
reftable_stack_destroy(st);
- for (i = 0; i <= N; i++) {
+ for (i = 0; i <= N; i++)
reftable_log_record_release(&logs[i]);
- }
clear_dir(dir);
reftable_log_record_release(&log);
}
@@ -817,7 +953,7 @@ static int write_nothing(struct reftable_writer *wr, void *arg UNUSED)
return 0;
}
-static void test_empty_add(void)
+static void t_empty_add(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
@@ -826,40 +962,40 @@ static void test_empty_add(void)
struct reftable_stack *st2 = NULL;
err = reftable_new_stack(&st, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
- err = reftable_stack_add(st, &write_nothing, NULL);
- EXPECT_ERR(err);
+ err = reftable_stack_add(st, write_nothing, NULL);
+ check(!err);
err = reftable_new_stack(&st2, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
clear_dir(dir);
reftable_stack_destroy(st);
reftable_stack_destroy(st2);
}
-static int fastlog2(uint64_t sz)
+static int fastlogN(uint64_t sz, uint64_t N)
{
int l = 0;
if (sz == 0)
return 0;
- for (; sz; sz /= 2)
+ for (; sz; sz /= N)
l++;
return l - 1;
}
-static void test_reftable_stack_auto_compaction(void)
+static void t_reftable_stack_auto_compaction(void)
{
struct reftable_write_options opts = {
.disable_auto_compact = 1,
};
struct reftable_stack *st = NULL;
char *dir = get_tmp_dir(__LINE__);
- int err, i;
- int N = 100;
+ int err;
+ size_t i, N = 100;
err = reftable_new_stack(&st, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
for (i = 0; i < N; i++) {
char name[100];
@@ -869,24 +1005,56 @@ static void test_reftable_stack_auto_compaction(void)
.value_type = REFTABLE_REF_SYMREF,
.value.symref = (char *) "master",
};
- snprintf(name, sizeof(name), "branch%04d", i);
+ snprintf(name, sizeof(name), "branch%04"PRIuMAX, (uintmax_t)i);
- err = reftable_stack_add(st, &write_test_ref, &ref);
- EXPECT_ERR(err);
+ err = reftable_stack_add(st, write_test_ref, &ref);
+ check(!err);
err = reftable_stack_auto_compact(st);
- EXPECT_ERR(err);
- EXPECT(i < 3 || st->merged->readers_len < 2 * fastlog2(i));
+ check(!err);
+ check(i < 2 || st->merged->readers_len < 2 * fastlogN(i, 2));
}
- EXPECT(reftable_stack_compaction_stats(st)->entries_written <
- (uint64_t)(N * fastlog2(N)));
+ check_int(reftable_stack_compaction_stats(st)->entries_written, <,
+ (uint64_t)(N * fastlogN(N, 2)));
reftable_stack_destroy(st);
clear_dir(dir);
}
-static void test_reftable_stack_auto_compaction_with_locked_tables(void)
+static void t_reftable_stack_auto_compaction_factor(void)
+{
+ struct reftable_write_options opts = {
+ .auto_compaction_factor = 5,
+ };
+ struct reftable_stack *st = NULL;
+ char *dir = get_tmp_dir(__LINE__);
+ int err;
+ size_t N = 100;
+
+ err = reftable_new_stack(&st, dir, &opts);
+ check(!err);
+
+ for (size_t i = 0; i < N; i++) {
+ char name[20];
+ struct reftable_ref_record ref = {
+ .refname = name,
+ .update_index = reftable_stack_next_update_index(st),
+ .value_type = REFTABLE_REF_VAL1,
+ };
+ xsnprintf(name, sizeof(name), "branch%04"PRIuMAX, (uintmax_t)i);
+
+ err = reftable_stack_add(st, &write_test_ref, &ref);
+ check(!err);
+
+ check(i < 5 || st->merged->readers_len < 5 * fastlogN(i, 5));
+ }
+
+ reftable_stack_destroy(st);
+ clear_dir(dir);
+}
+
+static void t_reftable_stack_auto_compaction_with_locked_tables(void)
{
struct reftable_write_options opts = {
.disable_auto_compact = 1,
@@ -897,10 +1065,10 @@ static void test_reftable_stack_auto_compaction_with_locked_tables(void)
int err;
err = reftable_new_stack(&st, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
write_n_ref_tables(st, 5);
- EXPECT(st->merged->readers_len == 5);
+ check_int(st->merged->readers_len, ==, 5);
/*
* Given that all tables we have written should be roughly the same
@@ -918,25 +1086,26 @@ static void test_reftable_stack_auto_compaction_with_locked_tables(void)
* only compact the newest two tables.
*/
err = reftable_stack_auto_compact(st);
- EXPECT_ERR(err);
- EXPECT(st->stats.failures == 0);
- EXPECT(st->merged->readers_len == 4);
+ check(!err);
+ check_int(st->stats.failures, ==, 0);
+ check_int(st->merged->readers_len, ==, 4);
reftable_stack_destroy(st);
strbuf_release(&buf);
clear_dir(dir);
}
-static void test_reftable_stack_add_performs_auto_compaction(void)
+static void t_reftable_stack_add_performs_auto_compaction(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
struct strbuf refname = STRBUF_INIT;
char *dir = get_tmp_dir(__LINE__);
- int err, i, n = 20;
+ int err;
+ size_t i, n = 20;
err = reftable_new_stack(&st, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
for (i = 0; i <= n; i++) {
struct reftable_ref_record ref = {
@@ -953,11 +1122,11 @@ static void test_reftable_stack_add_performs_auto_compaction(void)
st->opts.disable_auto_compact = i != n;
strbuf_reset(&refname);
- strbuf_addf(&refname, "branch-%04d", i);
+ strbuf_addf(&refname, "branch-%04"PRIuMAX, (uintmax_t)i);
ref.refname = refname.buf;
- err = reftable_stack_add(st, &write_test_ref, &ref);
- EXPECT_ERR(err);
+ err = reftable_stack_add(st, write_test_ref, &ref);
+ check(!err);
/*
* The stack length should grow continuously for all runs where
@@ -965,9 +1134,9 @@ static void test_reftable_stack_add_performs_auto_compaction(void)
* all tables in the stack.
*/
if (i != n)
- EXPECT(st->merged->readers_len == i + 1);
+ check_int(st->merged->readers_len, ==, i + 1);
else
- EXPECT(st->merged->readers_len == 1);
+ check_int(st->merged->readers_len, ==, 1);
}
reftable_stack_destroy(st);
@@ -975,7 +1144,7 @@ static void test_reftable_stack_add_performs_auto_compaction(void)
clear_dir(dir);
}
-static void test_reftable_stack_compaction_with_locked_tables(void)
+static void t_reftable_stack_compaction_with_locked_tables(void)
{
struct reftable_write_options opts = {
.disable_auto_compact = 1,
@@ -986,10 +1155,10 @@ static void test_reftable_stack_compaction_with_locked_tables(void)
int err;
err = reftable_new_stack(&st, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
write_n_ref_tables(st, 3);
- EXPECT(st->merged->readers_len == 3);
+ check_int(st->merged->readers_len, ==, 3);
/* Lock one of the tables that we're about to compact. */
strbuf_reset(&buf);
@@ -1001,16 +1170,16 @@ static void test_reftable_stack_compaction_with_locked_tables(void)
* compact all tables.
*/
err = reftable_stack_compact_all(st, NULL);
- EXPECT(err == REFTABLE_LOCK_ERROR);
- EXPECT(st->stats.failures == 1);
- EXPECT(st->merged->readers_len == 3);
+ check_int(err, ==, REFTABLE_LOCK_ERROR);
+ check_int(st->stats.failures, ==, 1);
+ check_int(st->merged->readers_len, ==, 3);
reftable_stack_destroy(st);
strbuf_release(&buf);
clear_dir(dir);
}
-static void test_reftable_stack_compaction_concurrent(void)
+static void t_reftable_stack_compaction_concurrent(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_stack *st1 = NULL, *st2 = NULL;
@@ -1018,19 +1187,19 @@ static void test_reftable_stack_compaction_concurrent(void)
int err;
err = reftable_new_stack(&st1, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
write_n_ref_tables(st1, 3);
err = reftable_new_stack(&st2, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
err = reftable_stack_compact_all(st1, NULL);
- EXPECT_ERR(err);
+ check(!err);
reftable_stack_destroy(st1);
reftable_stack_destroy(st2);
- EXPECT(count_dir_entries(dir) == 2);
+ check_int(count_dir_entries(dir), ==, 2);
clear_dir(dir);
}
@@ -1043,7 +1212,7 @@ static void unclean_stack_close(struct reftable_stack *st)
FREE_AND_NULL(st->readers);
}
-static void test_reftable_stack_compaction_concurrent_clean(void)
+static void t_reftable_stack_compaction_concurrent_clean(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_stack *st1 = NULL, *st2 = NULL, *st3 = NULL;
@@ -1051,24 +1220,24 @@ static void test_reftable_stack_compaction_concurrent_clean(void)
int err;
err = reftable_new_stack(&st1, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
write_n_ref_tables(st1, 3);
err = reftable_new_stack(&st2, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
err = reftable_stack_compact_all(st1, NULL);
- EXPECT_ERR(err);
+ check(!err);
unclean_stack_close(st1);
unclean_stack_close(st2);
err = reftable_new_stack(&st3, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
err = reftable_stack_clean(st3);
- EXPECT_ERR(err);
- EXPECT(count_dir_entries(dir) == 2);
+ check(!err);
+ check_int(count_dir_entries(dir), ==, 2);
reftable_stack_destroy(st1);
reftable_stack_destroy(st2);
@@ -1077,7 +1246,7 @@ static void test_reftable_stack_compaction_concurrent_clean(void)
clear_dir(dir);
}
-static void test_reftable_stack_read_across_reload(void)
+static void t_reftable_stack_read_across_reload(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_stack *st1 = NULL, *st2 = NULL;
@@ -1088,36 +1257,36 @@ static void test_reftable_stack_read_across_reload(void)
/* Create a first stack and set up an iterator for it. */
err = reftable_new_stack(&st1, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
write_n_ref_tables(st1, 2);
- EXPECT(st1->merged->readers_len == 2);
+ check_int(st1->merged->readers_len, ==, 2);
reftable_stack_init_ref_iterator(st1, &it);
err = reftable_iterator_seek_ref(&it, "");
- EXPECT_ERR(err);
+ check(!err);
/* Set up a second stack for the same directory and compact it. */
err = reftable_new_stack(&st2, dir, &opts);
- EXPECT_ERR(err);
- EXPECT(st2->merged->readers_len == 2);
+ check(!err);
+ check_int(st2->merged->readers_len, ==, 2);
err = reftable_stack_compact_all(st2, NULL);
- EXPECT_ERR(err);
- EXPECT(st2->merged->readers_len == 1);
+ check(!err);
+ check_int(st2->merged->readers_len, ==, 1);
/*
* Verify that we can continue to use the old iterator even after we
* have reloaded its stack.
*/
err = reftable_stack_reload(st1);
- EXPECT_ERR(err);
- EXPECT(st1->merged->readers_len == 1);
+ check(!err);
+ check_int(st1->merged->readers_len, ==, 1);
err = reftable_iterator_next_ref(&it, &rec);
- EXPECT_ERR(err);
- EXPECT(!strcmp(rec.refname, "refs/heads/branch-0000"));
+ check(!err);
+ check_str(rec.refname, "refs/heads/branch-0000");
err = reftable_iterator_next_ref(&it, &rec);
- EXPECT_ERR(err);
- EXPECT(!strcmp(rec.refname, "refs/heads/branch-0001"));
+ check(!err);
+ check_str(rec.refname, "refs/heads/branch-0001");
err = reftable_iterator_next_ref(&it, &rec);
- EXPECT(err > 0);
+ check_int(err, >, 0);
reftable_ref_record_release(&rec);
reftable_iterator_destroy(&it);
@@ -1126,7 +1295,7 @@ static void test_reftable_stack_read_across_reload(void)
clear_dir(dir);
}
-static void test_reftable_stack_reload_with_missing_table(void)
+static void t_reftable_stack_reload_with_missing_table(void)
{
struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
@@ -1138,12 +1307,12 @@ static void test_reftable_stack_reload_with_missing_table(void)
/* Create a first stack and set up an iterator for it. */
err = reftable_new_stack(&st, dir, &opts);
- EXPECT_ERR(err);
+ check(!err);
write_n_ref_tables(st, 2);
- EXPECT(st->merged->readers_len == 2);
+ check_int(st->merged->readers_len, ==, 2);
reftable_stack_init_ref_iterator(st, &it);
err = reftable_iterator_seek_ref(&it, "");
- EXPECT_ERR(err);
+ check(!err);
/*
* Update the tables.list file with some garbage data, while reusing
@@ -1156,24 +1325,24 @@ static void test_reftable_stack_reload_with_missing_table(void)
strbuf_addf(&table_path, "%s.lock", st->list_file);
write_file_buf(table_path.buf, content.buf, content.len);
err = rename(table_path.buf, st->list_file);
- EXPECT_ERR(err);
+ check(!err);
err = reftable_stack_reload(st);
- EXPECT(err == -4);
- EXPECT(st->merged->readers_len == 2);
+ check_int(err, ==, -4);
+ check_int(st->merged->readers_len, ==, 2);
/*
* Even though the reload has failed, we should be able to continue
* using the iterator.
*/
err = reftable_iterator_next_ref(&it, &rec);
- EXPECT_ERR(err);
- EXPECT(!strcmp(rec.refname, "refs/heads/branch-0000"));
+ check(!err);
+ check_str(rec.refname, "refs/heads/branch-0000");
err = reftable_iterator_next_ref(&it, &rec);
- EXPECT_ERR(err);
- EXPECT(!strcmp(rec.refname, "refs/heads/branch-0001"));
+ check(!err);
+ check_str(rec.refname, "refs/heads/branch-0001");
err = reftable_iterator_next_ref(&it, &rec);
- EXPECT(err > 0);
+ check_int(err, >, 0);
reftable_ref_record_release(&rec);
reftable_iterator_destroy(&it);
@@ -1183,31 +1352,35 @@ static void test_reftable_stack_reload_with_missing_table(void)
clear_dir(dir);
}
-int stack_test_main(int argc UNUSED, const char *argv[] UNUSED)
+int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
{
- RUN_TEST(test_empty_add);
- RUN_TEST(test_read_file);
- RUN_TEST(test_reflog_expire);
- RUN_TEST(test_reftable_stack_add);
- RUN_TEST(test_reftable_stack_add_one);
- RUN_TEST(test_reftable_stack_auto_compaction);
- RUN_TEST(test_reftable_stack_auto_compaction_with_locked_tables);
- RUN_TEST(test_reftable_stack_add_performs_auto_compaction);
- RUN_TEST(test_reftable_stack_compaction_concurrent);
- RUN_TEST(test_reftable_stack_compaction_concurrent_clean);
- RUN_TEST(test_reftable_stack_compaction_with_locked_tables);
- RUN_TEST(test_reftable_stack_hash_id);
- RUN_TEST(test_reftable_stack_lock_failure);
- RUN_TEST(test_reftable_stack_log_normalize);
- RUN_TEST(test_reftable_stack_tombstone);
- RUN_TEST(test_reftable_stack_transaction_api);
- RUN_TEST(test_reftable_stack_transaction_api_performs_auto_compaction);
- RUN_TEST(test_reftable_stack_auto_compaction_fails_gracefully);
- RUN_TEST(test_reftable_stack_update_index_check);
- RUN_TEST(test_reftable_stack_uptodate);
- RUN_TEST(test_reftable_stack_read_across_reload);
- RUN_TEST(test_reftable_stack_reload_with_missing_table);
- RUN_TEST(test_suggest_compaction_segment);
- RUN_TEST(test_suggest_compaction_segment_nothing);
- return 0;
+ TEST(t_empty_add(), "empty addition to stack");
+ TEST(t_read_file(), "read_lines works");
+ TEST(t_reflog_expire(), "expire reflog entries");
+ TEST(t_reftable_stack_add(), "add multiple refs and logs to stack");
+ TEST(t_reftable_stack_add_one(), "add a single ref record to stack");
+ TEST(t_reftable_stack_add_performs_auto_compaction(), "addition to stack triggers auto-compaction");
+ TEST(t_reftable_stack_auto_compaction(), "stack must form geometric sequence after compaction");
+ TEST(t_reftable_stack_auto_compaction_factor(), "auto-compaction with non-default geometric factor");
+ TEST(t_reftable_stack_auto_compaction_fails_gracefully(), "failure on auto-compaction");
+ TEST(t_reftable_stack_auto_compaction_with_locked_tables(), "auto compaction with locked tables");
+ TEST(t_reftable_stack_compaction_concurrent(), "compaction with concurrent stack");
+ TEST(t_reftable_stack_compaction_concurrent_clean(), "compaction with unclean stack shutdown");
+ TEST(t_reftable_stack_compaction_with_locked_tables(), "compaction with locked tables");
+ TEST(t_reftable_stack_hash_id(), "read stack with wrong hash ID");
+ TEST(t_reftable_stack_iterator(), "log and ref iterator for reftable stack");
+ TEST(t_reftable_stack_lock_failure(), "stack addition with lockfile failure");
+ TEST(t_reftable_stack_log_normalize(), "log messages should be normalized");
+ TEST(t_reftable_stack_read_across_reload(), "stack iterators work across reloads");
+ TEST(t_reftable_stack_reload_with_missing_table(), "stack iteration with garbage tables");
+ TEST(t_reftable_stack_tombstone(), "'tombstone' refs in stack");
+ TEST(t_reftable_stack_transaction_api(), "update transaction to stack");
+ TEST(t_reftable_stack_transaction_with_reload(), "transaction with reload");
+ TEST(t_reftable_stack_transaction_api_performs_auto_compaction(), "update transaction triggers auto-compaction");
+ TEST(t_reftable_stack_update_index_check(), "update transactions with equal update indices");
+ TEST(t_reftable_stack_uptodate(), "stack must be reloaded before ref update");
+ TEST(t_suggest_compaction_segment(), "suggest_compaction_segment with basic input");
+ TEST(t_suggest_compaction_segment_nothing(), "suggest_compaction_segment with pre-compacted input");
+
+ return test_done();
}
diff --git a/t/unit-tests/t-strvec.c b/t/unit-tests/t-strvec.c
deleted file mode 100644
index 5c844cf0c9..0000000000
--- a/t/unit-tests/t-strvec.c
+++ /dev/null
@@ -1,211 +0,0 @@
-#include "test-lib.h"
-#include "strbuf.h"
-#include "strvec.h"
-
-#define check_strvec(vec, ...) \
- do { \
- const char *expect[] = { __VA_ARGS__ }; \
- if (check_uint(ARRAY_SIZE(expect), >, 0) && \
- check_pointer_eq(expect[ARRAY_SIZE(expect) - 1], NULL) && \
- check_uint((vec)->nr, ==, ARRAY_SIZE(expect) - 1) && \
- check_uint((vec)->nr, <=, (vec)->alloc)) { \
- for (size_t i = 0; i < ARRAY_SIZE(expect); i++) { \
- if (!check_str((vec)->v[i], expect[i])) { \
- test_msg(" i: %"PRIuMAX, \
- (uintmax_t)i); \
- break; \
- } \
- } \
- } \
- } while (0)
-
-int cmd_main(int argc UNUSED, const char **argv UNUSED)
-{
- if_test ("static initialization") {
- struct strvec vec = STRVEC_INIT;
- check_pointer_eq(vec.v, empty_strvec);
- check_uint(vec.nr, ==, 0);
- check_uint(vec.alloc, ==, 0);
- }
-
- if_test ("dynamic initialization") {
- struct strvec vec;
- strvec_init(&vec);
- check_pointer_eq(vec.v, empty_strvec);
- check_uint(vec.nr, ==, 0);
- check_uint(vec.alloc, ==, 0);
- }
-
- if_test ("clear") {
- struct strvec vec = STRVEC_INIT;
- strvec_push(&vec, "foo");
- strvec_clear(&vec);
- check_pointer_eq(vec.v, empty_strvec);
- check_uint(vec.nr, ==, 0);
- check_uint(vec.alloc, ==, 0);
- }
-
- if_test ("push") {
- struct strvec vec = STRVEC_INIT;
-
- strvec_push(&vec, "foo");
- check_strvec(&vec, "foo", NULL);
-
- strvec_push(&vec, "bar");
- check_strvec(&vec, "foo", "bar", NULL);
-
- strvec_clear(&vec);
- }
-
- if_test ("pushf") {
- struct strvec vec = STRVEC_INIT;
- strvec_pushf(&vec, "foo: %d", 1);
- check_strvec(&vec, "foo: 1", NULL);
- strvec_clear(&vec);
- }
-
- if_test ("pushl") {
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", "bar", "baz", NULL);
- check_strvec(&vec, "foo", "bar", "baz", NULL);
- strvec_clear(&vec);
- }
-
- if_test ("pushv") {
- const char *strings[] = {
- "foo", "bar", "baz", NULL,
- };
- struct strvec vec = STRVEC_INIT;
-
- strvec_pushv(&vec, strings);
- check_strvec(&vec, "foo", "bar", "baz", NULL);
-
- strvec_clear(&vec);
- }
-
- if_test ("replace at head") {
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", "bar", "baz", NULL);
- strvec_replace(&vec, 0, "replaced");
- check_strvec(&vec, "replaced", "bar", "baz", NULL);
- strvec_clear(&vec);
- }
-
- if_test ("replace at tail") {
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", "bar", "baz", NULL);
- strvec_replace(&vec, 2, "replaced");
- check_strvec(&vec, "foo", "bar", "replaced", NULL);
- strvec_clear(&vec);
- }
-
- if_test ("replace in between") {
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", "bar", "baz", NULL);
- strvec_replace(&vec, 1, "replaced");
- check_strvec(&vec, "foo", "replaced", "baz", NULL);
- strvec_clear(&vec);
- }
-
- if_test ("replace with substring") {
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", NULL);
- strvec_replace(&vec, 0, vec.v[0] + 1);
- check_strvec(&vec, "oo", NULL);
- strvec_clear(&vec);
- }
-
- if_test ("remove at head") {
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", "bar", "baz", NULL);
- strvec_remove(&vec, 0);
- check_strvec(&vec, "bar", "baz", NULL);
- strvec_clear(&vec);
- }
-
- if_test ("remove at tail") {
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", "bar", "baz", NULL);
- strvec_remove(&vec, 2);
- check_strvec(&vec, "foo", "bar", NULL);
- strvec_clear(&vec);
- }
-
- if_test ("remove in between") {
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", "bar", "baz", NULL);
- strvec_remove(&vec, 1);
- check_strvec(&vec, "foo", "baz", NULL);
- strvec_clear(&vec);
- }
-
- if_test ("pop with empty array") {
- struct strvec vec = STRVEC_INIT;
- strvec_pop(&vec);
- check_strvec(&vec, NULL);
- strvec_clear(&vec);
- }
-
- if_test ("pop with non-empty array") {
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", "bar", "baz", NULL);
- strvec_pop(&vec);
- check_strvec(&vec, "foo", "bar", NULL);
- strvec_clear(&vec);
- }
-
- if_test ("split empty string") {
- struct strvec vec = STRVEC_INIT;
- strvec_split(&vec, "");
- check_strvec(&vec, NULL);
- strvec_clear(&vec);
- }
-
- if_test ("split single item") {
- struct strvec vec = STRVEC_INIT;
- strvec_split(&vec, "foo");
- check_strvec(&vec, "foo", NULL);
- strvec_clear(&vec);
- }
-
- if_test ("split multiple items") {
- struct strvec vec = STRVEC_INIT;
- strvec_split(&vec, "foo bar baz");
- check_strvec(&vec, "foo", "bar", "baz", NULL);
- strvec_clear(&vec);
- }
-
- if_test ("split whitespace only") {
- struct strvec vec = STRVEC_INIT;
- strvec_split(&vec, " \t\n");
- check_strvec(&vec, NULL);
- strvec_clear(&vec);
- }
-
- if_test ("split multiple consecutive whitespaces") {
- struct strvec vec = STRVEC_INIT;
- strvec_split(&vec, "foo\n\t bar");
- check_strvec(&vec, "foo", "bar", NULL);
- strvec_clear(&vec);
- }
-
- if_test ("detach") {
- struct strvec vec = STRVEC_INIT;
- const char **detached;
-
- strvec_push(&vec, "foo");
-
- detached = strvec_detach(&vec);
- check_str(detached[0], "foo");
- check_pointer_eq(detached[1], NULL);
-
- check_pointer_eq(vec.v, empty_strvec);
- check_uint(vec.nr, ==, 0);
- check_uint(vec.alloc, ==, 0);
-
- free((char *) detached[0]);
- free(detached);
- }
-
- return test_done();
-}
diff --git a/t/unit-tests/unit-test.c b/t/unit-tests/unit-test.c
new file mode 100644
index 0000000000..a474cdcfd3
--- /dev/null
+++ b/t/unit-tests/unit-test.c
@@ -0,0 +1,47 @@
+#include "unit-test.h"
+#include "parse-options.h"
+#include "string-list.h"
+#include "strvec.h"
+
+static const char * const unit_test_usage[] = {
+ N_("unit-test [<options>]"),
+ NULL,
+};
+
+int cmd_main(int argc, const char **argv)
+{
+ struct string_list run_args = STRING_LIST_INIT_NODUP;
+ struct string_list exclude_args = STRING_LIST_INIT_NODUP;
+ int immediate = 0;
+ struct option options[] = {
+ OPT_BOOL('i', "immediate", &immediate,
+ N_("immediately exit upon the first failed test")),
+ OPT_STRING_LIST('r', "run", &run_args, N_("suite[::test]"),
+ N_("run only test suite or individual test <suite[::test]>")),
+ OPT_STRING_LIST('x', "exclude", &exclude_args, N_("suite"),
+ N_("exclude test suite <suite>")),
+ OPT_END(),
+ };
+ struct strvec args = STRVEC_INIT;
+ int ret;
+
+ argc = parse_options(argc, argv, NULL, options,
+ unit_test_usage, PARSE_OPT_KEEP_ARGV0);
+ if (argc > 1)
+ usagef(_("extra command line parameter '%s'"), argv[0]);
+
+ strvec_push(&args, argv[0]);
+ strvec_push(&args, "-t");
+ if (immediate)
+ strvec_push(&args, "-Q");
+ for (size_t i = 0; i < run_args.nr; i++)
+ strvec_pushf(&args, "-s%s", run_args.items[i].string);
+ for (size_t i = 0; i < exclude_args.nr; i++)
+ strvec_pushf(&args, "-x%s", exclude_args.items[i].string);
+
+ ret = clar_test(args.nr, (char **) args.v);
+
+ string_list_clear(&run_args, 0);
+ strvec_clear(&args);
+ return ret;
+}
diff --git a/t/unit-tests/unit-test.h b/t/unit-tests/unit-test.h
new file mode 100644
index 0000000000..85e5d6a948
--- /dev/null
+++ b/t/unit-tests/unit-test.h
@@ -0,0 +1,10 @@
+#include "git-compat-util.h"
+#include "clar/clar.h"
+#include "clar-decls.h"
+#include "strbuf.h"
+
+#define cl_failf(fmt, ...) do { \
+ char desc[4096]; \
+ snprintf(desc, sizeof(desc), fmt, __VA_ARGS__); \
+ clar__fail(__FILE__, __func__, __LINE__, "Test failed.", desc, 1); \
+} while (0)
diff --git a/tmp-objdir.c b/tmp-objdir.c
index a8e4553f27..c2fb9f9193 100644
--- a/tmp-objdir.c
+++ b/tmp-objdir.c
@@ -13,6 +13,7 @@
#include "strvec.h"
#include "quote.h"
#include "object-store-ll.h"
+#include "repository.h"
struct tmp_objdir {
struct strbuf path;
@@ -132,7 +133,8 @@ struct tmp_objdir *tmp_objdir_create(const char *prefix)
* can recognize any stale objdirs left behind by a crash and delete
* them.
*/
- strbuf_addf(&t->path, "%s/tmp_objdir-%s-XXXXXX", get_object_directory(), prefix);
+ strbuf_addf(&t->path, "%s/tmp_objdir-%s-XXXXXX",
+ repo_get_object_directory(the_repository), prefix);
if (!mkdtemp(t->path.buf)) {
/* free, not destroy, as we never touched the filesystem */
@@ -152,7 +154,7 @@ struct tmp_objdir *tmp_objdir_create(const char *prefix)
}
env_append(&t->env, ALTERNATE_DB_ENVIRONMENT,
- absolute_path(get_object_directory()));
+ absolute_path(repo_get_object_directory(the_repository)));
env_replace(&t->env, DB_ENVIRONMENT, absolute_path(t->path.buf));
env_replace(&t->env, GIT_QUARANTINE_ENVIRONMENT,
absolute_path(t->path.buf));
@@ -267,7 +269,7 @@ int tmp_objdir_migrate(struct tmp_objdir *t)
}
strbuf_addbuf(&src, &t->path);
- strbuf_addstr(&dst, get_object_directory());
+ strbuf_addstr(&dst, repo_get_object_directory(the_repository));
ret = migrate_paths(&src, &dst);
diff --git a/trace.c b/trace.c
index 8669ddfca2..d8c43773ae 100644
--- a/trace.c
+++ b/trace.c
@@ -21,9 +21,11 @@
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
#include "abspath.h"
-#include "environment.h"
+#include "repository.h"
#include "quote.h"
#include "setup.h"
#include "trace.h"
@@ -305,14 +307,14 @@ void trace_repo_setup(void)
cwd = xgetcwd();
- if (!(git_work_tree = get_git_work_tree()))
+ if (!(git_work_tree = repo_get_work_tree(the_repository)))
git_work_tree = "(null)";
if (!startup_info->prefix)
prefix = "(null)";
- trace_printf_key(&trace_setup_key, "setup: git_dir: %s\n", quote_crnl(get_git_dir()));
- trace_printf_key(&trace_setup_key, "setup: git_common_dir: %s\n", quote_crnl(get_git_common_dir()));
+ trace_printf_key(&trace_setup_key, "setup: git_dir: %s\n", quote_crnl(repo_get_git_dir(the_repository)));
+ trace_printf_key(&trace_setup_key, "setup: git_common_dir: %s\n", quote_crnl(repo_get_common_dir(the_repository)));
trace_printf_key(&trace_setup_key, "setup: worktree: %s\n", quote_crnl(git_work_tree));
trace_printf_key(&trace_setup_key, "setup: cwd: %s\n", quote_crnl(cwd));
trace_printf_key(&trace_setup_key, "setup: prefix: %s\n", quote_crnl(prefix));
diff --git a/trace2.h b/trace2.h
index 19e04bf040..901f39253a 100644
--- a/trace2.h
+++ b/trace2.h
@@ -554,6 +554,7 @@ enum trace2_counter_id {
TRACE2_COUNTER_ID_TEST2, /* emits summary and thread events */
TRACE2_COUNTER_ID_PACKED_REFS_JUMPS, /* counts number of jumps */
+ TRACE2_COUNTER_ID_REFTABLE_RESEEKS, /* counts number of re-seeks */
/* counts number of fsyncs */
TRACE2_COUNTER_ID_FSYNC_WRITEOUT_ONLY,
diff --git a/trace2/tr2_cfg.c b/trace2/tr2_cfg.c
index d96d908bb9..22a99a0682 100644
--- a/trace2/tr2_cfg.c
+++ b/trace2/tr2_cfg.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
#include "config.h"
#include "strbuf.h"
@@ -124,7 +126,7 @@ void tr2_cfg_list_config_fl(const char *file, int line)
struct tr2_cfg_data data = { file, line };
if (tr2_cfg_load_patterns() > 0)
- read_early_config(tr2_cfg_cb, &data);
+ read_early_config(the_repository, tr2_cfg_cb, &data);
}
void tr2_list_env_vars_fl(const char *file, int line)
diff --git a/trace2/tr2_ctr.c b/trace2/tr2_ctr.c
index d3a33715c1..036b643578 100644
--- a/trace2/tr2_ctr.c
+++ b/trace2/tr2_ctr.c
@@ -31,6 +31,11 @@ static struct tr2_counter_metadata tr2_counter_metadata[TRACE2_NUMBER_OF_COUNTER
.name = "jumps_made",
.want_per_thread_events = 0,
},
+ [TRACE2_COUNTER_ID_REFTABLE_RESEEKS] = {
+ .category = "reftable",
+ .name = "reseeks_made",
+ .want_per_thread_events = 0,
+ },
[TRACE2_COUNTER_ID_FSYNC_WRITEOUT_ONLY] = {
.category = "fsync",
.name = "writeout-only",
diff --git a/transport-helper.c b/transport-helper.c
index 09b3560ffd..c688967b8c 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -89,11 +89,18 @@ static int recvline(struct helper_data *helper, struct strbuf *buffer)
return recvline_fh(helper->out, buffer);
}
-static void write_constant(int fd, const char *str)
+static int write_constant_gently(int fd, const char *str)
{
if (debug)
fprintf(stderr, "Debug: Remote helper: -> %s", str);
if (write_in_full(fd, str, strlen(str)) < 0)
+ return -1;
+ return 0;
+}
+
+static void write_constant(int fd, const char *str)
+{
+ if (write_constant_gently(fd, str) < 0)
die_errno(_("full write to remote helper failed"));
}
@@ -143,7 +150,7 @@ static struct child_process *get_helper(struct transport *transport)
if (have_git_dir())
strvec_pushf(&helper->env, "%s=%s",
- GIT_DIR_ENVIRONMENT, get_git_dir());
+ GIT_DIR_ENVIRONMENT, repo_get_git_dir(the_repository));
helper->trace2_child_class = helper->args.v[0]; /* "remote-<name>" */
@@ -168,13 +175,16 @@ static struct child_process *get_helper(struct transport *transport)
die_errno(_("can't dup helper output fd"));
data->out = xfdopen(duped, "r");
- write_constant(helper->in, "capabilities\n");
+ sigchain_push(SIGPIPE, SIG_IGN);
+ if (write_constant_gently(helper->in, "capabilities\n") < 0)
+ die("remote helper '%s' aborted session", data->name);
+ sigchain_pop(SIGPIPE);
while (1) {
const char *capname, *arg;
int mandatory = 0;
if (recvline(data, &buf))
- exit(128);
+ die("remote helper '%s' aborted session", data->name);
if (!*buf.buf)
break;
diff --git a/tree-diff.c b/tree-diff.c
index 9252481df3..5eab8af631 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -1,6 +1,9 @@
/*
* Helper functions for tree diff generation
*/
+
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
#include "diff.h"
#include "diffcore.h"
diff --git a/unicode-width.h b/unicode-width.h
index be5bf8c4f2..3ffee123a0 100644
--- a/unicode-width.h
+++ b/unicode-width.h
@@ -27,7 +27,7 @@ static const struct interval zero_width[] = {
{ 0x0829, 0x082D },
{ 0x0859, 0x085B },
{ 0x0890, 0x0891 },
-{ 0x0898, 0x089F },
+{ 0x0897, 0x089F },
{ 0x08CA, 0x0902 },
{ 0x093A, 0x093A },
{ 0x093C, 0x093C },
@@ -227,8 +227,9 @@ static const struct interval zero_width[] = {
{ 0x10A3F, 0x10A3F },
{ 0x10AE5, 0x10AE6 },
{ 0x10D24, 0x10D27 },
+{ 0x10D69, 0x10D6D },
{ 0x10EAB, 0x10EAC },
-{ 0x10EFD, 0x10EFF },
+{ 0x10EFC, 0x10EFF },
{ 0x10F46, 0x10F50 },
{ 0x10F82, 0x10F85 },
{ 0x11001, 0x11001 },
@@ -261,6 +262,11 @@ static const struct interval zero_width[] = {
{ 0x11340, 0x11340 },
{ 0x11366, 0x1136C },
{ 0x11370, 0x11374 },
+{ 0x113BB, 0x113C0 },
+{ 0x113CE, 0x113CE },
+{ 0x113D0, 0x113D0 },
+{ 0x113D2, 0x113D2 },
+{ 0x113E1, 0x113E2 },
{ 0x11438, 0x1143F },
{ 0x11442, 0x11444 },
{ 0x11446, 0x11446 },
@@ -280,7 +286,8 @@ static const struct interval zero_width[] = {
{ 0x116AD, 0x116AD },
{ 0x116B0, 0x116B5 },
{ 0x116B7, 0x116B7 },
-{ 0x1171D, 0x1171F },
+{ 0x1171D, 0x1171D },
+{ 0x1171F, 0x1171F },
{ 0x11722, 0x11725 },
{ 0x11727, 0x1172B },
{ 0x1182F, 0x11837 },
@@ -319,8 +326,11 @@ static const struct interval zero_width[] = {
{ 0x11F36, 0x11F3A },
{ 0x11F40, 0x11F40 },
{ 0x11F42, 0x11F42 },
+{ 0x11F5A, 0x11F5A },
{ 0x13430, 0x13440 },
{ 0x13447, 0x13455 },
+{ 0x1611E, 0x16129 },
+{ 0x1612D, 0x1612F },
{ 0x16AF0, 0x16AF4 },
{ 0x16B30, 0x16B36 },
{ 0x16F4F, 0x16F4F },
@@ -351,6 +361,7 @@ static const struct interval zero_width[] = {
{ 0x1E2AE, 0x1E2AE },
{ 0x1E2EC, 0x1E2EF },
{ 0x1E4EC, 0x1E4EF },
+{ 0x1E5EE, 0x1E5EF },
{ 0x1E8D0, 0x1E8D6 },
{ 0x1E944, 0x1E94A },
{ 0xE0001, 0xE0001 },
@@ -366,8 +377,10 @@ static const struct interval double_width[] = {
{ 0x23F3, 0x23F3 },
{ 0x25FD, 0x25FE },
{ 0x2614, 0x2615 },
+{ 0x2630, 0x2637 },
{ 0x2648, 0x2653 },
{ 0x267F, 0x267F },
+{ 0x268A, 0x268F },
{ 0x2693, 0x2693 },
{ 0x26A1, 0x26A1 },
{ 0x26AA, 0x26AB },
@@ -401,11 +414,10 @@ static const struct interval double_width[] = {
{ 0x3099, 0x30FF },
{ 0x3105, 0x312F },
{ 0x3131, 0x318E },
-{ 0x3190, 0x31E3 },
+{ 0x3190, 0x31E5 },
{ 0x31EF, 0x321E },
{ 0x3220, 0x3247 },
-{ 0x3250, 0x4DBF },
-{ 0x4E00, 0xA48C },
+{ 0x3250, 0xA48C },
{ 0xA490, 0xA4C6 },
{ 0xA960, 0xA97C },
{ 0xAC00, 0xD7A3 },
@@ -420,7 +432,7 @@ static const struct interval double_width[] = {
{ 0x16FF0, 0x16FF1 },
{ 0x17000, 0x187F7 },
{ 0x18800, 0x18CD5 },
-{ 0x18D00, 0x18D08 },
+{ 0x18CFF, 0x18D08 },
{ 0x1AFF0, 0x1AFF3 },
{ 0x1AFF5, 0x1AFFB },
{ 0x1AFFD, 0x1AFFE },
@@ -430,6 +442,8 @@ static const struct interval double_width[] = {
{ 0x1B155, 0x1B155 },
{ 0x1B164, 0x1B167 },
{ 0x1B170, 0x1B2FB },
+{ 0x1D300, 0x1D356 },
+{ 0x1D360, 0x1D376 },
{ 0x1F004, 0x1F004 },
{ 0x1F0CF, 0x1F0CF },
{ 0x1F18E, 0x1F18E },
@@ -470,11 +484,10 @@ static const struct interval double_width[] = {
{ 0x1F93C, 0x1F945 },
{ 0x1F947, 0x1F9FF },
{ 0x1FA70, 0x1FA7C },
-{ 0x1FA80, 0x1FA88 },
-{ 0x1FA90, 0x1FABD },
-{ 0x1FABF, 0x1FAC5 },
-{ 0x1FACE, 0x1FADB },
-{ 0x1FAE0, 0x1FAE8 },
+{ 0x1FA80, 0x1FA89 },
+{ 0x1FA8F, 0x1FAC6 },
+{ 0x1FACE, 0x1FADC },
+{ 0x1FADF, 0x1FAE9 },
{ 0x1FAF0, 0x1FAF8 },
{ 0x20000, 0x2FFFD },
{ 0x30000, 0x3FFFD }
diff --git a/upload-pack.c b/upload-pack.c
index c84c3c3b1f..6d6e0f9f98 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1812,7 +1812,7 @@ int upload_pack_v2(struct repository *r, struct packet_reader *request)
} else {
/*
* Request had 'want's but no 'have's so we can
- * immedietly go to construct and send a pack.
+ * immediately go to construct and send a pack.
*/
state = FETCH_SEND_PACK;
}
diff --git a/userdiff.c b/userdiff.c
index 989629149f..d43d8360d1 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
#include "config.h"
#include "userdiff.h"
diff --git a/worktree.c b/worktree.c
index 30a947426e..0f032ccedf 100644
--- a/worktree.c
+++ b/worktree.c
@@ -57,7 +57,7 @@ static void add_head_info(struct worktree *wt)
static int is_current_worktree(struct worktree *wt)
{
- char *git_dir = absolute_pathdup(get_git_dir());
+ char *git_dir = absolute_pathdup(repo_get_git_dir(the_repository));
const char *wt_git_dir = get_worktree_git_dir(wt);
int is_current = !fspathcmp(git_dir, absolute_path(wt_git_dir));
free(git_dir);
@@ -72,7 +72,7 @@ static struct worktree *get_main_worktree(int skip_reading_head)
struct worktree *worktree = NULL;
struct strbuf worktree_path = STRBUF_INIT;
- strbuf_add_real_path(&worktree_path, get_git_common_dir());
+ strbuf_add_real_path(&worktree_path, repo_get_common_dir(the_repository));
strbuf_strip_suffix(&worktree_path, "/.git");
CALLOC_ARRAY(worktree, 1);
@@ -143,7 +143,7 @@ static struct worktree **get_worktrees_internal(int skip_reading_head)
list[counter++] = get_main_worktree(skip_reading_head);
- strbuf_addf(&path, "%s/worktrees", get_git_common_dir());
+ strbuf_addf(&path, "%s/worktrees", repo_get_common_dir(the_repository));
dir = opendir(path.buf);
strbuf_release(&path);
if (dir) {
@@ -171,9 +171,9 @@ struct worktree **get_worktrees(void)
const char *get_worktree_git_dir(const struct worktree *wt)
{
if (!wt)
- return get_git_dir();
+ return repo_get_git_dir(the_repository);
else if (!wt->id)
- return get_git_common_dir();
+ return repo_get_common_dir(the_repository);
else
return git_common_path("worktrees/%s", wt->id);
}
@@ -626,7 +626,7 @@ static int is_main_worktree_path(const char *path)
strbuf_add_real_path(&target, path);
strbuf_strip_suffix(&target, "/.git");
- strbuf_add_real_path(&maindir, get_git_common_dir());
+ strbuf_add_real_path(&maindir, repo_get_common_dir(the_repository));
strbuf_strip_suffix(&maindir, "/.git");
cmp = fspathcmp(maindir.buf, target.buf);
diff --git a/wt-status.c b/wt-status.c
index b477239039..6a6397ca8f 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -16,6 +16,7 @@
#include "revision.h"
#include "diffcore.h"
#include "quote.h"
+#include "repository.h"
#include "run-command.h"
#include "strvec.h"
#include "remote.h"
@@ -152,7 +153,7 @@ void wt_status_prepare(struct repository *r, struct wt_status *s)
"HEAD", 0, NULL, NULL);
s->reference = "HEAD";
s->fp = stdout;
- s->index_file = get_index_file();
+ s->index_file = repo_get_index_file(the_repository);
s->change.strdup_strings = 1;
s->untracked.strdup_strings = 1;
s->ignored.strdup_strings = 1;
@@ -2595,7 +2596,7 @@ int has_unstaged_changes(struct repository *r, int ignore_submodules)
rev_info.diffopt.flags.quick = 1;
diff_setup_done(&rev_info.diffopt);
run_diff_files(&rev_info, 0);
- result = diff_result_code(&rev_info.diffopt);
+ result = diff_result_code(&rev_info);
release_revisions(&rev_info);
return result;
}
@@ -2629,7 +2630,7 @@ int has_uncommitted_changes(struct repository *r,
diff_setup_done(&rev_info.diffopt);
run_diff_index(&rev_info, DIFF_INDEX_CACHED);
- result = diff_result_code(&rev_info.diffopt);
+ result = diff_result_code(&rev_info);
release_revisions(&rev_info);
return result;
}