]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'rp/apply-cached-doc'
authorJunio C Hamano <gitster@pobox.com>
Mon, 31 Aug 2020 22:49:51 +0000 (15:49 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 31 Aug 2020 22:49:51 +0000 (15:49 -0700)
The description of --cached/--index options in "git apply --help"
has been updated.

* rp/apply-cached-doc:
  git-apply.txt: update descriptions of --cached, --index

425 files changed:
.github/workflows/main.yml
Documentation/Makefile
Documentation/MyFirstContribution.txt
Documentation/RelNotes/2.29.0.txt [new file with mode: 0644]
Documentation/blame-options.txt
Documentation/cmd-list.perl
Documentation/config.txt
Documentation/config/extensions.txt [new file with mode: 0644]
Documentation/config/fmt-merge-msg.txt
Documentation/config/sendemail.txt
Documentation/config/uploadpack.txt
Documentation/diff-options.txt
Documentation/fetch-options.txt
Documentation/git-bisect.txt
Documentation/git-bundle.txt
Documentation/git-commit-graph.txt
Documentation/git-for-each-ref.txt
Documentation/git-help.txt
Documentation/git-index-pack.txt
Documentation/git-init.txt
Documentation/git-log.txt
Documentation/git-multi-pack-index.txt
Documentation/git-notes.txt
Documentation/git-pack-objects.txt
Documentation/git-rev-list.txt
Documentation/git-show-index.txt
Documentation/git-update-ref.txt
Documentation/git-worktree.txt
Documentation/git.txt
Documentation/gitcredentials.txt
Documentation/object-format-disclaimer.txt [new file with mode: 0644]
Documentation/rev-list-description.txt [new file with mode: 0644]
Documentation/rev-list-options.txt
Documentation/revisions.txt
Documentation/technical/api-parse-options.txt
Documentation/technical/bundle-format.txt
Documentation/technical/commit-graph-format.txt
Documentation/technical/commit-graph.txt
Documentation/technical/hash-function-transition.txt
Documentation/technical/http-protocol.txt
Documentation/technical/index-format.txt
Documentation/technical/pack-format.txt
Documentation/technical/protocol-capabilities.txt
Documentation/technical/shallow.txt
Makefile
RelNotes
add-interactive.c
add-patch.c
apply.c
argv-array.c [deleted file]
bisect.c
bisect.h
blame.c
bloom.c
bugreport.c
builtin/add.c
builtin/am.c
builtin/annotate.c
builtin/bisect--helper.c
builtin/blame.c
builtin/bundle.c
builtin/check-ignore.c
builtin/checkout.c
builtin/clean.c
builtin/clone.c
builtin/commit-graph.c
builtin/commit.c
builtin/describe.c
builtin/difftool.c
builtin/fetch.c
builtin/fsck.c
builtin/gc.c
builtin/grep.c
builtin/help.c
builtin/index-pack.c
builtin/init-db.c
builtin/log.c
builtin/ls-files.c
builtin/ls-remote.c
builtin/merge.c
builtin/mv.c
builtin/name-rev.c
builtin/pack-objects.c
builtin/pull.c
builtin/range-diff.c
builtin/rebase.c
builtin/receive-pack.c
builtin/remote-ext.c
builtin/remote.c
builtin/repack.c
builtin/replace.c
builtin/rev-list.c
builtin/show-branch.c
builtin/stash.c
builtin/submodule--helper.c
builtin/update-ref.c
builtin/upload-archive.c
builtin/verify-pack.c
builtin/worktree.c
bundle.c
bundle.h
cache.h
checkout.c
ci/lib.sh
ci/run-build-and-tests.sh
column.c
command-list.txt
commit-graph.c
commit-graph.h
commit-slab-decl.h
commit-slab-impl.h
commit-slab.h
commit.c
compat/mingw.c
compat/terminal.c
config.c
config.h
config.mak.dev
connect.c
connected.c
contrib/buildsystems/CMakeLists.txt [new file with mode: 0644]
contrib/completion/git-completion.bash
contrib/subtree/git-subtree.txt
contrib/subtree/t/t7900-subtree.sh
daemon.c
diff-lib.c
diff.c
diff.h
dir.c
dir.h
editor.c
entry.c
environment.c
exec-cmd.c
exec-cmd.h
fast-import.c
fetch-pack.c
fmt-merge-msg.c
fsmonitor.c
git-bisect.sh
git-compat-util.h
git-cvsexportcommit.perl
git-mergetool--lib.sh
git-rebase--preserve-merges.sh
git-send-email.perl
git.c
gpg-interface.c
graph.c
grep.c
hashmap.h
help.c
help.h
http-backend.c
http-fetch.c
http-push.c
http.c
imap-send.c
line-log.c
list-objects-filter-options.c
list-objects-filter-options.h
ls-refs.c
ls-refs.h
mem-pool.c
mem-pool.h
merge-recursive.c
merge-recursive.h
merge.c
mergetools/bc
mergetools/bc3 [deleted file]
mergetools/gvimdiff3 [deleted file]
mergetools/nvimdiff [moved from mergetools/gvimdiff2 with 100% similarity]
mergetools/vimdiff
mergetools/vimdiff2 [deleted file]
mergetools/vimdiff3 [deleted file]
midx.c
object-store.h
pack-write.c
pager.c
parse-options-cb.c
parse-options.c
parse-options.h
path.c
path.h
pathspec.c
perl/Git.pm
po/fr.po
progress.c
protocol.c
quote.c
quote.h
range-diff.c
range-diff.h
read-cache.c
ref-filter.c
refs.c
refs.h
refs/files-backend.c
refs/packed-backend.c
refs/refs-internal.h
refspec.c
refspec.h
remote-curl.c
remote-testsvn.c
remote.c
remote.h
repository.c
revision.c
revision.h
run-command.c
run-command.h
send-pack.c
sequencer.c
serve.c
serve.h
setup.c
sha1-file.c
shallow.c
sideband.c
split-index.c
strvec.c [new file with mode: 0644]
strvec.h [moved from argv-array.h with 50% similarity]
sub-process.c
submodule.c
submodule.h
t/README
t/helper/test-bloom.c
t/helper/test-config.c
t/helper/test-read-midx.c
t/helper/test-run-command.c
t/helper/test-trace2.c
t/lib-pack.sh
t/lib-submodule-update.sh
t/lib-t6000.sh
t/perf/README
t/perf/p5302-pack-index.sh
t/perf/perf-lib.sh
t/t0000-basic.sh
t/t0001-init.sh
t/t0040-parse-options.sh
t/t0410-partial-clone.sh
t/t1006-cat-file.sh
t/t1050-large.sh
t/t1091-sparse-checkout-builtin.sh
t/t1302-repo-version.sh
t/t1400-update-ref.sh
t/t1405-main-ref-store.sh
t/t1410-reflog.sh
t/t1416-ref-transaction-hooks.sh
t/t1450-fsck.sh
t/t1500-rev-parse.sh
t/t1507-rev-parse-upstream.sh
t/t2025-checkout-no-overlay.sh
t/t2072-restore-pathspec-file.sh
t/t3000-ls-files-others.sh
t/t3305-notes-fanout.sh
t/t3308-notes-merge.sh
t/t3404-rebase-interactive.sh
t/t3432-rebase-fast-forward.sh
t/t3500-cherry.sh
t/t3501-revert-cherry-pick.sh
t/t3507-cherry-pick-conflict.sh
t/t3600-rm.sh
t/t3701-add-interactive.sh
t/t3800-mktag.sh
t/t4002-diff-basic.sh
t/t4005-diff-rename-2.sh
t/t4010-diff-pathspec.sh
t/t4013-diff-various.sh
t/t4013/diff.diff-tree_--root_-p_--abbrev=10_initial [new file with mode: 0644]
t/t4013/diff.diff-tree_--root_-p_--full-index_--abbrev=10_initial [new file with mode: 0644]
t/t4013/diff.diff-tree_--root_-p_--full-index_initial [new file with mode: 0644]
t/t4013/diff.log_--decorate=full_--all
t/t4013/diff.log_--decorate_--all
t/t4013/diff.log_--diff-merges=off_-p_--first-parent_master [new file with mode: 0644]
t/t4013/diff.log_--first-parent_--diff-merges=off_-p_master [new file with mode: 0644]
t/t4013/diff.log_--no-diff-merges_-p_--first-parent_master [new file with mode: 0644]
t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
t/t4013/diff.log_--patch-with-stat_master
t/t4013/diff.log_--patch-with-stat_master_--_dir_
t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
t/t4013/diff.log_--root_--patch-with-stat_--summary_master
t/t4013/diff.log_--root_--patch-with-stat_master
t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master
t/t4013/diff.log_--root_-p_master
t/t4013/diff.log_--root_master
t/t4013/diff.log_-m_-p_--first-parent_master
t/t4013/diff.log_-m_-p_master
t/t4013/diff.log_-p_--first-parent_master
t/t4013/diff.log_-p_master
t/t4013/diff.log_master
t/t4013/diff.show_--first-parent_master
t/t4013/diff.show_-c_master
t/t4013/diff.show_-m_master
t/t4013/diff.show_master
t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master
t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
t/t4018/fortran-block-data [new file with mode: 0644]
t/t4018/fortran-comment [new file with mode: 0644]
t/t4018/fortran-comment-keyword [new file with mode: 0644]
t/t4018/fortran-comment-legacy [new file with mode: 0644]
t/t4018/fortran-comment-legacy-star [new file with mode: 0644]
t/t4018/fortran-external-function [new file with mode: 0644]
t/t4018/fortran-external-subroutine [new file with mode: 0644]
t/t4018/fortran-module [new file with mode: 0644]
t/t4018/fortran-module-procedure [new file with mode: 0644]
t/t4018/fortran-program [new file with mode: 0644]
t/t4027-diff-submodule.sh
t/t4034-diff-words.sh
t/t4104-apply-boundary.sh
t/t4134-apply-submodule.sh
t/t4140-apply-ita.sh [new file with mode: 0755]
t/t4150-am.sh
t/t4200-rerere.sh
t/t4202-log.sh
t/t4211-line-log.sh
t/t4216-log-bloom.sh
t/t5300-pack-object.sh
t/t5302-pack-index.sh
t/t5308-pack-detect-duplicates.sh
t/t5313-pack-bounds-checks.sh
t/t5318-commit-graph.sh
t/t5319-multi-pack-index.sh
t/t5324-split-commit-graph.sh
t/t5504-fetch-receive-strict.sh
t/t5510-fetch.sh
t/t5521-pull-options.sh
t/t5530-upload-pack-error.sh
t/t5539-fetch-http-shallow.sh
t/t5541-http-push-smart.sh
t/t5553-set-upstream.sh
t/t5562-http-backend-content-length.sh
t/t5601-clone.sh
t/t5607-clone-bundle.sh
t/t5616-partial-clone.sh
t/t5702-protocol-v2.sh
t/t5703-upload-pack-ref-in-want.sh
t/t6000-rev-list-misc.sh
t/t6002-rev-list-bisect.sh
t/t6006-rev-list-format.sh
t/t6030-bisect-porcelain.sh
t/t6100-rev-list-in-order.sh
t/t6101-rev-parse-parents.sh
t/t6200-fmt-merge-msg.sh
t/t6300-for-each-ref.sh
t/t6301-for-each-ref-errors.sh
t/t6400-merge-df.sh [moved from t/t6020-merge-df.sh with 100% similarity]
t/t6401-merge-criss-cross.sh [moved from t/t6021-merge-criss-cross.sh with 100% similarity]
t/t6402-merge-rename.sh [moved from t/t6022-merge-rename.sh with 100% similarity]
t/t6403-merge-file.sh [moved from t/t6023-merge-file.sh with 100% similarity]
t/t6404-recursive-merge.sh [moved from t/t6024-recursive-merge.sh with 100% similarity]
t/t6405-merge-symlinks.sh [moved from t/t6025-merge-symlinks.sh with 100% similarity]
t/t6406-merge-attr.sh [moved from t/t6026-merge-attr.sh with 98% similarity]
t/t6407-merge-binary.sh [moved from t/t6027-merge-binary.sh with 100% similarity]
t/t6408-merge-up-to-date.sh [moved from t/t6028-merge-up-to-date.sh with 100% similarity]
t/t6409-merge-subtree.sh [moved from t/t6029-merge-subtree.sh with 100% similarity]
t/t6411-merge-filemode.sh [moved from t/t6031-merge-filemode.sh with 100% similarity]
t/t6412-merge-large-rename.sh [moved from t/t6032-merge-large-rename.sh with 100% similarity]
t/t6413-merge-crlf.sh [moved from t/t6033-merge-crlf.sh with 100% similarity]
t/t6414-merge-rename-nocruft.sh [moved from t/t6034-merge-rename-nocruft.sh with 100% similarity]
t/t6415-merge-dir-to-symlink.sh [moved from t/t6035-merge-dir-to-symlink.sh with 100% similarity]
t/t6416-recursive-corner-cases.sh [moved from t/t6036-recursive-corner-cases.sh with 99% similarity]
t/t6417-merge-ours-theirs.sh [moved from t/t6037-merge-ours-theirs.sh with 100% similarity]
t/t6418-merge-text-auto.sh [moved from t/t6038-merge-text-auto.sh with 88% similarity]
t/t6419-merge-ignorecase.sh [moved from t/t6039-merge-ignorecase.sh with 100% similarity]
t/t6422-merge-rename-corner-cases.sh [moved from t/t6042-merge-rename-corner-cases.sh with 94% similarity]
t/t6423-merge-rename-directories.sh [moved from t/t6043-merge-rename-directories.sh with 98% similarity]
t/t6424-merge-unrelated-index-changes.sh [moved from t/t6044-merge-unrelated-index-changes.sh with 100% similarity]
t/t6425-merge-rename-delete.sh [moved from t/t6045-merge-rename-delete.sh with 72% similarity]
t/t6426-merge-skip-unneeded-updates.sh [moved from t/t6046-merge-skip-unneeded-updates.sh with 99% similarity]
t/t6427-diff3-conflict-markers.sh [moved from t/t6047-diff3-conflict-markers.sh with 100% similarity]
t/t6430-merge-recursive.sh [moved from t/t3030-merge-recursive.sh with 100% similarity]
t/t6431-merge-criscross.sh [moved from t/t3031-merge-criscross.sh with 100% similarity]
t/t6432-merge-recursive-space-options.sh [moved from t/t3032-merge-recursive-space-options.sh with 100% similarity]
t/t6433-merge-toplevel.sh [moved from t/t3033-merge-toplevel.sh with 100% similarity]
t/t6434-merge-recursive-rename-options.sh [moved from t/t3034-merge-recursive-rename-options.sh with 100% similarity]
t/t6435-merge-sparse.sh [moved from t/t3035-merge-sparse.sh with 100% similarity]
t/t6436-merge-overwrite.sh [moved from t/t7607-merge-overwrite.sh with 100% similarity]
t/t6437-submodule-merge.sh [moved from t/t7405-submodule-merge.sh with 99% similarity]
t/t6438-submodule-directory-file-conflicts.sh [moved from t/t7613-merge-submodule.sh with 100% similarity]
t/t6439-merge-co-error-msgs.sh [moved from t/t7609-merge-co-error-msgs.sh with 100% similarity]
t/t6500-gc.sh
t/t6501-freshen-objects.sh
t/t7001-mv.sh
t/t7003-filter-branch.sh
t/t7061-wtstatus-ignore.sh
t/t7063-status-untracked-cache.sh
t/t7102-reset.sh
t/t7107-reset-pathspec-file.sh
t/t7201-co.sh
t/t7400-submodule-basic.sh
t/t7506-status-submodule.sh
t/t7508-status.sh
t/t7600-merge.sh
t/t7608-merge-messages.sh
t/t8002-blame.sh
t/t8003-blame-corner-cases.sh
t/t8011-blame-split-file.sh
t/t8014-blame-ignore-fuzzy.sh
t/t9001-send-email.sh
t/t9100-git-svn-basic.sh
t/t9300-fast-import.sh
t/t9301-fast-import-notes.sh
t/t9350-fast-export.sh
t/t9400-git-cvsserver-server.sh
t/t9401-git-cvsserver-crlf.sh
t/t9402-git-cvsserver-refs.sh
t/t9500-gitweb-standalone-no-errors.sh
t/t9700/test.pl
t/t9834-git-p4-file-dir-bug.sh
t/test-lib-functions.sh
t/test-lib.sh
tmp-objdir.c
transport-helper.c
transport-internal.h
transport.c
transport.h
tree-diff.c
tree-walk.c
unpack-trees.c
unpack-trees.h
upload-pack.c
upload-pack.h
userdiff.c
worktree.c
wt-status.c

index 84a5dcff7a05fb724d78826212c5fa22ba5df958..30425404eb3fb8bc66ebf2c16803763f5d1247d0 100644 (file)
@@ -7,34 +7,34 @@ env:
 
 jobs:
   ci-config:
-      runs-on: ubuntu-latest
-      outputs:
-        enabled: ${{ steps.check-ref.outputs.enabled }}
-      steps:
-        - name: try to clone ci-config branch
-          continue-on-error: true
-          run: |
-            git -c protocol.version=2 clone \
-              --no-tags \
-              --single-branch \
-              -b ci-config \
-              --depth 1 \
-              --no-checkout \
-              --filter=blob:none \
-              https://github.com/${{ github.repository }} \
-              config-repo &&
-              cd config-repo &&
-              git checkout HEAD -- ci/config
-        - id: check-ref
-          name: check whether CI is enabled for ref
-          run: |
-            enabled=yes
-            if test -x config-repo/ci/config/allow-ref &&
-               ! config-repo/ci/config/allow-ref '${{ github.ref }}'
-            then
-              enabled=no
-            fi
-            echo "::set-output name=enabled::$enabled"
+    runs-on: ubuntu-latest
+    outputs:
+      enabled: ${{ steps.check-ref.outputs.enabled }}
+    steps:
+      - name: try to clone ci-config branch
+        continue-on-error: true
+        run: |
+          git -c protocol.version=2 clone \
+            --no-tags \
+            --single-branch \
+            -b ci-config \
+            --depth 1 \
+            --no-checkout \
+            --filter=blob:none \
+            https://github.com/${{ github.repository }} \
+            config-repo &&
+            cd config-repo &&
+            git checkout HEAD -- ci/config
+      - id: check-ref
+        name: check whether CI is enabled for ref
+        run: |
+          enabled=yes
+          if test -x config-repo/ci/config/allow-ref &&
+             ! config-repo/ci/config/allow-ref '${{ github.ref }}'
+          then
+            enabled=no
+          fi
+          echo "::set-output name=enabled::$enabled"
 
   windows-build:
     needs: ci-config
@@ -145,13 +145,6 @@ jobs:
         ## Unzip and remove the artifact
         unzip artifacts.zip
         rm artifacts.zip
-    - name: generate Visual Studio solution
-      shell: powershell
-      run: |
-        & .\git-sdk-64-minimal\usr\bin\bash.exe -lc @"
-          make NDEBUG=1 DEVELOPER=1 vcxproj
-        "@
-        if (!$?) { exit(1) }
     - name: download vcpkg artifacts
       shell: powershell
       run: |
@@ -163,6 +156,17 @@ jobs:
         Remove-Item compat.zip
     - name: add msbuild to PATH
       uses: microsoft/setup-msbuild@v1.0.0
+    - name: copy dlls to root
+      shell: powershell
+      run: |
+        & compat\vcbuild\vcpkg_copy_dlls.bat release
+        if (!$?) { exit(1) }
+    - name: generate Visual Studio solution
+      shell: bash
+      run: |
+        cmake `pwd`/contrib/buildsystems/ -DCMAKE_PREFIX_PATH=`pwd`/compat/vcbuild/vcpkg/installed/x64-windows \
+        -DIconv_LIBRARY=`pwd`/compat/vcbuild/vcpkg/installed/x64-windows/lib/libiconv.lib -DIconv_INCLUDE_DIR=`pwd`/compat/vcbuild/vcpkg/installed/x64-windows/include \
+        -DMSGFMT_EXE=`pwd`/git-sdk-64-minimal/mingw64/bin/msgfmt.exe -DPERL_TESTS=OFF -DPYTHON_TESTS=OFF -DCURL_NO_CURL_CMAKE=ON
     - name: MSBuild
       run: msbuild git.sln -property:Configuration=Release -property:Platform=x64 -maxCpuCount:4 -property:PlatformToolset=v142
     - name: bundle artifact tar
@@ -171,8 +175,6 @@ jobs:
         MSVC: 1
         VCPKG_ROOT: ${{github.workspace}}\compat\vcbuild\vcpkg
       run: |
-        & compat\vcbuild\vcpkg_copy_dlls.bat release
-        if (!$?) { exit(1) }
         & git-sdk-64-minimal\usr\bin\bash.exe -lc @"
           mkdir -p artifacts &&
           eval \"`$(make -n artifacts-tar INCLUDE_DLLS_IN_ARTIFACTS=YesPlease ARTIFACTS_DIRECTORY=artifacts 2>&1 | grep ^tar)\"
@@ -203,7 +205,7 @@ jobs:
     - name: extract build artifacts
       shell: bash
       run: tar xf artifacts.tar.gz
-    - name: test (parallel)
+    - name: test
       shell: powershell
       env:
         MSYSTEM: MINGW64
@@ -214,12 +216,19 @@ jobs:
           # Let Git ignore the SDK and the test-cache
           printf '%s\n' /git-sdk-64-minimal/ /test-cache/ >>.git/info/exclude
 
-          cd t &&
-          PATH=\"`$PWD/helper:`$PATH\" &&
-          test-tool.exe run-command testsuite --jobs=10 -V -x --write-junit-xml \
-                  `$(test-tool.exe path-utils slice-tests \
-                          ${{matrix.nr}} 10 t[0-9]*.sh)
+          ci/run-test-slice.sh ${{matrix.nr}} 10
         "@
+    - name: ci/print-test-failures.sh
+      if: failure()
+      shell: powershell
+      run: |
+        & .\git-sdk-64-minimal\usr\bin\bash.exe -lc ci/print-test-failures.sh
+    - name: Upload failed tests' directories
+      if: failure() && env.FAILED_TEST_ARTIFACTS != ''
+      uses: actions/upload-artifact@v1
+      with:
+        name: failed-tests-windows
+        path: ${{env.FAILED_TEST_ARTIFACTS}}
   regular:
     needs: ci-config
     if: needs.ci-config.outputs.enabled == 'yes'
index ecd0b340b1c5ad0f94cabe257606016101b81c62..80d1908a44ca38058c58dcc4e3444ee96060757b 100644 (file)
@@ -17,6 +17,7 @@ MAN1_TXT += git.txt
 MAN1_TXT += gitk.txt
 MAN1_TXT += gitweb.txt
 
+# man5 / man7 guides (note: new guides should also be added to command-list.txt)
 MAN5_TXT += gitattributes.txt
 MAN5_TXT += githooks.txt
 MAN5_TXT += gitignore.txt
@@ -294,6 +295,7 @@ cmds_txt = cmds-ancillaryinterrogators.txt \
        cmds-plumbingmanipulators.txt \
        cmds-synchingrepositories.txt \
        cmds-synchelpers.txt \
+       cmds-guide.txt \
        cmds-purehelpers.txt \
        cmds-foreignscminterface.txt
 
@@ -301,7 +303,7 @@ $(cmds_txt): cmd-list.made
 
 cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT)
        $(QUIET_GEN)$(RM) $@ && \
-       $(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \
+       $(PERL_PATH) ./cmd-list.perl ../command-list.txt $(cmds_txt) $(QUIET_STDERR) && \
        date >$@
 
 mergetools_txt = mergetools-diff.txt mergetools-merge.txt
index d85c9b5143cec2f315c33886c497576e0c5591b8..4f85a089ef9d99e868dd1550992ac234e13266ff 100644 (file)
@@ -319,14 +319,14 @@ function body:
 ...
 
        git_config(git_default_config, NULL);
-       if (git_config_get_string_const("user.name", &cfg_name) > 0)
+       if (git_config_get_string_tmp("user.name", &cfg_name) > 0)
                printf(_("No name is found in config\n"));
        else
                printf(_("Your name: %s\n"), cfg_name);
 ----
 
 `git_config()` will grab the configuration from config files known to Git and
-apply standard precedence rules. `git_config_get_string_const()` will look up
+apply standard precedence rules. `git_config_get_string_tmp()` will look up
 a specific key ("user.name") and give you the value. There are a number of
 single-key lookup functions like this one; you can see them all (and more info
 about how to use `git_config()`) in `Documentation/technical/api-config.txt`.
diff --git a/Documentation/RelNotes/2.29.0.txt b/Documentation/RelNotes/2.29.0.txt
new file mode 100644 (file)
index 0000000..334e63a
--- /dev/null
@@ -0,0 +1,248 @@
+Git 2.29 Release Notes
+======================
+
+Updates since v2.28
+-------------------
+
+UI, Workflows & Features
+
+ * "git help log" has been enhanced by sharing more material from the
+   documentation for the underlying "git rev-list" command.
+
+ * "git for-each-ref --format=<>" learned %(contents:size).
+
+ * "git merge" learned to selectively omit " into <branch>" at the end
+   of the title of default merge message with merge.suppressDest
+   configuration.
+
+ * The component to respond to "git fetch" request is made more
+   configurable to selectively allow or reject object filtering
+   specification used for partial cloning.
+
+ * Stop when "sendmail.*" configuration variables are defined, which
+   could be a mistaken attempt to define "sendemail.*" variables.
+
+ * The existing backends for "git mergetool" based on variants of vim
+   have been refactored and then support for "nvim" has been added.
+
+ * "git bisect" learns the "--first-parent" option to find the first
+   breakage along the first-parent chain.
+
+ * "git log --first-parent -p" showed patches only for single-parent
+   commits on the first-parent chain; the "--first-parent" option has
+   been made to imply "-m".  Use "--no-diff-merges" to restore the
+   previous behaviour to omit patches for merge commits.
+
+ * The commit labels used to explain each side of conflicted hunks
+   placed by the sequencer machinery have been made more readable by
+   humans.
+
+ * The "--batch-size" option of "git multi-pack-index repack" command
+   is now used to specify that very small packfiles are collected into
+   one until the total size roughly exceeds it.
+
+ * The recent addition of SHA-256 support is marked as experimental in
+   the documentation.
+
+ * "git fetch" learned --no-write-fetch-head option to avoid writing
+   the FETCH_HEAD file.
+
+ * Command line completion (in contrib/) usually omits redundant,
+   deprecated and/or dangerous options from its output; it learned to
+   optionally include all of them.
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * The changed-path Bloom filter is improved using ideas from an
+   independent implementation.
+
+ * Updates to the changed-paths bloom filter.
+
+ * The test framework has been updated so that most tests will run
+   with predictable (artificial) timestamps.
+
+ * Preliminary clean-up of the refs API in preparation for adding a
+   new refs backend "reftable".
+
+ * Dev support to limit the use of test_must_fail to only git commands.
+
+ * While packing many objects in a repository with a promissor remote,
+   lazily fetching missing objects from the promissor remote one by
+   one may be inefficient---the code now attempts to fetch all the
+   missing objects in batch (obviously this won't work for a lazy
+   clone that lazily fetches tree objects as you cannot even enumerate
+   what blobs are missing until you learn which trees are missing).
+
+ * The pretend-object mechanism checks if the given object already
+   exists in the object store before deciding to keep the data
+   in-core, but the check would have triggered lazy fetching of such
+   an object from a promissor remote.
+
+ * The argv_array API is useful for not just managing argv but any
+   "vector" (NULL-terminated array) of strings, and has seen adoption
+   to a certain degree.  It has been renamed to "strvec" to reduce the
+   barrier to adoption.
+
+ * The final leg of SHA-256 transition plus doc updates.  Note that
+   there is no inter-operability between SHA-1 and SHA-256
+   repositories yet.
+
+ * CMake support to build with MSVC for Windows bypassing the Makefile.
+
+ * A new helper function has_object() has been introduced to make it
+   easier to mark object existence checks that do and don't want to
+   trigger lazy fetches, and a few such checks are converted using it.
+
+ * A no-op replacement function implemented as a C preprocessor macro
+   does not perform as good a job as one implemented as a "static
+   inline" function in catching errors in parameters; replace the
+   former with the latter in <git-compat-util.h> header.
+
+ * Test framework update.
+   (merge d572f52a64 es/test-cmp-typocatcher later to maint).
+
+ * Updates to "git merge" tests, in preparation for a new merge
+   strategy backend.
+
+ * midx and commit-graph files now use the byte defined in their file
+   format specification for identifying the hash function used for
+   object names.
+
+ * The FETCH_HEAD is now always read from the filesystem regardless of
+   the ref backend in use, as its format is much richer than the
+   normal refs, and written directly by "git fetch" as a plain file..
+
+
+Fixes since v2.28
+-----------------
+
+ * "git clone --separate-git-dir=$elsewhere" used to stomp on the
+   contents of the existing directory $elsewhere, which has been
+   taught to fail when $elsewhere is not an empty directory.
+   (merge dfaa209a79 bw/fail-cloning-into-non-empty later to maint).
+
+ * With the base fix to 2.27 regresion, any new extensions in a v0
+   repository would still be silently honored, which is not quite
+   right.  Instead, complain and die loudly.
+   (merge ec91ffca04 jk/reject-newer-extensions-in-v0 later to maint).
+
+ * Fetching from a lazily cloned repository resulted at the server
+   side in attempts to lazy fetch objects that the client side has,
+   many of which will not be available from the third-party anyway.
+   (merge 77aa0941ce jt/avoid-lazy-fetching-upon-have-check later to maint).
+
+ * Fix to an ancient bug caused by an over-eager attempt for
+   optimization.
+   (merge a98f7fb366 rs/add-index-entry-optim-fix later to maint).
+
+ * Pushing a ref whose name contains non-ASCII character with the
+   "--force-with-lease" option did not work over smart HTTP protocol,
+   which has been corrected.
+   (merge cd85b447bf bc/push-cas-cquoted-refname later to maint).
+
+ * "git mv src dst", when src is an unmerged path, errored out
+   correctly but with an incorrect error message to claim that src is
+   not tracked, which has been clarified.
+   (merge 9b906af657 ct/mv-unmerged-path-error later to maint).
+
+ * Fix to a regression introduced during 2.27 cycle.
+   (merge cada7308ad en/fill-directory-exponential later to maint).
+
+ * Command line completion (in contrib/) update.
+   (merge 688b87c81b mp/complete-show-color-moved later to maint).
+
+ * All "mergy" operations that internally use the merge-recursive
+   machinery should honor the merge.renormalize configuration, but
+   many of them didn't.
+
+ * Doc cleanup around "worktree".
+   (merge dc9c144be5 es/worktree-doc-cleanups later to maint).
+
+ * The "git blame --first-parent" option was not documented, but now
+   it is.
+   (merge 11bc12ae1e rp/blame-first-parent-doc later to maint).
+
+ * The logic to find the ref transaction hook script attempted to
+   cache the path to the found hook without realizing that it needed
+   to keep a copied value, as the API it used returned a transitory
+   buffer space.  This has been corrected.
+   (merge 09b2aa30c9 ps/ref-transaction-hook later to maint).
+
+ * Recent versions of "git diff-files" shows a diff between the index
+   and the working tree for "intent-to-add" paths as a "new file"
+   patch; "git apply --cached" should be able to take "git diff-files"
+   and should act as an equivalent to "git add" for the path, but the
+   command failed to do so for such a path.
+   (merge 4c025c667e rp/apply-cached-with-i-t-a later to maint).
+
+ * "git diff [<tree-ish>] $path" for a $path that is marked with i-t-a
+   bit was not showing the mode bits from the working tree.
+   (merge cb0dd22b82 rp/ita-diff-modefix later to maint).
+
+ * Ring buffer with size 4 used for bin-hex translation resulted in a
+   wrong object name in the sequencer's todo output, which has been
+   corrected.
+   (merge 5da69c0dac ak/sequencer-fix-find-uniq-abbrev later to maint).
+
+ * When given more than one target line ranges, "git blame -La,b
+   -Lc,d" was over-eager to coalesce groups of original lines and
+   showed incorrect results, which has been corrected.
+   (merge c2ebaa27d6 jk/blame-coalesce-fix later to maint).
+
+ * The regexp to identify the function boundary for FORTRAN programs
+   has been updated.
+   (merge 75c3b6b2e8 pb/userdiff-fortran-update later to maint).
+
+ * A few end-user facing messages have been updated to be
+   hash-algorithm agnostic.
+   (merge 4279000d3e jc/object-names-are-not-sha-1 later to maint).
+
+ * "unlink" emulation on MinGW has been optimized.
+   (merge 680e0b4524 jh/mingw-unlink later to maint).
+
+ * The purpose of "git init --separate-git-dir" is to initialize a
+   new project with the repository separate from the working tree,
+   or, in the case of an existing project, to move the repository
+   (the .git/ directory) out of the working tree. It does not make
+   sense to use --separate-git-dir with a bare repository for which
+   there is no working tree, so disallow its use with bare
+   repositories.
+   (merge ccf236a23a es/init-no-separate-git-dir-in-bare later to maint).
+
+ * "ls-files -o" mishandled the top-level directory of another git
+   working tree that hangs in the current git working tree.
+   (merge ab282aa548 en/dir-nonbare-embedded later to maint).
+
+ * Fix some incorrect UNLEAK() annotations.
+   (merge 3e19816dc0 jk/unleak-fixes later to maint).
+
+ * Use more buffered I/O where we used to call many small write(2)s.
+   (merge a698d67b08 rs/more-buffered-io later to maint).
+
+ * The patch-id computation did not ignore the "incomplete last line"
+   marker like whitespaces.
+   (merge 82a62015a7 rs/patch-id-with-incomplete-line later to maint).
+
+ * Other code cleanup, docfix, build fix, etc.
+   (merge 84544f2ea3 sk/typofixes later to maint).
+   (merge b17f411ab5 ar/help-guides-doc later to maint).
+   (merge 98c6871fad rs/grep-simpler-parse-object-or-die-call later to maint).
+   (merge 861c4ce141 en/typofixes later to maint).
+   (merge 60e47f6773 sg/ci-git-path-fix-with-pyenv later to maint).
+   (merge e2bfa50ac3 jb/doc-packfile-name later to maint).
+   (merge 918d8ff780 es/worktree-cleanup later to maint).
+   (merge dc156bc31f ma/t1450-quotefix later to maint).
+   (merge 56e743426b en/merge-recursive-comment-fixes later to maint).
+   (merge 7d23ff818f rs/bisect-oid-to-hex-fix later to maint).
+   (merge de20baf2c9 ny/notes-doc-sample-update later to maint).
+   (merge f649aaaf82 so/rev-parser-errormessage-fix later to maint).
+   (merge 6103d58b7f bc/sha-256-cvs-svn-updates later to maint).
+   (merge ac900fddb7 ma/stop-progress-null-fix later to maint).
+   (merge e767963ab6 rs/upload-pack-sigchain-fix later to maint).
+   (merge a831908599 rs/preserve-merges-unused-code-removal later to maint).
+   (merge 6dfefe70a9 jb/commit-graph-doc-fix later to maint).
+   (merge 847b37271e pb/set-url-docfix later to maint).
+   (merge 748f733d54 mt/checkout-entry-dead-code-removal later to maint).
+   (merge ce820cbd58 dl/subtree-docs later to maint).
+   (merge 55fe225dde jk/leakfix later to maint).
index 5d122db6e9e6863fcf1e69ebc14feb1393501e0b..88750af7ae19672dd1b44a6131b180acdc77ba16 100644 (file)
@@ -36,6 +36,12 @@ include::line-range-format.txt[]
        START.  `git blame --reverse START` is taken as `git blame
        --reverse START..HEAD` for convenience.
 
+--first-parent::
+       Follow only the first parent commit upon seeing a merge
+       commit. This option can be used to determine when a line
+       was introduced to a particular integration branch, rather
+       than when it was introduced to the history overall.
+
 -p::
 --porcelain::
        Show in a format designed for machine consumption.
index 5aa73cfe458d9485510c6a9a67e38e522394b62a..af5da45d2878e07ffe4586bfb8c1dc16134f9e95 100755 (executable)
@@ -6,9 +6,14 @@ sub format_one {
        my ($out, $nameattr) = @_;
        my ($name, $attr) = @$nameattr;
        my ($state, $description);
+       my $mansection;
        $state = 0;
        open I, '<', "$name.txt" or die "No such file $name.txt";
        while (<I>) {
+               if (/^git[a-z0-9-]*\(([0-9])\)$/) {
+                       $mansection = $1;
+                       next;
+               }
                if (/^NAME$/) {
                        $state = 1;
                        next;
@@ -27,7 +32,7 @@ sub format_one {
                die "No description found in $name.txt";
        }
        if (my ($verify_name, $text) = ($description =~ /^($name) - (.*)/)) {
-               print $out "linkgit:$name\[1\]::\n\t";
+               print $out "linkgit:$name\[$mansection\]::\n\t";
                if ($attr =~ / deprecated /) {
                        print $out "(deprecated) ";
                }
@@ -38,12 +43,15 @@ sub format_one {
        }
 }
 
-while (<>) {
+my ($input, @categories) = @ARGV;
+
+open IN, "<$input";
+while (<IN>) {
        last if /^### command list/;
 }
 
 my %cmds = ();
-for (sort <>) {
+for (sort <IN>) {
        next if /^#/;
 
        chomp;
@@ -51,17 +59,10 @@ for (sort <>) {
        $attr = '' unless defined $attr;
        push @{$cmds{$cat}}, [$name, " $attr "];
 }
+close IN;
 
-for my $cat (qw(ancillaryinterrogators
-               ancillarymanipulators
-               mainporcelain
-               plumbinginterrogators
-               plumbingmanipulators
-               synchingrepositories
-               foreignscminterface
-               purehelpers
-               synchelpers)) {
-       my $out = "cmds-$cat.txt";
+for my $out (@categories) {
+       my ($cat) = $out =~ /^cmds-(.*)\.txt$/;
        open O, '>', "$out+" or die "Cannot open output file $out+";
        for (@{$cmds{$cat}}) {
                format_one(\*O, $_);
index ef0768b91a02cafdcb6044dba0169a5092bbd913..3042d80978d6158f827fa1ea272edb7d2b2d571b 100644 (file)
@@ -348,6 +348,8 @@ include::config/diff.txt[]
 
 include::config/difftool.txt[]
 
+include::config/extensions.txt[]
+
 include::config/fastimport.txt[]
 
 include::config/feature.txt[]
diff --git a/Documentation/config/extensions.txt b/Documentation/config/extensions.txt
new file mode 100644 (file)
index 0000000..4e23d73
--- /dev/null
@@ -0,0 +1,8 @@
+extensions.objectFormat::
+       Specify the hash algorithm to use.  The acceptable values are `sha1` and
+       `sha256`.  If not specified, `sha1` is assumed.  It is an error to specify
+       this key unless `core.repositoryFormatVersion` is 1.
++
+Note that this setting should only be set by linkgit:git-init[1] or
+linkgit:git-clone[1].  Trying to change it after initialization will not
+work and will produce hard-to-diagnose issues.
index c73cfa90b70c59c14cd4984c950711bef5b3f6bf..a8e8f74d0a25e6b857358cc78864c288d8fc4cfa 100644 (file)
@@ -8,3 +8,15 @@ merge.log::
        most the specified number of one-line descriptions from the
        actual commits that are being merged.  Defaults to false, and
        true is a synonym for 20.
+
+merge.suppressDest::
+       By adding a glob that matches the names of integration
+       branches to this multi-valued configuration variable, the
+       default merge message computed for merges into these
+       integration branches will omit " into <branch name>" from
+       its title.
++
+An element with an empty value can be used to clear the list
+of globs accumulated from previous configuration entries.
+When there is no `merge.suppressDest` variable defined, the
+default value of `master` is used for backward compatibility.
index 0006faf800ae69cd4ee3cde99b5e661e06ae6893..cbc5af42fdf05c1d9450c55a4342c58714e9a766 100644 (file)
@@ -61,3 +61,8 @@ sendemail.smtpBatchSize::
 sendemail.smtpReloginDelay::
        Seconds wait before reconnecting to smtp server.
        See also the `--relogin-delay` option of linkgit:git-send-email[1].
+
+sendemail.forbidSendmailVariables::
+       To avoid common misconfiguration mistakes, linkgit:git-send-email[1]
+       will abort with a warning if any configuration options for "sendmail"
+       exist. Set this variable to bypass the check.
index ed1c835695c3cf2a9058163b19bef7070695113f..ee7b3ac94f82e4376d06d63c9a09d9370b10a34c 100644 (file)
@@ -57,6 +57,24 @@ uploadpack.allowFilter::
        If this option is set, `upload-pack` will support partial
        clone and partial fetch object filtering.
 
+uploadpackfilter.allow::
+       Provides a default value for unspecified object filters (see: the
+       below configuration variable).
+       Defaults to `true`.
+
+uploadpackfilter.<filter>.allow::
+       Explicitly allow or ban the object filter corresponding to
+       `<filter>`, where `<filter>` may be one of: `blob:none`,
+       `blob:limit`, `tree`, `sparse:oid`, or `combine`. If using
+       combined filters, both `combine` and all of the nested filter
+       kinds must be allowed. Defaults to `uploadpackfilter.allow`.
+
+uploadpackfilter.tree.maxDepth::
+       Only allow `--filter=tree=<n>` when `n` is no more than the value of
+       `uploadpackfilter.tree.maxDepth`. If set, this also implies
+       `uploadpackfilter.tree.allow=true`, unless this configuration
+       variable had already been set. Has no effect if unset.
+
 uploadpack.allowRefInWant::
        If this option is set, `upload-pack` will support the `ref-in-want`
        feature of the protocol version 2 `fetch` command.  This feature
index 7987d72b0212e1247ff5ea14b553d4a322c1f5f5..573fb9bb71e2b7df1062258289a0af308c50bf5b 100644 (file)
@@ -73,6 +73,11 @@ ifndef::git-format-patch[]
        Synonym for `-p --raw`.
 endif::git-format-patch[]
 
+ifdef::git-log[]
+-t::
+       Show the tree objects in the diff output.
+endif::git-log[]
+
 --indent-heuristic::
        Enable the heuristic that shifts diff hunk boundaries to make patches
        easier to read. This is the default.
@@ -441,10 +446,11 @@ endif::git-format-patch[]
 --abbrev[=<n>]::
        Instead of showing the full 40-byte hexadecimal object
        name in diff-raw format output and diff-tree header
-       lines, show only a partial prefix.  This is
-       independent of the `--full-index` option above, which controls
-       the diff-patch output format.  Non default number of
-       digits can be specified with `--abbrev=<n>`.
+       lines, show only a partial prefix.
+       In diff-patch output format, `--full-index` takes higher
+       precedence, i.e. if `--full-index` is specified, full blob
+       names will be shown regardless of `--abbrev`.
+       Non default number of digits can be specified with `--abbrev=<n>`.
 
 -B[<n>][/<m>]::
 --break-rewrites[=[<n>][/<m>]]::
index 6e2a160a47cb8c07a72600d2fc7ad404bf2bc1c1..e8104c082ed16e3829e39f10be211d16e7c81510 100644 (file)
@@ -64,6 +64,15 @@ documented in linkgit:git-config[1].
 --dry-run::
        Show what would be done, without making any changes.
 
+ifndef::git-pull[]
+--[no-]write-fetch-head::
+       Write the list of remote refs fetched in the `FETCH_HEAD`
+       file directly under `$GIT_DIR`.  This is the default.
+       Passing `--no-write-fetch-head` from the command line tells
+       Git not to write the file.  Under `--dry-run` option, the
+       file is never written.
+endif::git-pull[]
+
 -f::
 --force::
        When 'git fetch' is used with `<src>:<dst>` refspec it may
@@ -186,7 +195,7 @@ ifndef::git-pull[]
 endif::git-pull[]
 
 --set-upstream::
-       If the remote is fetched successfully, pull and add upstream
+       If the remote is fetched successfully, add upstream
        (tracking) reference, used by argument-less
        linkgit:git-pull[1] and other commands. For more information,
        see `branch.<name>.merge` and `branch.<name>.remote` in
index 7586c5a8437edfc146fa3b802bc5e72e5070ee9a..0e993e458717743e4e2f136d27f7291101853bba 100644 (file)
@@ -17,7 +17,7 @@ The command takes various subcommands, and different options depending
 on the subcommand:
 
  git bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>]
-                 [--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
+                 [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]
  git bisect (bad|new|<term-new>) [<rev>]
  git bisect (good|old|<term-old>) [<rev>...]
  git bisect terms [--term-good | --term-bad]
@@ -365,6 +365,17 @@ does not require a checked out tree.
 +
 If the repository is bare, `--no-checkout` is assumed.
 
+--first-parent::
++
+Follow only the first parent commit upon seeing a merge commit.
++
+In detecting regressions introduced through the merging of a branch, the merge
+commit will be identified as introduction of the bug and its ancestors will be
+ignored.
++
+This option is particularly useful in avoiding false positives when a merged
+branch contained broken or non-buildable commits, but the merge itself was OK.
+
 EXAMPLES
 --------
 
index d34b0964be17b88ae6798aed46ca518a97aceea1..53804cad4b67fdc3898ff008d737517c4928e7da 100644 (file)
@@ -9,7 +9,8 @@ git-bundle - Move objects and refs by archive
 SYNOPSIS
 --------
 [verse]
-'git bundle' create [-q | --quiet | --progress | --all-progress] [--all-progress-implied] <file> <git-rev-list-args>
+'git bundle' create [-q | --quiet | --progress | --all-progress] [--all-progress-implied]
+                   [--version=<version>] <file> <git-rev-list-args>
 'git bundle' verify [-q | --quiet] <file>
 'git bundle' list-heads <file> [<refname>...]
 'git bundle' unbundle <file> [<refname>...]
@@ -102,6 +103,12 @@ unbundle <file>::
        is activated.  Unlike --all-progress this flag doesn't actually
        force any progress display by itself.
 
+--version=<version>::
+       Specify the bundle version.  Version 2 is the older format and can only be
+       used with SHA-1 repositories; the newer version 3 contains capabilities that
+       permit extensions. The default is the oldest supported format, based on the
+       hash algorithm in use.
+
 -q::
 --quiet::
        This flag makes the command not to report its progress
index 8ca1764d3dcab4f37abe9f5e92dddb0d822b47f4..17405c73a98e8a80bf0b45b2a730aee2693f8614 100644 (file)
@@ -62,7 +62,10 @@ existing commit-graph file.
 With the `--changed-paths` option, compute and write information about the
 paths changed between a commit and its first parent. This operation can
 take a while on large repositories. It provides significant performance gains
-for getting history of a directory or a file with `git log -- <path>`.
+for getting history of a directory or a file with `git log -- <path>`. If
+this option is given, future commit-graph writes will automatically assume
+that this option was intended. Use `--no-changed-paths` to stop storing this
+data.
 +
 With the `--split[=<strategy>]` option, write the commit-graph as a
 chain of multiple commit-graph files stored in
index 6dcd39f6f63dca79f7bc324874e3a4a6172bb688..2ea71c5f6c2c14ff6c0bda87f63f2b14b895d00b 100644 (file)
@@ -232,12 +232,27 @@ Fields that have name-email-date tuple as its value (`author`,
 `committer`, and `tagger`) can be suffixed with `name`, `email`,
 and `date` to extract the named component.
 
-The complete message in a commit and tag object is `contents`.
-Its first line is `contents:subject`, where subject is the concatenation
-of all lines of the commit message up to the first blank line.  The next
-line is `contents:body`, where body is all of the lines after the first
-blank line.  The optional GPG signature is `contents:signature`.  The
-first `N` lines of the message is obtained using `contents:lines=N`.
+The message in a commit or a tag object is `contents`, from which
+`contents:<part>` can be used to extract various parts out of:
+
+contents:size::
+       The size in bytes of the commit or tag message.
+
+contents:subject::
+       The first paragraph of the message, which typically is a
+       single line, is taken as the "subject" of the commit or the
+       tag message.
+
+contents:body::
+       The remainder of the commit or the tag message that follows
+       the "subject".
+
+contents:signature::
+       The optional GPG signature of the tag.
+
+contents:lines=N::
+       The first `N` lines of the message.
+
 Additionally, the trailers as interpreted by linkgit:git-interpret-trailers[1]
 are obtained as `trailers` (or by using the historical alias
 `contents:trailers`).  Non-trailer lines from the trailer block can be omitted
index f71db0daa24358e8589281d06ee48e7cd877bca8..44fe8860b3f17bcb64d5d90ed22b6f8898ca93fa 100644 (file)
@@ -8,7 +8,7 @@ git-help - Display help information about Git
 SYNOPSIS
 --------
 [verse]
-'git help' [-a|--all [--[no-]verbose]] [-g|--guide]
+'git help' [-a|--all [--[no-]verbose]] [-g|--guides]
           [-i|--info|-m|--man|-w|--web] [COMMAND|GUIDE]
 
 DESCRIPTION
@@ -21,8 +21,8 @@ on the standard output.
 If the option `--all` or `-a` is given, all available commands are
 printed on the standard output.
 
-If the option `--guide` or `-g` is given, a list of the useful
-Git guides is also printed on the standard output.
+If the option `--guides` or `-g` is given, a list of the
+Git concept guides is also printed on the standard output.
 
 If a command, or a guide, is given, a manual page for that command or
 guide is brought up. The 'man' program is used by default for this
@@ -58,7 +58,7 @@ OPTIONS
 
 -g::
 --guides::
-       Prints a list of useful guides on the standard output. This
+       Prints a list of the Git concept guides on the standard output. This
        option overrides any given command or guide name.
 
 -i::
index 9316d9a80b0d7bb5f83f80400585fe7cb22dc723..af0c26232c1e775cf5f4d56ee67c07b6a73a9104 100644 (file)
@@ -100,12 +100,14 @@ OPTIONS
        value is set or outside a repository.
 +
 This option cannot be used with --stdin.
++
+include::object-format-disclaimer.txt[]
 
 NOTES
 -----
 
-Once the index has been created, the list of object names is sorted
-and the SHA-1 hash of that list is printed to stdout. If --stdin was
+Once the index has been created, the hash that goes into the name of
+the pack/idx file is printed to stdout. If --stdin was
 also used then this is prefixed by either "pack\t", or "keep\t" if a
 new .keep file was successfully created. This is useful to remove a
 .keep file used as a lock to prevent the race with 'git repack'
index ddfe265da5b6524f30d972bfea990bb2a89b5611..f35f70f13d0385e24ba2c0727e3720b4a068a048 100644 (file)
@@ -53,6 +53,8 @@ current working directory.
 
 Specify the given object format (hash algorithm) for the repository.  The valid
 values are 'sha1' and (if enabled) 'sha256'.  'sha1' is the default.
++
+include::object-format-disclaimer.txt[]
 
 --template=<template_directory>::
 
index 20e6d21a74abcd354dbad38ab55e82dd6a3fd869..2b8ac5ff882ae84d52d08458c2439f314d2a0370 100644 (file)
@@ -15,9 +15,12 @@ DESCRIPTION
 -----------
 Shows the commit logs.
 
-The command takes options applicable to the `git rev-list`
+:git-log: 1
+include::rev-list-description.txt[]
+
+The command takes options applicable to the linkgit:git-rev-list[1]
 command to control what is shown and how, and options applicable to
-the `git diff-*` commands to control how the changes
+the linkgit:git-diff[1] command to control how the changes
 each commit introduces are shown.
 
 
@@ -111,8 +114,51 @@ include::rev-list-options.txt[]
 
 include::pretty-formats.txt[]
 
-COMMON DIFF OPTIONS
--------------------
+DIFF FORMATTING
+---------------
+
+By default, `git log` does not generate any diff output. The options
+below can be used to show the changes made by each commit.
+
+Note that unless one of `-c`, `--cc`, or `-m` is given, merge commits
+will never show a diff, even if a diff format like `--patch` is
+selected, nor will they match search options like `-S`. The exception is
+when `--first-parent` is in use, in which merges are treated like normal
+single-parent commits (this can be overridden by providing a
+combined-diff option or with `--no-diff-merges`).
+
+-c::
+       With this option, diff output for a merge commit
+       shows the differences from each of the parents to the merge result
+       simultaneously instead of showing pairwise diff between a parent
+       and the result one at a time. Furthermore, it lists only files
+       which were modified from all parents.
+
+--cc::
+       This flag implies the `-c` option and further compresses the
+       patch output by omitting uninteresting hunks whose contents in
+       the parents have only two variants and the merge result picks
+       one of them without modification.
+
+--combined-all-paths::
+       This flag causes combined diffs (used for merge commits) to
+       list the name of the file from all parents.  It thus only has
+       effect when -c or --cc are specified, and is likely only
+       useful if filename changes are detected (i.e. when either
+       rename or copy detection have been requested).
+
+-m::
+       This flag makes the merge commits show the full diff like
+       regular commits; for each merge parent, a separate log entry
+       and diff is generated. An exception is that only diff against
+       the first parent is shown when `--first-parent` option is given;
+       in that case, the output represents the changes the merge
+       brought _into_ the then-current branch.
+
+--diff-merges=off::
+--no-diff-merges::
+       Disable output of diffs for merge commits (default). Useful to
+       override `-m`, `-c`, or `--cc`.
 
 :git-log: 1
 include::diff-options.txt[]
index 0c6619493c1eddd92323c620e4ae374a7c6a4b91..eb0caa04393a7136e125c95038b6b740bc215086 100644 (file)
@@ -51,11 +51,12 @@ repack::
        multi-pack-index, then divide by the total number of objects in
        the pack and multiply by the pack size. We select packs with
        expected size below the batch size until the set of packs have
-       total expected size at least the batch size. If the total size
-       does not reach the batch size, then do nothing. If a new pack-
-       file is created, rewrite the multi-pack-index to reference the
-       new pack-file. A later run of 'git multi-pack-index expire' will
-       delete the pack-files that were part of this batch.
+       total expected size at least the batch size, or all pack-files
+       are considered. If only one pack-file is selected, then do
+       nothing. If a new pack-file is created, rewrite the
+       multi-pack-index to reference the new pack-file. A later run of
+       'git multi-pack-index expire' will delete the pack-files that
+       were part of this batch.
 +
 If `repack.packKeptObjects` is `false`, then any pack-files with an
 associated `.keep` file will not be selected for the batch to repack.
index ced2e8280ef5e4c4c930fd1abdab83834c293140..0a4200674c40af473d135ccd5df129f28a684864 100644 (file)
@@ -223,7 +223,7 @@ are taken from notes refs.  A notes ref is usually a branch which
 contains "files" whose paths are the object names for the objects
 they describe, with some directory separators included for performance
 reasons footnote:[Permitted pathnames have the form
-'ab'`/`'cd'`/`'ef'`/`'...'`/`'abcdef...': a sequence of directory
+'bf'`/`'fe'`/`'30'`/`'...'`/`'680d5a...': a sequence of directory
 names of two hexadecimal digits each followed by a filename with the
 rest of the object ID.].
 
index eaa2f2a4041f2eed78aea08131b1120fb195aaf7..54d715ead1373d0feb4eee512fbe8ea8b446216c 100644 (file)
@@ -270,15 +270,18 @@ So does `git bundle` (see linkgit:git-bundle[1]) when it creates a bundle.
        This option specifies how missing objects are handled.
 +
 The form '--missing=error' requests that pack-objects stop with an error if
-a missing object is encountered.  This is the default action.
+a missing object is encountered.  If the repository is a partial clone, an
+attempt to fetch missing objects will be made before declaring them missing.
+This is the default action.
 +
 The form '--missing=allow-any' will allow object traversal to continue
-if a missing object is encountered.  Missing objects will silently be
-omitted from the results.
+if a missing object is encountered.  No fetch of a missing object will occur.
+Missing objects will silently be omitted from the results.
 +
 The form '--missing=allow-promisor' is like 'allow-any', but will only
 allow object traversal to continue for EXPECTED promisor missing objects.
-Unexpected missing object will raise an error.
+No fetch of a missing object will occur.  An unexpected missing object will
+raise an error.
 
 --exclude-promisor-objects::
        Omit objects that are known to be in the promisor remote.  (This
index 025c9114365682cab4feb345c3a69beb5900d299..5da66232dc3f7b21106cdeba55cc1d94bce04393 100644 (file)
@@ -14,44 +14,8 @@ SYNOPSIS
 DESCRIPTION
 -----------
 
-List commits that are reachable by following the `parent` links from the
-given commit(s), but exclude commits that are reachable from the one(s)
-given with a '{caret}' in front of them.  The output is given in reverse
-chronological order by default.
-
-You can think of this as a set operation.  Commits given on the command
-line form a set of commits that are reachable from any of them, and then
-commits reachable from any of the ones given with '{caret}' in front are
-subtracted from that set.  The remaining commits are what comes out in the
-command's output.  Various other options and paths parameters can be used
-to further limit the result.
-
-Thus, the following command:
-
------------------------------------------------------------------------
-       $ git rev-list foo bar ^baz
------------------------------------------------------------------------
-
-means "list all the commits which are reachable from 'foo' or 'bar', but
-not from 'baz'".
-
-A special notation "'<commit1>'..'<commit2>'" can be used as a
-short-hand for "{caret}'<commit1>' '<commit2>'". For example, either of
-the following may be used interchangeably:
-
------------------------------------------------------------------------
-       $ git rev-list origin..HEAD
-       $ git rev-list HEAD ^origin
------------------------------------------------------------------------
-
-Another special notation is "'<commit1>'...'<commit2>'" which is useful
-for merges.  The resulting set of commits is the symmetric difference
-between the two operands.  The following two commands are equivalent:
-
------------------------------------------------------------------------
-       $ git rev-list A B --not $(git merge-base --all A B)
-       $ git rev-list A...B
------------------------------------------------------------------------
+:git-rev-list: 1
+include::rev-list-description.txt[]
 
 'rev-list' is a very essential Git command, since it
 provides the ability to build and traverse commit ancestry graphs. For
index 39b1d8eaa1456f60af07de2e30f0653f9d5efd64..e49318a5a0aec7f46c6d23dbff5afcb920fae236 100644 (file)
@@ -44,6 +44,8 @@ OPTIONS
        valid values are 'sha1' and (if enabled) 'sha256'.  The default is the
        algorithm for the current repository (set by `extensions.objectFormat`), or
        'sha1' if no value is set or outside a repository..
++
+include::object-format-disclaimer.txt[]
 
 GIT
 ---
index 3e737c236074849377e3766c55f4533a270c436f..d401234b03ce85722ff9624acb16c125d3780b27 100644 (file)
@@ -148,12 +148,13 @@ still see a subset of the modifications.
 
 LOGGING UPDATES
 ---------------
-If config parameter "core.logAllRefUpdates" is true and the ref is one under
-"refs/heads/", "refs/remotes/", "refs/notes/", or the symbolic ref HEAD; or
-the file "$GIT_DIR/logs/<ref>" exists then `git update-ref` will append
-a line to the log file "$GIT_DIR/logs/<ref>" (dereferencing all
-symbolic refs before creating the log name) describing the change
-in ref value.  Log lines are formatted as:
+If config parameter "core.logAllRefUpdates" is true and the ref is one
+under "refs/heads/", "refs/remotes/", "refs/notes/", or a pseudoref
+like HEAD or ORIG_HEAD; or the file "$GIT_DIR/logs/<ref>" exists then
+`git update-ref` will append a line to the log file
+"$GIT_DIR/logs/<ref>" (dereferencing all symbolic refs before creating
+the log name) describing the change in ref value.  Log lines are
+formatted as:
 
     oldsha1 SP newsha1 SP committer LF
 
index 4796c3c05ef7e55d883f6db03767d9953c97e6da..6ee6ec79824a6a8e43d2411b9226c72a49d52c9e 100644 (file)
@@ -25,8 +25,9 @@ Manage multiple working trees attached to the same repository.
 A git repository can support multiple working trees, allowing you to check
 out more than one branch at a time.  With `git worktree add` a new working
 tree is associated with the repository.  This new working tree is called a
-"linked working tree" as opposed to the "main working tree" prepared by "git
-init" or "git clone".  A repository has one main working tree (if it's not a
+"linked working tree" as opposed to the "main working tree" prepared by
+linkgit:git-init[1] or linkgit:git-clone[1].
+A repository has one main working tree (if it's not a
 bare repository) and zero or more linked working trees. When you are done
 with a linked working tree, remove it with `git worktree remove`.
 
@@ -48,10 +49,10 @@ add <path> [<commit-ish>]::
 
 Create `<path>` and checkout `<commit-ish>` into it. The new working directory
 is linked to the current repository, sharing everything except working
-directory specific files such as HEAD, index, etc. `-` may also be
-specified as `<commit-ish>`; it is synonymous with `@{-1}`.
+directory specific files such as `HEAD`, `index`, etc. As a convenience,
+`<commit-ish>` may be a bare "`-`", which is synonymous with `@{-1}`.
 +
-If <commit-ish> is a branch name (call it `<branch>`) and is not found,
+If `<commit-ish>` is a branch name (call it `<branch>`) and is not found,
 and neither `-b` nor `-B` nor `--detach` are used, but there does
 exist a tracking branch in exactly one remote (call it `<remote>`)
 with a matching name, treat as equivalent to:
@@ -66,24 +67,24 @@ one for the purposes of disambiguation, even if the `<branch>` isn't
 unique across all remotes. Set it to
 e.g. `checkout.defaultRemote=origin` to always checkout remote
 branches from there if `<branch>` is ambiguous but exists on the
-'origin' remote. See also `checkout.defaultRemote` in
+`origin` remote. See also `checkout.defaultRemote` in
 linkgit:git-config[1].
 +
 If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,
-then, as a convenience, the new worktree is associated with a branch
+then, as a convenience, the new working tree is associated with a branch
 (call it `<branch>`) named after `$(basename <path>)`.  If `<branch>`
-doesn't exist, a new branch based on HEAD is automatically created as
+doesn't exist, a new branch based on `HEAD` is automatically created as
 if `-b <branch>` was given.  If `<branch>` does exist, it will be
-checked out in the new worktree, if it's not checked out anywhere
-else, otherwise the command will refuse to create the worktree (unless
+checked out in the new working tree, if it's not checked out anywhere
+else, otherwise the command will refuse to create the working tree (unless
 `--force` is used).
 
 list::
 
-List details of each worktree.  The main worktree is listed first, followed by
-each of the linked worktrees.  The output details include if the worktree is
-bare, the revision currently checked out, and the branch currently checked out
-(or 'detached HEAD' if none).
+List details of each working tree.  The main working tree is listed first,
+followed by each of the linked working trees.  The output details include
+whether the working tree is bare, the revision currently checked out, and the
+branch currently checked out (or "detached HEAD" if none).
 
 lock::
 
@@ -100,7 +101,7 @@ or linked working trees containing submodules cannot be moved.
 
 prune::
 
-Prune working tree information in $GIT_DIR/worktrees.
+Prune working tree information in `$GIT_DIR/worktrees`.
 
 remove::
 
@@ -128,7 +129,7 @@ OPTIONS
 `move` refuses to move a locked working tree unless `--force` is specified
 twice. If the destination is already assigned to some other working tree but is
 missing (for instance, if `<new-path>` was deleted manually), then `--force`
-allows the move to proceed; use --force twice if the destination is locked.
+allows the move to proceed; use `--force` twice if the destination is locked.
 +
 `remove` refuses to remove an unclean working tree unless `--force` is used.
 To remove a locked working tree, specify `--force` twice.
@@ -137,13 +138,13 @@ To remove a locked working tree, specify `--force` twice.
 -B <new-branch>::
        With `add`, create a new branch named `<new-branch>` starting at
        `<commit-ish>`, and check out `<new-branch>` into the new working tree.
-       If `<commit-ish>` is omitted, it defaults to HEAD.
+       If `<commit-ish>` is omitted, it defaults to `HEAD`.
        By default, `-b` refuses to create a new branch if it already
        exists. `-B` overrides this safeguard, resetting `<new-branch>` to
        `<commit-ish>`.
 
 --detach::
-       With `add`, detach HEAD in the new working tree. See "DETACHED HEAD"
+       With `add`, detach `HEAD` in the new working tree. See "DETACHED HEAD"
        in linkgit:git-checkout[1].
 
 --[no-]checkout::
@@ -154,7 +155,7 @@ To remove a locked working tree, specify `--force` twice.
 
 --[no-]guess-remote::
        With `worktree add <path>`, without `<commit-ish>`, instead
-       of creating a new branch from HEAD, if there exists a tracking
+       of creating a new branch from `HEAD`, if there exists a tracking
        branch in exactly one remote matching the basename of `<path>`,
        base the new branch on the remote-tracking branch, and mark
        the remote-tracking branch as "upstream" from the new branch.
@@ -166,12 +167,12 @@ This can also be set up as the default behaviour by using the
        When creating a new branch, if `<commit-ish>` is a branch,
        mark it as "upstream" from the new branch.  This is the
        default if `<commit-ish>` is a remote-tracking branch.  See
-       "--track" in linkgit:git-branch[1] for details.
+       `--track` in linkgit:git-branch[1] for details.
 
 --lock::
        Keep the working tree locked after creation. This is the
        equivalent of `git worktree lock` after `git worktree add`,
-       but without race condition.
+       but without race condition.
 
 -n::
 --dry-run::
@@ -185,14 +186,14 @@ This can also be set up as the default behaviour by using the
 
 -q::
 --quiet::
-       With 'add', suppress feedback messages.
+       With `add`, suppress feedback messages.
 
 -v::
 --verbose::
        With `prune`, report all removals.
 
 --expire <time>::
-       With `prune`, only expire unused working trees older than <time>.
+       With `prune`, only expire unused working trees older than `<time>`.
 
 --reason <string>::
        With `lock`, an explanation why the working tree is locked.
@@ -202,48 +203,48 @@ This can also be set up as the default behaviour by using the
        absolute.
 +
 If the last path components in the working tree's path is unique among
-working trees, it can be used to identify worktrees. For example if
-you only have two working trees, at "/abc/def/ghi" and "/abc/def/ggg",
-then "ghi" or "def/ghi" is enough to point to the former working tree.
+working trees, it can be used to identify a working tree. For example if
+you only have two working trees, at `/abc/def/ghi` and `/abc/def/ggg`,
+then `ghi` or `def/ghi` is enough to point to the former working tree.
 
 REFS
 ----
 In multiple working trees, some refs may be shared between all working
-trees, some refs are local. One example is HEAD is different for all
-working trees. This section is about the sharing rules and how to access
+trees and some refs are local. One example is `HEAD` which is different for each
+working tree. This section is about the sharing rules and how to access
 refs of one working tree from another.
 
 In general, all pseudo refs are per working tree and all refs starting
-with "refs/" are shared. Pseudo refs are ones like HEAD which are
-directly under GIT_DIR instead of inside GIT_DIR/refs. There is one
-exception to this: refs inside refs/bisect and refs/worktree is not
+with `refs/` are shared. Pseudo refs are ones like `HEAD` which are
+directly under `$GIT_DIR` instead of inside `$GIT_DIR/refs`. There are
+exceptions, however: refs inside `refs/bisect` and `refs/worktree` are not
 shared.
 
 Refs that are per working tree can still be accessed from another
-working tree via two special paths, main-worktree and worktrees. The
-former gives access to per-worktree refs of the main working tree,
+working tree via two special paths, `main-worktree` and `worktrees`. The
+former gives access to per-working tree refs of the main working tree,
 while the latter to all linked working trees.
 
-For example, main-worktree/HEAD or main-worktree/refs/bisect/good
-resolve to the same value as the main working tree's HEAD and
-refs/bisect/good respectively. Similarly, worktrees/foo/HEAD or
-worktrees/bar/refs/bisect/bad are the same as
-GIT_COMMON_DIR/worktrees/foo/HEAD and
-GIT_COMMON_DIR/worktrees/bar/refs/bisect/bad.
+For example, `main-worktree/HEAD` or `main-worktree/refs/bisect/good`
+resolve to the same value as the main working tree's `HEAD` and
+`refs/bisect/good` respectively. Similarly, `worktrees/foo/HEAD` or
+`worktrees/bar/refs/bisect/bad` are the same as
+`$GIT_COMMON_DIR/worktrees/foo/HEAD` and
+`$GIT_COMMON_DIR/worktrees/bar/refs/bisect/bad`.
 
-To access refs, it's best not to look inside GIT_DIR directly. Instead
+To access refs, it's best not to look inside `$GIT_DIR` directly. Instead
 use commands such as linkgit:git-rev-parse[1] or linkgit:git-update-ref[1]
 which will handle refs correctly.
 
 CONFIGURATION FILE
 ------------------
-By default, the repository "config" file is shared across all working
+By default, the repository `config` file is shared across all working
 trees. If the config variables `core.bare` or `core.worktree` are
 already present in the config file, they will be applied to the main
 working trees only.
 
 In order to have configuration specific to working trees, you can turn
-on "worktreeConfig" extension, e.g.:
+on the `worktreeConfig` extension, e.g.:
 
 ------------
 $ git config extensions.worktreeConfig true
@@ -255,7 +256,7 @@ configuration in this file with `git config --worktree`. Older Git
 versions will refuse to access repositories with this extension.
 
 Note that in this file, the exception for `core.bare` and `core.worktree`
-is gone. If you have them in $GIT_DIR/config before, you must move
+is gone. If they exist in `$GIT_DIR/config`, you must move
 them to the `config.worktree` of the main working tree. You may also
 take this opportunity to review and move other configuration that you
 do not want to share to all working trees:
@@ -268,7 +269,7 @@ do not want to share to all working trees:
 DETAILS
 -------
 Each linked working tree has a private sub-directory in the repository's
-$GIT_DIR/worktrees directory.  The private sub-directory's name is usually
+`$GIT_DIR/worktrees` directory.  The private sub-directory's name is usually
 the base name of the linked working tree's path, possibly appended with a
 number to make it unique.  For example, when `$GIT_DIR=/path/main/.git` the
 command `git worktree add /path/other/test-next next` creates the linked
@@ -276,51 +277,51 @@ working tree in `/path/other/test-next` and also creates a
 `$GIT_DIR/worktrees/test-next` directory (or `$GIT_DIR/worktrees/test-next1`
 if `test-next` is already taken).
 
-Within a linked working tree, $GIT_DIR is set to point to this private
+Within a linked working tree, `$GIT_DIR` is set to point to this private
 directory (e.g. `/path/main/.git/worktrees/test-next` in the example) and
-$GIT_COMMON_DIR is set to point back to the main working tree's $GIT_DIR
+`$GIT_COMMON_DIR` is set to point back to the main working tree's `$GIT_DIR`
 (e.g. `/path/main/.git`). These settings are made in a `.git` file located at
 the top directory of the linked working tree.
 
 Path resolution via `git rev-parse --git-path` uses either
-$GIT_DIR or $GIT_COMMON_DIR depending on the path. For example, in the
+`$GIT_DIR` or `$GIT_COMMON_DIR` depending on the path. For example, in the
 linked working tree `git rev-parse --git-path HEAD` returns
 `/path/main/.git/worktrees/test-next/HEAD` (not
 `/path/other/test-next/.git/HEAD` or `/path/main/.git/HEAD`) while `git
 rev-parse --git-path refs/heads/master` uses
-$GIT_COMMON_DIR and returns `/path/main/.git/refs/heads/master`,
-since refs are shared across all working trees, except refs/bisect and
-refs/worktree.
+`$GIT_COMMON_DIR` and returns `/path/main/.git/refs/heads/master`,
+since refs are shared across all working trees, except `refs/bisect` and
+`refs/worktree`.
 
 See linkgit:gitrepository-layout[5] for more information. The rule of
 thumb is do not make any assumption about whether a path belongs to
-$GIT_DIR or $GIT_COMMON_DIR when you need to directly access something
-inside $GIT_DIR. Use `git rev-parse --git-path` to get the final path.
+`$GIT_DIR` or `$GIT_COMMON_DIR` when you need to directly access something
+inside `$GIT_DIR`. Use `git rev-parse --git-path` to get the final path.
 
-If you manually move a linked working tree, you need to update the 'gitdir' file
+If you manually move a linked working tree, you need to update the `gitdir` file
 in the entry's directory. For example, if a linked working tree is moved
 to `/newpath/test-next` and its `.git` file points to
 `/path/main/.git/worktrees/test-next`, then update
 `/path/main/.git/worktrees/test-next/gitdir` to reference `/newpath/test-next`
 instead.
 
-To prevent a $GIT_DIR/worktrees entry from being pruned (which
+To prevent a `$GIT_DIR/worktrees` entry from being pruned (which
 can be useful in some situations, such as when the
 entry's working tree is stored on a portable device), use the
 `git worktree lock` command, which adds a file named
-'locked' to the entry's directory. The file contains the reason in
+`locked` to the entry's directory. The file contains the reason in
 plain text. For example, if a linked working tree's `.git` file points
 to `/path/main/.git/worktrees/test-next` then a file named
 `/path/main/.git/worktrees/test-next/locked` will prevent the
 `test-next` entry from being pruned.  See
 linkgit:gitrepository-layout[5] for details.
 
-When extensions.worktreeConfig is enabled, the config file
+When `extensions.worktreeConfig` is enabled, the config file
 `.git/worktrees/<id>/config.worktree` is read after `.git/config` is.
 
 LIST OUTPUT FORMAT
 ------------------
-The worktree list command has two output formats.  The default format shows the
+The `worktree list` command has two output formats. The default format shows the
 details on a single line with columns.  For example:
 
 ------------
@@ -333,10 +334,10 @@ $ git worktree list
 Porcelain Format
 ~~~~~~~~~~~~~~~~
 The porcelain format has a line per attribute.  Attributes are listed with a
-label and value separated by a single space.  Boolean attributes (like 'bare'
-and 'detached') are listed as a label only, and are only present if and only
-if the value is true.  The first attribute of a worktree is always `worktree`,
-an empty line indicates the end of the record.  For example:
+label and value separated by a single space.  Boolean attributes (like `bare`
+and `detached`) are listed as a label only, and are present only
+if the value is true.  The first attribute of a working tree is always
+`worktree`, an empty line indicates the end of the record.  For example:
 
 ------------
 $ git worktree list --porcelain
index 3e50065198891b8f889d7905d8e0573ca791f02f..2fc92586b52386c770bed28a11275c64eea3414a 100644 (file)
@@ -304,6 +304,13 @@ users typically do not use them directly.
 
 include::cmds-purehelpers.txt[]
 
+Guides
+------
+
+The following documentation pages are guides about Git concepts.
+
+include::cmds-guide.txt[]
+
 
 Configuration Mechanism
 -----------------------
@@ -497,7 +504,8 @@ double-quotes and respecting backslash escapes. E.g., the value
        If this variable is set, the default hash algorithm for new
        repositories will be set to this value. This value is currently
        ignored when cloning; the setting of the remote repository
-       is used instead. The default is "sha1".
+       is used instead. The default is "sha1". THIS VARIABLE IS
+       EXPERIMENTAL! See `--object-format` in linkgit:git-init[1].
 
 Git Commits
 ~~~~~~~~~~~
index 9e481aec858d6eb36a98f3b7432e9847c50dc58b..758bf39ba385804440794e91e34d24ad79a3dea4 100644 (file)
@@ -3,7 +3,7 @@ gitcredentials(7)
 
 NAME
 ----
-gitcredentials - providing usernames and passwords to Git
+gitcredentials - Providing usernames and passwords to Git
 
 SYNOPSIS
 --------
diff --git a/Documentation/object-format-disclaimer.txt b/Documentation/object-format-disclaimer.txt
new file mode 100644 (file)
index 0000000..4cb106f
--- /dev/null
@@ -0,0 +1,6 @@
+THIS OPTION IS EXPERIMENTAL! SHA-256 support is experimental and still
+in an early stage.  A SHA-256 repository will in general not be able to
+share work with "regular" SHA-1 repositories.  It should be assumed
+that, e.g., Git internal file formats in relation to SHA-256
+repositories may change in backwards-incompatible ways.  Only use
+`--object-format=sha256` for testing purposes.
diff --git a/Documentation/rev-list-description.txt b/Documentation/rev-list-description.txt
new file mode 100644 (file)
index 0000000..a9efa7f
--- /dev/null
@@ -0,0 +1,61 @@
+List commits that are reachable by following the `parent` links from the
+given commit(s), but exclude commits that are reachable from the one(s)
+given with a '{caret}' in front of them.  The output is given in reverse
+chronological order by default.
+
+You can think of this as a set operation. Commits reachable from any of
+the commits given on the command line form a set, and then commits reachable
+from any of the ones given with '{caret}' in front are subtracted from that
+set.  The remaining commits are what comes out in the command's output.
+Various other options and paths parameters can be used to further limit the
+result.
+
+Thus, the following command:
+
+ifdef::git-rev-list[]
+-----------------------------------------------------------------------
+$ git rev-list foo bar ^baz
+-----------------------------------------------------------------------
+endif::git-rev-list[]
+ifdef::git-log[]
+-----------------------------------------------------------------------
+$ git log foo bar ^baz
+-----------------------------------------------------------------------
+endif::git-log[]
+
+means "list all the commits which are reachable from 'foo' or 'bar', but
+not from 'baz'".
+
+A special notation "'<commit1>'..'<commit2>'" can be used as a
+short-hand for "^'<commit1>' '<commit2>'". For example, either of
+the following may be used interchangeably:
+
+ifdef::git-rev-list[]
+-----------------------------------------------------------------------
+$ git rev-list origin..HEAD
+$ git rev-list HEAD ^origin
+-----------------------------------------------------------------------
+endif::git-rev-list[]
+ifdef::git-log[]
+-----------------------------------------------------------------------
+$ git log origin..HEAD
+$ git log HEAD ^origin
+-----------------------------------------------------------------------
+endif::git-log[]
+
+Another special notation is "'<commit1>'...'<commit2>'" which is useful
+for merges.  The resulting set of commits is the symmetric difference
+between the two operands.  The following two commands are equivalent:
+
+ifdef::git-rev-list[]
+-----------------------------------------------------------------------
+$ git rev-list A B --not $(git merge-base --all A B)
+$ git rev-list A...B
+-----------------------------------------------------------------------
+endif::git-rev-list[]
+ifdef::git-log[]
+-----------------------------------------------------------------------
+$ git log A B --not $(git merge-base --all A B)
+$ git log A...B
+-----------------------------------------------------------------------
+endif::git-log[]
index b01b2b677303aeb2575a594c5af781e8391fae51..002379056a072cb87f7c65bbcaedaa4ebed7387a 100644 (file)
@@ -128,8 +128,7 @@ parents) and `--max-parents=-1` (negative numbers denote no upper limit).
        because merges into a topic branch tend to be only about
        adjusting to updated upstream from time to time, and
        this option allows you to ignore the individual commits
-       brought in to your history by such a merge. Cannot be
-       combined with --bisect.
+       brought in to your history by such a merge.
 
 --not::
        Reverses the meaning of the '{caret}' prefix (or lack thereof)
@@ -207,7 +206,7 @@ ifndef::git-rev-list[]
        Pretend as if the bad bisection ref `refs/bisect/bad`
        was listed and as if it was followed by `--not` and the good
        bisection refs `refs/bisect/good-*` on the command
-       line. Cannot be combined with --first-parent.
+       line.
 endif::git-rev-list[]
 
 --stdin::
@@ -743,7 +742,7 @@ outputs 'midpoint', the output of the two commands
 would be of roughly the same length.  Finding the change which
 introduces a regression is thus reduced to a binary search: repeatedly
 generate and test new 'midpoint's until the commit chain is of length
-one. Cannot be combined with --first-parent.
+one.
 
 --bisect-vars::
        This calculates the same as `--bisect`, except that refs in
@@ -1117,48 +1116,3 @@ ifdef::git-rev-list[]
        by a tab.
 endif::git-rev-list[]
 endif::git-shortlog[]
-
-ifndef::git-shortlog[]
-ifndef::git-rev-list[]
-Diff Formatting
-~~~~~~~~~~~~~~~
-
-Listed below are options that control the formatting of diff output.
-Some of them are specific to linkgit:git-rev-list[1], however other diff
-options may be given. See linkgit:git-diff-files[1] for more options.
-
--c::
-       With this option, diff output for a merge commit
-       shows the differences from each of the parents to the merge result
-       simultaneously instead of showing pairwise diff between a parent
-       and the result one at a time. Furthermore, it lists only files
-       which were modified from all parents.
-
---cc::
-       This flag implies the `-c` option and further compresses the
-       patch output by omitting uninteresting hunks whose contents in
-       the parents have only two variants and the merge result picks
-       one of them without modification.
-
---combined-all-paths::
-       This flag causes combined diffs (used for merge commits) to
-       list the name of the file from all parents.  It thus only has
-       effect when -c or --cc are specified, and is likely only
-       useful if filename changes are detected (i.e. when either
-       rename or copy detection have been requested).
-
--m::
-       This flag makes the merge commits show the full diff like
-       regular commits; for each merge parent, a separate log entry
-       and diff is generated. An exception is that only diff against
-       the first parent is shown when `--first-parent` option is given;
-       in that case, the output represents the changes the merge
-       brought _into_ the then-current branch.
-
--r::
-       Show recursive diffs.
-
--t::
-       Show the tree objects in the diff output. This implies `-r`.
-endif::git-rev-list[]
-endif::git-shortlog[]
index 1ad95065c1f64577e2b65e6c730c4550b7c2992e..d9169c062eb1abc75545fb87f360cd06aa225aaa 100644 (file)
@@ -254,6 +254,9 @@ specifying a single revision, using the notation described in the
 previous section, means the set of commits `reachable` from the given
 commit.
 
+Specifying several revisions means the set of commits reachable from
+any of the given commits.
+
 A commit's reachable set is the commit itself and the commits in
 its ancestry chain.
 
index 2e2e7c10c620d86af5adbb0f7e7987dbe5feb12c..5a60bbfa7f4141eca54ac921642dbc2c8ada7ab3 100644 (file)
@@ -232,9 +232,9 @@ There are some macros to easily define options:
        will be overwritten, so this should only be used for options where
        the last one specified on the command line wins.
 
-`OPT_PASSTHRU_ARGV(short, long, &argv_array_var, arg_str, description, flags)`::
+`OPT_PASSTHRU_ARGV(short, long, &strvec_var, arg_str, description, flags)`::
        Introduce an option where all instances of it on the command-line will
-       be reconstructed into an argv_array. This is useful when you need to
+       be reconstructed into a strvec. This is useful when you need to
        pass the command-line option, which can be specified multiple times,
        to another command.
 
index 0e828151a5026d5f77952d4598e33bd1f990a9c3..bac558d049a36f4b4fbb132c7aa1dd5af4770102 100644 (file)
@@ -7,6 +7,8 @@ The Git bundle format is a format that represents both refs and Git objects.
 We will use ABNF notation to define the Git bundle format. See
 protocol-common.txt for the details.
 
+A v2 bundle looks like this:
+
 ----
 bundle    = signature *prerequisite *reference LF pack
 signature = "# v2 git bundle" LF
@@ -18,9 +20,28 @@ reference    = obj-id SP refname LF
 pack         = ... ; packfile
 ----
 
+A v3 bundle looks like this:
+
+----
+bundle    = signature *capability *prerequisite *reference LF pack
+signature = "# v3 git bundle" LF
+
+capability   = "@" key ["=" value] LF
+prerequisite = "-" obj-id SP comment LF
+comment      = *CHAR
+reference    = obj-id SP refname LF
+key          = 1*(ALPHA / DIGIT / "-")
+value        = *(%01-09 / %0b-FF)
+
+pack         = ... ; packfile
+----
+
 == Semantics
 
-A Git bundle consists of three parts.
+A Git bundle consists of several parts.
+
+* "Capabilities", which are only in the v3 format, indicate functionality that
+       the bundle requires to be read properly.
 
 * "Prerequisites" lists the objects that are NOT included in the bundle and the
   reader of the bundle MUST already have, in order to use the data in the
@@ -46,3 +67,10 @@ put any string here. The reader of the bundle MUST ignore the comment.
 Note that the prerequisites does not represent a shallow-clone boundary. The
 semantics of the prerequisites and the shallow-clone boundaries are different,
 and the Git bundle v2 format cannot represent a shallow clone repository.
+
+== Capabilities
+
+Because there is no opportunity for negotiation, unknown capabilities cause 'git
+bundle' to abort.  The only known capability is `object-format`, which specifies
+the hash algorithm in use, and can take the same values as the
+`extensions.objectFormat` configuration value.
index 1beef171822b7fd8ac7a3a088e831b4045ec561c..6ddbceba15c9708385ba51f339bf232c15753648 100644 (file)
@@ -32,7 +32,7 @@ the body into "chunks" and provide a binary lookup table at the beginning
 of the body. The header includes certain values, such as number of chunks
 and hash type.
 
-All 4-byte numbers are in network order.
+All multi-byte numbers are in network byte order.
 
 HEADER:
 
@@ -42,8 +42,13 @@ HEADER:
   1-byte version number:
       Currently, the only valid version is 1.
 
-  1-byte Hash Version (1 = SHA-1)
-      We infer the hash length (H) from this value.
+  1-byte Hash Version
+      We infer the hash length (H) from this value:
+       1 => SHA-1
+       2 => SHA-256
+      If the hash type does not match the repository's hash algorithm, the
+      commit-graph file should be ignored with a warning presented to the
+      user.
 
   1-byte number (C) of "chunks"
 
index 808fa30b99f26456ed0867caffc0294676a9afa0..f14a7659aa8733a2a992eb949caf1d4e7a67accf 100644 (file)
@@ -210,12 +210,12 @@ file.
                            +---------------------+
                            |                     |
  +-----------------------+  +---------------------+
- |  graph-{hash2} |->|                     |
+ |  graph-{hash2}        |->|                     |
  +-----------------------+  +---------------------+
          |                 |                     |
  +-----------------------+  +---------------------+
  |                       |  |                     |
- |  graph-{hash1} |->|                     |
+ |  graph-{hash1}        |->|                     |
  |                       |  |                     |
  +-----------------------+  +---------------------+
          |                  tmp_graphXXX
@@ -223,7 +223,7 @@ file.
  |                       |
  |                       |
  |                       |
- |  graph-{hash0} |
+ |  graph-{hash0}        |
  |                       |
  |                       |
  |                       |
index 5b2db3be1ecc448ade0529fea12752be53fa1930..6fd20ebbc254472936238a8db590585e93d5eb91 100644 (file)
@@ -650,7 +650,6 @@ Some initial steps can be implemented independently of one another:
 
 The first user-visible change is the introduction of the objectFormat
 extension (without compatObjectFormat). This requires:
-- implementing the loose-object-idx
 - teaching fsck about this mode of operation
 - using the hash function API (vtable) when computing object names
 - signing objects and verifying signatures
@@ -658,6 +657,7 @@ extension (without compatObjectFormat). This requires:
   repository
 
 Next comes introduction of compatObjectFormat:
+- implementing the loose-object-idx
 - translating object names between object formats
 - translating object content between object formats
 - generating and verifying signatures in the compat format
index 51a79e63de9b77656ec225ea3e8d38289d9e4ae8..96d89ea9b226136603a041e96789709c979883fd 100644 (file)
@@ -401,8 +401,9 @@ at all in the request stream:
 The stream is terminated by a pkt-line flush (`0000`).
 
 A single "want" or "have" command MUST have one hex formatted
-SHA-1 as its value.  Multiple SHA-1s MUST be sent by sending
-multiple commands.
+object name as its value.  Multiple object names MUST be sent by sending
+multiple commands. Object names MUST be given using the object format
+negotiated through the `object-format` capability (default SHA-1).
 
 The `have` list is created by popping the first 32 commits
 from `c_pending`.  Less can be supplied if `c_pending` empties.
index faa25c5c527e72bb63ae66e834b20e7f3f1a519a..f9a3644711b903336587333923a0203fa5fe9d86 100644 (file)
@@ -3,8 +3,11 @@ Git index format
 
 == The Git index file has the following format
 
-  All binary numbers are in network byte order. Version 2 is described
-  here unless stated otherwise.
+  All binary numbers are in network byte order.
+  In a repository using the traditional SHA-1, checksums and object IDs
+  (object names) mentioned below are all computed using SHA-1.  Similarly,
+  in SHA-256 repositories, these values are computed using SHA-256.
+  Version 2 is described here unless stated otherwise.
 
    - A 12-byte header consisting of
 
@@ -32,8 +35,7 @@ Git index format
 
      Extension data
 
-   - 160-bit SHA-1 over the content of the index file before this
-     checksum.
+   - Hash checksum over the content of the index file before this checksum.
 
 == Index entry
 
@@ -80,7 +82,7 @@ Git index format
   32-bit file size
     This is the on-disk size from stat(2), truncated to 32-bit.
 
-  160-bit SHA-1 for the represented object
+  Object name for the represented object
 
   A 16-bit 'flags' field split into (high to low bits)
 
@@ -160,8 +162,8 @@ Git index format
 
   - A newline (ASCII 10); and
 
-  - 160-bit object name for the object that would result from writing
-    this span of index as a tree.
+  - Object name for the object that would result from writing this span
+    of index as a tree.
 
   An entry can be in an invalidated state and is represented by having
   a negative number in the entry_count field. In this case, there is no
@@ -198,7 +200,7 @@ Git index format
     stage 1 to 3 (a missing stage is represented by "0" in this field);
     and
 
-  - At most three 160-bit object names of the entry in stages from 1 to 3
+  - At most three object names of the entry in stages from 1 to 3
     (nothing is written for a missing stage).
 
 === Split index
@@ -211,8 +213,8 @@ Git index format
 
   The extension consists of:
 
-  - 160-bit SHA-1 of the shared index file. The shared index file path
-    is $GIT_DIR/sharedindex.<SHA-1>. If all 160 bits are zero, the
+  - Hash of the shared index file. The shared index file path
+    is $GIT_DIR/sharedindex.<hash>. If all bits are zero, the
     index does not require a shared index file.
 
   - An ewah-encoded delete bitmap, each bit represents an entry in the
@@ -253,10 +255,10 @@ Git index format
 
   - 32-bit dir_flags (see struct dir_struct)
 
-  - 160-bit SHA-1 of $GIT_DIR/info/exclude. Null SHA-1 means the file
+  - Hash of $GIT_DIR/info/exclude. A null hash means the file
     does not exist.
 
-  - 160-bit SHA-1 of core.excludesfile. Null SHA-1 means the file does
+  - Hash of core.excludesfile. A null hash means the file does
     not exist.
 
   - NUL-terminated string of per-dir exclude file name. This usually
@@ -285,13 +287,13 @@ The remaining data of each directory block is grouped by type:
   - An ewah bitmap, the n-th bit records "check-only" bit of
     read_directory_recursive() for the n-th directory.
 
-  - An ewah bitmap, the n-th bit indicates whether SHA-1 and stat data
+  - An ewah bitmap, the n-th bit indicates whether hash and stat data
     is valid for the n-th directory and exists in the next data.
 
   - An array of stat data. The n-th data corresponds with the n-th
     "one" bit in the previous ewah bitmap.
 
-  - An array of SHA-1. The n-th SHA-1 corresponds with the n-th "one" bit
+  - An array of hashes. The n-th hash corresponds with the n-th "one" bit
     in the previous ewah bitmap.
 
   - One NUL.
@@ -330,12 +332,12 @@ The remaining data of each directory block is grouped by type:
 
   - 32-bit offset to the end of the index entries
 
-  - 160-bit SHA-1 over the extension types and their sizes (but not
+  - Hash over the extension types and their sizes (but not
        their contents).  E.g. if we have "TREE" extension that is N-bytes
        long, "REUC" extension that is M-bytes long, followed by "EOIE",
        then the hash would be:
 
-       SHA-1("TREE" + <binary representation of N> +
+       Hash("TREE" + <binary representation of N> +
                "REUC" + <binary representation of M>)
 
 == Index Entry Offset Table
index d3a142c6520258033f95b7e427be41f930883f99..f96b2e605f3486d389c0bb0674c060d7f52fe38a 100644 (file)
@@ -1,6 +1,12 @@
 Git pack format
 ===============
 
+== Checksums and object IDs
+
+In a repository using the traditional SHA-1, pack checksums, index checksums,
+and object IDs (object names) mentioned below are all computed using SHA-1.
+Similarly, in SHA-256 repositories, these values are computed using SHA-256.
+
 == pack-*.pack files have the following format:
 
    - A header appears at the beginning and consists of the following:
@@ -26,7 +32,7 @@ Git pack format
 
      (deltified representation)
      n-byte type and length (3-bit type, (n-1)*7+4-bit length)
-     20-byte base object name if OBJ_REF_DELTA or a negative relative
+     base object name if OBJ_REF_DELTA or a negative relative
         offset from the delta object's position in the pack if this
         is an OBJ_OFS_DELTA object
      compressed delta data
@@ -34,7 +40,7 @@ Git pack format
      Observation: length of each object is encoded in a variable
      length format and is not constrained to 32-bit or anything.
 
-  - The trailer records 20-byte SHA-1 checksum of all of the above.
+  - The trailer records a pack checksum of all of the above.
 
 === Object types
 
@@ -58,8 +64,8 @@ ofs-delta and ref-delta, which is only valid in a pack file.
 
 Both ofs-delta and ref-delta store the "delta" to be applied to
 another object (called 'base object') to reconstruct the object. The
-difference between them is, ref-delta directly encodes 20-byte base
-object name. If the base object is in the same pack, ofs-delta encodes
+difference between them is, ref-delta directly encodes base object
+name. If the base object is in the same pack, ofs-delta encodes
 the offset of the base object in the pack instead.
 
 The base object could also be deltified if it's in the same pack.
@@ -143,14 +149,14 @@ This is the instruction reserved for future expansion.
     object is stored in the packfile as the offset from the
     beginning.
 
-    20-byte object name.
+    one object name of the appropriate size.
 
   - The file is concluded with a trailer:
 
-    A copy of the 20-byte SHA-1 checksum at the end of
-    corresponding packfile.
+    A copy of the pack checksum at the end of the corresponding
+    packfile.
 
-    20-byte SHA-1-checksum of all of the above.
+    Index checksum of all of the above.
 
 Pack Idx file:
 
@@ -198,7 +204,7 @@ Pack file entry: <+
         If it is not DELTA, then deflated bytes (the size above
                is the size before compression).
        If it is REF_DELTA, then
-         20-byte base object name SHA-1 (the size above is the
+         base object name (the size above is the
                size of the delta data that follows).
           delta data, deflated.
        If it is OFS_DELTA, then
@@ -227,9 +233,9 @@ Pack file entry: <+
 
   - A 256-entry fan-out table just like v1.
 
-  - A table of sorted 20-byte SHA-1 object names.  These are
-    packed together without offset values to reduce the cache
-    footprint of the binary search for a specific object name.
+  - A table of sorted object names.  These are packed together
+    without offset values to reduce the cache footprint of the
+    binary search for a specific object name.
 
   - A table of 4-byte CRC32 values of the packed object data.
     This is new in v2 so compressed data can be copied directly
@@ -248,10 +254,10 @@ Pack file entry: <+
 
   - The same trailer as a v1 pack file:
 
-    A copy of the 20-byte SHA-1 checksum at the end of
+    A copy of the pack checksum at the end of
     corresponding packfile.
 
-    20-byte SHA-1-checksum of all of the above.
+    Index checksum of all of the above.
 
 == multi-pack-index (MIDX) files have the following format:
 
@@ -273,7 +279,12 @@ HEADER:
            Git only writes or recognizes version 1.
 
        1-byte Object Id Version
-           Git only writes or recognizes version 1 (SHA1).
+           We infer the length of object IDs (OIDs) from this value:
+               1 => SHA-1
+               2 => SHA-256
+           If the hash type does not match the repository's hash algorithm,
+           the multi-pack-index file should be ignored with a warning
+           presented to the user.
 
        1-byte number of "chunks"
 
@@ -329,4 +340,4 @@ CHUNK DATA:
 
 TRAILER:
 
-       20-byte SHA1-checksum of the above contents.
+       Index checksum of the above contents.
index 36ccd14f97ed4631078fbac5cf65940840d3e197..124d716807eb3e90802282782705dd096be99e43 100644 (file)
@@ -324,15 +324,19 @@ allow-tip-sha1-in-want
 ----------------------
 
 If the upload-pack server advertises this capability, fetch-pack may
-send "want" lines with SHA-1s that exist at the server but are not
-advertised by upload-pack.
+send "want" lines with object names that exist at the server but are not
+advertised by upload-pack. For historical reasons, the name of this
+capability contains "sha1". Object names are always given using the
+object format negotiated through the 'object-format' capability.
 
 allow-reachable-sha1-in-want
 ----------------------------
 
 If the upload-pack server advertises this capability, fetch-pack may
-send "want" lines with SHA-1s that exist at the server but are not
-advertised by upload-pack.
+send "want" lines with object names that exist at the server but are not
+advertised by upload-pack. For historical reasons, the name of this
+capability contains "sha1". Object names are always given using the
+object format negotiated through the 'object-format' capability.
 
 push-cert=<nonce>
 -----------------
index 01dedfe9ffedc28c2c6ac5ef15dbb3c5fe519cc0..f3738baa0f0580cc92e3c1a604e16715ac2608a3 100644 (file)
@@ -13,7 +13,7 @@ pretend as if they are root commits (e.g. "git log" traversal
 stops after showing them; "git fsck" does not complain saying
 the commits listed on their "parent" lines do not exist).
 
-Each line contains exactly one SHA-1. When read, a commit_graft
+Each line contains exactly one object name. When read, a commit_graft
 will be constructed, which has nr_parent < 0 to make it easier
 to discern from user provided grafts.
 
index 372139f1f244824e23684ce95e371d63244de48e..65f8cfb2368d2d6099bdfd845a7beb505702b86f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -828,7 +828,6 @@ LIB_OBJS += apply.o
 LIB_OBJS += archive-tar.o
 LIB_OBJS += archive-zip.o
 LIB_OBJS += archive.o
-LIB_OBJS += argv-array.o
 LIB_OBJS += attr.o
 LIB_OBJS += base85.o
 LIB_OBJS += bisect.o
@@ -986,6 +985,7 @@ LIB_OBJS += sigchain.o
 LIB_OBJS += split-index.o
 LIB_OBJS += stable-qsort.o
 LIB_OBJS += strbuf.o
+LIB_OBJS += strvec.o
 LIB_OBJS += streaming.o
 LIB_OBJS += string-list.o
 LIB_OBJS += sub-process.o
index a7b4f6dc414595bb1474053e1002322a12f95739..914365022e60d65077bd5a552e6f8888332e9418 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.28.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.29.0.txt
\ No newline at end of file
index 29cd2fe02014b32c21b69059e5bbf93018a77223..555c4abf324f553b6bb70f6640554d407c12677a 100644 (file)
@@ -935,18 +935,18 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,
        opts->prompt = N_("Patch update");
        count = list_and_choose(s, files, opts);
        if (count > 0) {
-               struct argv_array args = ARGV_ARRAY_INIT;
+               struct strvec args = STRVEC_INIT;
                struct pathspec ps_selected = { 0 };
 
                for (i = 0; i < files->items.nr; i++)
                        if (files->selected[i])
-                               argv_array_push(&args,
-                                               files->items.items[i].string);
+                               strvec_push(&args,
+                                           files->items.items[i].string);
                parse_pathspec(&ps_selected,
                               PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL,
-                              PATHSPEC_LITERAL_PATH, "", args.argv);
+                              PATHSPEC_LITERAL_PATH, "", args.v);
                res = run_add_p(s->r, ADD_P_ADD, NULL, &ps_selected);
-               argv_array_clear(&args);
+               strvec_clear(&args);
                clear_pathspec(&ps_selected);
        }
 
@@ -976,18 +976,18 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps,
        count = list_and_choose(s, files, opts);
        opts->flags = 0;
        if (count > 0) {
-               struct argv_array args = ARGV_ARRAY_INIT;
+               struct strvec args = STRVEC_INIT;
 
-               argv_array_pushl(&args, "git", "diff", "-p", "--cached",
-                                oid_to_hex(!is_initial ? &oid :
-                                           s->r->hash_algo->empty_tree),
-                                "--", NULL);
+               strvec_pushl(&args, "git", "diff", "-p", "--cached",
+                            oid_to_hex(!is_initial ? &oid :
+                                       s->r->hash_algo->empty_tree),
+                            "--", NULL);
                for (i = 0; i < files->items.nr; i++)
                        if (files->selected[i])
-                               argv_array_push(&args,
-                                               files->items.items[i].string);
-               res = run_command_v_opt(args.argv, 0);
-               argv_array_clear(&args);
+                               strvec_push(&args,
+                                           files->items.items[i].string);
+               res = run_command_v_opt(args.v, 0);
+               strvec_clear(&args);
        }
 
        putchar('\n');
index f899389e2cc2359d255f9a74430ef2a995fba004..f67b304a552947553e5990a239e6aa18ee745a52 100644 (file)
@@ -2,7 +2,7 @@
 #include "add-interactive.h"
 #include "strbuf.h"
 #include "run-command.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "pathspec.h"
 #include "color.h"
 #include "diff.h"
@@ -286,12 +286,12 @@ static void setup_child_process(struct add_p_state *s,
 
        va_start(ap, cp);
        while ((arg = va_arg(ap, const char *)))
-               argv_array_push(&cp->args, arg);
+               strvec_push(&cp->args, arg);
        va_end(ap);
 
        cp->git_cmd = 1;
-       argv_array_pushf(&cp->env_array,
-                        INDEX_ENVIRONMENT "=%s", s->s.r->index_file);
+       strvec_pushf(&cp->env_array,
+                    INDEX_ENVIRONMENT "=%s", s->s.r->index_file);
 }
 
 static int parse_range(const char **p,
@@ -370,7 +370,7 @@ static int is_octal(const char *p, size_t len)
 
 static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
 {
-       struct argv_array args = ARGV_ARRAY_INIT;
+       struct strvec args = STRVEC_INIT;
        const char *diff_algorithm = s->s.interactive_diff_algorithm;
        struct strbuf *plain = &s->plain, *colored = NULL;
        struct child_process cp = CHILD_PROCESS_INIT;
@@ -380,32 +380,32 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
        struct hunk *hunk = NULL;
        int res;
 
-       argv_array_pushv(&args, s->mode->diff_cmd);
+       strvec_pushv(&args, s->mode->diff_cmd);
        if (diff_algorithm)
-               argv_array_pushf(&args, "--diff-algorithm=%s", diff_algorithm);
+               strvec_pushf(&args, "--diff-algorithm=%s", diff_algorithm);
        if (s->revision) {
                struct object_id oid;
-               argv_array_push(&args,
-                               /* could be on an unborn branch */
-                               !strcmp("HEAD", s->revision) &&
-                               get_oid("HEAD", &oid) ?
-                               empty_tree_oid_hex() : s->revision);
+               strvec_push(&args,
+                           /* could be on an unborn branch */
+                           !strcmp("HEAD", s->revision) &&
+                           get_oid("HEAD", &oid) ?
+                           empty_tree_oid_hex() : s->revision);
        }
-       color_arg_index = args.argc;
+       color_arg_index = args.nr;
        /* Use `--no-color` explicitly, just in case `diff.color = always`. */
-       argv_array_pushl(&args, "--no-color", "-p", "--", NULL);
+       strvec_pushl(&args, "--no-color", "-p", "--", NULL);
        for (i = 0; i < ps->nr; i++)
-               argv_array_push(&args, ps->items[i].original);
+               strvec_push(&args, ps->items[i].original);
 
        setup_child_process(s, &cp, NULL);
-       cp.argv = args.argv;
+       cp.argv = args.v;
        res = capture_command(&cp, plain, 0);
        if (res) {
-               argv_array_clear(&args);
+               strvec_clear(&args);
                return error(_("could not parse diff"));
        }
        if (!plain->len) {
-               argv_array_clear(&args);
+               strvec_clear(&args);
                return 0;
        }
        strbuf_complete_line(plain);
@@ -415,11 +415,11 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
                const char *diff_filter = s->s.interactive_diff_filter;
 
                setup_child_process(s, &colored_cp, NULL);
-               xsnprintf((char *)args.argv[color_arg_index], 8, "--color");
-               colored_cp.argv = args.argv;
+               xsnprintf((char *)args.v[color_arg_index], 8, "--color");
+               colored_cp.argv = args.v;
                colored = &s->colored;
                res = capture_command(&colored_cp, colored, 0);
-               argv_array_clear(&args);
+               strvec_clear(&args);
                if (res)
                        return error(_("could not parse colored diff"));
 
@@ -444,7 +444,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
                colored_p = colored->buf;
                colored_pend = colored_p + colored->len;
        }
-       argv_array_clear(&args);
+       strvec_clear(&args);
 
        /* parse files and hunks */
        p = plain->buf;
@@ -1158,7 +1158,7 @@ static int run_apply_check(struct add_p_state *s,
 
        setup_child_process(s, &cp,
                            "apply", "--check", NULL);
-       argv_array_pushv(&cp.args, s->mode->apply_check_args);
+       strvec_pushv(&cp.args, s->mode->apply_check_args);
        if (pipe_command(&cp, s->buf.buf, s->buf.len, NULL, 0, NULL, 0))
                return error(_("'git apply --cached' failed"));
 
@@ -1203,7 +1203,7 @@ static int edit_hunk_loop(struct add_p_state *s,
        for (;;) {
                int res = edit_hunk_manually(s, hunk);
                if (res == 0) {
-                       /* abandonded */
+                       /* abandoned */
                        *hunk = backup;
                        return -1;
                }
@@ -1619,7 +1619,7 @@ soft_increment:
                                           s->mode->is_reverse);
                else {
                        setup_child_process(s, &cp, "apply", NULL);
-                       argv_array_pushv(&cp.args, s->mode->apply_args);
+                       strvec_pushv(&cp.args, s->mode->apply_args);
                        if (pipe_command(&cp, s->buf.buf, s->buf.len,
                                         NULL, 0, NULL, 0))
                                error(_("'git apply' failed"));
diff --git a/apply.c b/apply.c
index 8bff604dbe203402d93bd13fe5b03d635a7a50ee..76dba93c974b3814117e3856d875e7e4381d2f62 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -30,8 +30,8 @@ struct gitdiff_data {
 
 static void git_apply_config(void)
 {
-       git_config_get_string_const("apply.whitespace", &apply_default_whitespace);
-       git_config_get_string_const("apply.ignorewhitespace", &apply_default_ignorewhitespace);
+       git_config_get_string("apply.whitespace", &apply_default_whitespace);
+       git_config_get_string("apply.ignorewhitespace", &apply_default_ignorewhitespace);
        git_config(git_xmerge_config, NULL);
 }
 
@@ -3178,7 +3178,7 @@ static int apply_binary(struct apply_state *state,
                return 0; /* deletion patch */
        }
 
-       if (has_object_file(&oid)) {
+       if (has_object(the_repository, &oid, 0)) {
                /* We already have the postimage */
                enum object_type type;
                unsigned long size;
@@ -3740,6 +3740,7 @@ static int check_preimage(struct apply_state *state,
 
 #define EXISTS_IN_INDEX 1
 #define EXISTS_IN_WORKTREE 2
+#define EXISTS_IN_INDEX_AS_ITA 3
 
 static int check_to_create(struct apply_state *state,
                           const char *new_name,
@@ -3747,10 +3748,23 @@ static int check_to_create(struct apply_state *state,
 {
        struct stat nst;
 
-       if (state->check_index &&
-           index_name_pos(state->repo->index, new_name, strlen(new_name)) >= 0 &&
-           !ok_if_exists)
-               return EXISTS_IN_INDEX;
+       if (state->check_index && (!ok_if_exists || !state->cached)) {
+               int pos;
+
+               pos = index_name_pos(state->repo->index, new_name, strlen(new_name));
+               if (pos >= 0) {
+                       struct cache_entry *ce = state->repo->index->cache[pos];
+
+                       /* allow ITA, as they do not yet exist in the index */
+                       if (!ok_if_exists && !(ce->ce_flags & CE_INTENT_TO_ADD))
+                               return EXISTS_IN_INDEX;
+
+                       /* ITA entries can never match working tree files */
+                       if (!state->cached && (ce->ce_flags & CE_INTENT_TO_ADD))
+                               return EXISTS_IN_INDEX_AS_ITA;
+               }
+       }
+
        if (state->cached)
                return 0;
 
@@ -3935,6 +3949,9 @@ static int check_patch(struct apply_state *state, struct patch *patch)
                case EXISTS_IN_INDEX:
                        return error(_("%s: already exists in index"), new_name);
                        break;
+               case EXISTS_IN_INDEX_AS_ITA:
+                       return error(_("%s: does not match index"), new_name);
+                       break;
                case EXISTS_IN_WORKTREE:
                        return error(_("%s: already exists in working directory"),
                                     new_name);
diff --git a/argv-array.c b/argv-array.c
deleted file mode 100644 (file)
index 61ef8c0..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-#include "cache.h"
-#include "argv-array.h"
-#include "strbuf.h"
-
-const char *empty_argv[] = { NULL };
-
-void argv_array_init(struct argv_array *array)
-{
-       array->argv = empty_argv;
-       array->argc = 0;
-       array->alloc = 0;
-}
-
-static void argv_array_push_nodup(struct argv_array *array, const char *value)
-{
-       if (array->argv == empty_argv)
-               array->argv = NULL;
-
-       ALLOC_GROW(array->argv, array->argc + 2, array->alloc);
-       array->argv[array->argc++] = value;
-       array->argv[array->argc] = NULL;
-}
-
-const char *argv_array_push(struct argv_array *array, const char *value)
-{
-       argv_array_push_nodup(array, xstrdup(value));
-       return array->argv[array->argc - 1];
-}
-
-const char *argv_array_pushf(struct argv_array *array, const char *fmt, ...)
-{
-       va_list ap;
-       struct strbuf v = STRBUF_INIT;
-
-       va_start(ap, fmt);
-       strbuf_vaddf(&v, fmt, ap);
-       va_end(ap);
-
-       argv_array_push_nodup(array, strbuf_detach(&v, NULL));
-       return array->argv[array->argc - 1];
-}
-
-void argv_array_pushl(struct argv_array *array, ...)
-{
-       va_list ap;
-       const char *arg;
-
-       va_start(ap, array);
-       while ((arg = va_arg(ap, const char *)))
-               argv_array_push(array, arg);
-       va_end(ap);
-}
-
-void argv_array_pushv(struct argv_array *array, const char **argv)
-{
-       for (; *argv; argv++)
-               argv_array_push(array, *argv);
-}
-
-void argv_array_pop(struct argv_array *array)
-{
-       if (!array->argc)
-               return;
-       free((char *)array->argv[array->argc - 1]);
-       array->argv[array->argc - 1] = NULL;
-       array->argc--;
-}
-
-void argv_array_split(struct argv_array *array, const char *to_split)
-{
-       while (isspace(*to_split))
-               to_split++;
-       for (;;) {
-               const char *p = to_split;
-
-               if (!*p)
-                       break;
-
-               while (*p && !isspace(*p))
-                       p++;
-               argv_array_push_nodup(array, xstrndup(to_split, p - to_split));
-
-               while (isspace(*p))
-                       p++;
-               to_split = p;
-       }
-}
-
-void argv_array_clear(struct argv_array *array)
-{
-       if (array->argv != empty_argv) {
-               int i;
-               for (i = 0; i < array->argc; i++)
-                       free((char *)array->argv[i]);
-               free(array->argv);
-       }
-       argv_array_init(array);
-}
-
-const char **argv_array_detach(struct argv_array *array)
-{
-       if (array->argv == empty_argv)
-               return xcalloc(1, sizeof(const char *));
-       else {
-               const char **ret = array->argv;
-               argv_array_init(array);
-               return ret;
-       }
-}
index d5e830410f5949d1e8c24e990cf0a70b980656ea..d42a3a3767d60bd36af1d57aabd8adc1be5fd378 100644 (file)
--- a/bisect.c
+++ b/bisect.c
 #include "log-tree.h"
 #include "bisect.h"
 #include "oid-array.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "commit-slab.h"
 #include "commit-reach.h"
 #include "object-store.h"
+#include "dir.h"
 
 static struct oid_array good_revs;
 static struct oid_array skipped_revs;
@@ -88,15 +89,16 @@ static inline void weight_set(struct commit_list *elem, int weight)
        **commit_weight_at(&commit_weight, elem->item) = weight;
 }
 
-static int count_interesting_parents(struct commit *commit)
+static int count_interesting_parents(struct commit *commit, unsigned bisect_flags)
 {
        struct commit_list *p;
        int count;
 
        for (count = 0, p = commit->parents; p; p = p->next) {
-               if (p->item->object.flags & UNINTERESTING)
-                       continue;
-               count++;
+               if (!(p->item->object.flags & UNINTERESTING))
+                       count++;
+               if (bisect_flags & FIND_BISECTION_FIRST_PARENT_ONLY)
+                       break;
        }
        return count;
 }
@@ -135,7 +137,7 @@ static void show_list(const char *debug, int counted, int nr,
        for (p = list; p; p = p->next) {
                struct commit_list *pp;
                struct commit *commit = p->item;
-               unsigned flags = commit->object.flags;
+               unsigned commit_flags = commit->object.flags;
                enum object_type type;
                unsigned long size;
                char *buf = read_object_file(&commit->object.oid, &type,
@@ -144,9 +146,9 @@ static void show_list(const char *debug, int counted, int nr,
                int subject_len;
 
                fprintf(stderr, "%c%c%c ",
-                       (flags & TREESAME) ? ' ' : 'T',
-                       (flags & UNINTERESTING) ? 'U' : ' ',
-                       (flags & COUNTED) ? 'C' : ' ');
+                       (commit_flags & TREESAME) ? ' ' : 'T',
+                       (commit_flags & UNINTERESTING) ? 'U' : ' ',
+                       (commit_flags & COUNTED) ? 'C' : ' ');
                if (*commit_weight_at(&commit_weight, p->item))
                        fprintf(stderr, "%3d", weight(p));
                else
@@ -171,9 +173,9 @@ static struct commit_list *best_bisection(struct commit_list *list, int nr)
        best = list;
        for (p = list; p; p = p->next) {
                int distance;
-               unsigned flags = p->item->object.flags;
+               unsigned commit_flags = p->item->object.flags;
 
-               if (flags & TREESAME)
+               if (commit_flags & TREESAME)
                        continue;
                distance = weight(p);
                if (nr - distance < distance)
@@ -212,9 +214,9 @@ static struct commit_list *best_bisection_sorted(struct commit_list *list, int n
 
        for (p = list, cnt = 0; p; p = p->next) {
                int distance;
-               unsigned flags = p->item->object.flags;
+               unsigned commit_flags = p->item->object.flags;
 
-               if (flags & TREESAME)
+               if (commit_flags & TREESAME)
                        continue;
                distance = weight(p);
                if (nr - distance < distance)
@@ -259,7 +261,7 @@ static struct commit_list *best_bisection_sorted(struct commit_list *list, int n
  */
 static struct commit_list *do_find_bisection(struct commit_list *list,
                                             int nr, int *weights,
-                                            int find_all)
+                                            unsigned bisect_flags)
 {
        int n, counted;
        struct commit_list *p;
@@ -268,12 +270,12 @@ static struct commit_list *do_find_bisection(struct commit_list *list,
 
        for (n = 0, p = list; p; p = p->next) {
                struct commit *commit = p->item;
-               unsigned flags = commit->object.flags;
+               unsigned commit_flags = commit->object.flags;
 
                *commit_weight_at(&commit_weight, p->item) = &weights[n++];
-               switch (count_interesting_parents(commit)) {
+               switch (count_interesting_parents(commit, bisect_flags)) {
                case 0:
-                       if (!(flags & TREESAME)) {
+                       if (!(commit_flags & TREESAME)) {
                                weight_set(p, 1);
                                counted++;
                                show_list("bisection 2 count one",
@@ -314,11 +316,13 @@ static struct commit_list *do_find_bisection(struct commit_list *list,
                        continue;
                if (weight(p) != -2)
                        continue;
+               if (bisect_flags & FIND_BISECTION_FIRST_PARENT_ONLY)
+                       BUG("shouldn't be calling count-distance in fp mode");
                weight_set(p, count_distance(p));
                clear_distance(list);
 
                /* Does it happen to be at exactly half-way? */
-               if (!find_all && halfway(p, nr))
+               if (!(bisect_flags & FIND_BISECTION_ALL) && halfway(p, nr))
                        return p;
                counted++;
        }
@@ -328,11 +332,14 @@ static struct commit_list *do_find_bisection(struct commit_list *list,
        while (counted < nr) {
                for (p = list; p; p = p->next) {
                        struct commit_list *q;
-                       unsigned flags = p->item->object.flags;
+                       unsigned commit_flags = p->item->object.flags;
 
                        if (0 <= weight(p))
                                continue;
-                       for (q = p->item->parents; q; q = q->next) {
+
+                       for (q = p->item->parents;
+                            q;
+                            q = bisect_flags & FIND_BISECTION_FIRST_PARENT_ONLY ? NULL : q->next) {
                                if (q->item->object.flags & UNINTERESTING)
                                        continue;
                                if (0 <= weight(q))
@@ -346,7 +353,7 @@ static struct commit_list *do_find_bisection(struct commit_list *list,
                         * add one for p itself if p is to be counted,
                         * otherwise inherit it from q directly.
                         */
-                       if (!(flags & TREESAME)) {
+                       if (!(commit_flags & TREESAME)) {
                                weight_set(p, weight(q)+1);
                                counted++;
                                show_list("bisection 2 count one",
@@ -356,21 +363,21 @@ static struct commit_list *do_find_bisection(struct commit_list *list,
                                weight_set(p, weight(q));
 
                        /* Does it happen to be at exactly half-way? */
-                       if (!find_all && halfway(p, nr))
+                       if (!(bisect_flags & FIND_BISECTION_ALL) && halfway(p, nr))
                                return p;
                }
        }
 
        show_list("bisection 2 counted all", counted, nr, list);
 
-       if (!find_all)
+       if (!(bisect_flags & FIND_BISECTION_ALL))
                return best_bisection(list, nr);
        else
                return best_bisection_sorted(list, nr);
 }
 
 void find_bisection(struct commit_list **commit_list, int *reaches,
-                   int *all, int find_all)
+                   int *all, unsigned bisect_flags)
 {
        int nr, on_list;
        struct commit_list *list, *p, *best, *next, *last;
@@ -386,16 +393,16 @@ void find_bisection(struct commit_list **commit_list, int *reaches,
        for (nr = on_list = 0, last = NULL, p = *commit_list;
             p;
             p = next) {
-               unsigned flags = p->item->object.flags;
+               unsigned commit_flags = p->item->object.flags;
 
                next = p->next;
-               if (flags & UNINTERESTING) {
+               if (commit_flags & UNINTERESTING) {
                        free(p);
                        continue;
                }
                p->next = last;
                last = p;
-               if (!(flags & TREESAME))
+               if (!(commit_flags & TREESAME))
                        nr++;
                on_list++;
        }
@@ -406,9 +413,9 @@ void find_bisection(struct commit_list **commit_list, int *reaches,
        weights = xcalloc(on_list, sizeof(*weights));
 
        /* Do the real work of finding bisection commit. */
-       best = do_find_bisection(list, nr, weights, find_all);
+       best = do_find_bisection(list, nr, weights, bisect_flags);
        if (best) {
-               if (!find_all) {
+               if (!(bisect_flags & FIND_BISECTION_ALL)) {
                        list->item = best->item;
                        free_commit_list(list->next);
                        best = list;
@@ -454,9 +461,10 @@ static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN")
 static GIT_PATH_FUNC(git_path_bisect_start, "BISECT_START")
 static GIT_PATH_FUNC(git_path_bisect_log, "BISECT_LOG")
 static GIT_PATH_FUNC(git_path_bisect_terms, "BISECT_TERMS")
+static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT")
 static GIT_PATH_FUNC(git_path_head_name, "head-name")
 
-static void read_bisect_paths(struct argv_array *array)
+static void read_bisect_paths(struct strvec *array)
 {
        struct strbuf str = STRBUF_INIT;
        const char *filename = git_path_bisect_names();
@@ -464,7 +472,7 @@ static void read_bisect_paths(struct argv_array *array)
 
        while (strbuf_getline_lf(&str, fp) != EOF) {
                strbuf_trim(&str);
-               if (sq_dequote_to_argv_array(str.buf, array))
+               if (sq_dequote_to_strvec(str.buf, array))
                        die(_("Badly quoted content in file '%s': %s"),
                            filename, str.buf);
        }
@@ -632,7 +640,7 @@ static void bisect_rev_setup(struct repository *r, struct rev_info *revs,
                             const char *bad_format, const char *good_format,
                             int read_paths)
 {
-       struct argv_array rev_argv = ARGV_ARRAY_INIT;
+       struct strvec rev_argv = STRVEC_INIT;
        int i;
 
        repo_init_revisions(r, revs, prefix);
@@ -640,16 +648,16 @@ static void bisect_rev_setup(struct repository *r, struct rev_info *revs,
        revs->commit_format = CMIT_FMT_UNSPECIFIED;
 
        /* rev_argv.argv[0] will be ignored by setup_revisions */
-       argv_array_push(&rev_argv, "bisect_rev_setup");
-       argv_array_pushf(&rev_argv, bad_format, oid_to_hex(current_bad_oid));
+       strvec_push(&rev_argv, "bisect_rev_setup");
+       strvec_pushf(&rev_argv, bad_format, oid_to_hex(current_bad_oid));
        for (i = 0; i < good_revs.nr; i++)
-               argv_array_pushf(&rev_argv, good_format,
-                                oid_to_hex(good_revs.oid + i));
-       argv_array_push(&rev_argv, "--");
+               strvec_pushf(&rev_argv, good_format,
+                            oid_to_hex(good_revs.oid + i));
+       strvec_push(&rev_argv, "--");
        if (read_paths)
                read_bisect_paths(&rev_argv);
 
-       setup_revisions(rev_argv.argc, rev_argv.argv, revs, NULL);
+       setup_revisions(rev_argv.nr, rev_argv.v, revs, NULL);
        /* XXX leak rev_argv, as "revs" may still be pointing to it */
 }
 
@@ -709,7 +717,7 @@ static enum bisect_error bisect_checkout(const struct object_id *bisect_rev, int
        char bisect_rev_hex[GIT_MAX_HEXSZ + 1];
        enum bisect_error res = BISECT_OK;
 
-       memcpy(bisect_rev_hex, oid_to_hex(bisect_rev), the_hash_algo->hexsz + 1);
+       oid_to_hex_r(bisect_rev_hex, bisect_rev);
        update_ref(NULL, "BISECT_EXPECTED_REV", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR);
 
        argv_checkout[2] = bisect_rev_hex;
@@ -983,7 +991,7 @@ void read_bisect_terms(const char **read_bad, const char **read_good)
  * If no_checkout is non-zero, the bisection process does not
  * checkout the trial commit but instead simply updates BISECT_HEAD.
  */
-enum bisect_error bisect_next_all(struct repository *r, const char *prefix, int no_checkout)
+enum bisect_error bisect_next_all(struct repository *r, const char *prefix)
 {
        struct rev_info revs;
        struct commit_list *tried;
@@ -991,21 +999,31 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix, int
        enum bisect_error res = BISECT_OK;
        struct object_id *bisect_rev;
        char *steps_msg;
+       int no_checkout = ref_exists("BISECT_HEAD");
+       unsigned bisect_flags = 0;
 
        read_bisect_terms(&term_bad, &term_good);
        if (read_bisect_refs())
                die(_("reading bisect refs failed"));
 
+       if (file_exists(git_path_bisect_first_parent()))
+               bisect_flags |= FIND_BISECTION_FIRST_PARENT_ONLY;
+
+       if (skipped_revs.nr)
+               bisect_flags |= FIND_BISECTION_ALL;
+
        res = check_good_are_ancestors_of_bad(r, prefix, no_checkout);
        if (res)
                return res;
 
        bisect_rev_setup(r, &revs, prefix, "%s", "^%s", 1);
+
+       revs.first_parent_only = !!(bisect_flags & FIND_BISECTION_FIRST_PARENT_ONLY);
        revs.limited = 1;
 
        bisect_common(&revs);
 
-       find_bisection(&revs.commits, &reaches, &all, !!skipped_revs.nr);
+       find_bisection(&revs.commits, &reaches, &all, bisect_flags);
        revs.commits = managed_skipped(revs.commits, &tried);
 
        if (!revs.commits) {
@@ -1133,6 +1151,7 @@ int bisect_clean_state(void)
        unlink_or_warn(git_path_bisect_names());
        unlink_or_warn(git_path_bisect_run());
        unlink_or_warn(git_path_bisect_terms());
+       unlink_or_warn(git_path_bisect_first_parent());
        /* Cleanup head-name if it got left by an old version of git-bisect */
        unlink_or_warn(git_path_head_name());
        /*
index 8bad8d8391546f347ec91324eca21f74bda8e68f..ec24ac2d7ee9d18fa6a9188534040602fd728e38 100644 (file)
--- a/bisect.h
+++ b/bisect.h
@@ -12,7 +12,7 @@ struct repository;
  * best commit, as chosen by `find_all`.
  */
 void find_bisection(struct commit_list **list, int *reaches, int *all,
-                   int find_all);
+                   unsigned bisect_flags);
 
 struct commit_list *filter_skipped(struct commit_list *list,
                                   struct commit_list **tried,
@@ -23,6 +23,9 @@ struct commit_list *filter_skipped(struct commit_list *list,
 #define BISECT_SHOW_ALL                (1<<0)
 #define REV_LIST_QUIET         (1<<1)
 
+#define FIND_BISECTION_ALL                     (1u<<0)
+#define FIND_BISECTION_FIRST_PARENT_ONLY       (1u<<1)
+
 struct rev_list_info {
        struct rev_info *revs;
        int flags;
@@ -58,9 +61,7 @@ enum bisect_error {
        BISECT_INTERNAL_SUCCESS_MERGE_BASE = -11
 };
 
-enum bisect_error bisect_next_all(struct repository *r,
-                   const char *prefix,
-                   int no_checkout);
+enum bisect_error bisect_next_all(struct repository *r, const char *prefix);
 
 int estimate_bisect_steps(int all);
 
diff --git a/blame.c b/blame.c
index 82fa16d6585b90e3635d87f6adc1e4856524f7d6..1be1cd82a29b781e6761f7281d8a8c3df89a0535 100644 (file)
--- a/blame.c
+++ b/blame.c
@@ -1184,6 +1184,7 @@ void blame_coalesce(struct blame_scoreboard *sb)
        for (ent = sb->ent; ent && (next = ent->next); ent = next) {
                if (ent->suspect == next->suspect &&
                    ent->s_lno + ent->num_lines == next->s_lno &&
+                   ent->lno + ent->num_lines == next->lno &&
                    ent->ignored == next->ignored &&
                    ent->unblamable == next->unblamable) {
                        ent->num_lines += next->num_lines;
diff --git a/bloom.c b/bloom.c
index 6a7f2f2bdc13031f2861a5cd8c8417bafaed503f..1a573226e70e571b49a7af29d49740768b1465af 100644 (file)
--- a/bloom.c
+++ b/bloom.c
@@ -187,7 +187,7 @@ struct bloom_filter *get_bloom_filter(struct repository *r,
        struct diff_options diffopt;
        int max_changes = 512;
 
-       if (bloom_filters.slab_size == 0)
+       if (!bloom_filters.slab_size)
                return NULL;
 
        filter = bloom_filter_slab_at(&bloom_filters, c);
@@ -195,16 +195,14 @@ struct bloom_filter *get_bloom_filter(struct repository *r,
        if (!filter->data) {
                load_commit_graph_info(r, c);
                if (commit_graph_position(c) != COMMIT_NOT_FROM_GRAPH &&
-                       r->objects->commit_graph->chunk_bloom_indexes) {
-                       if (load_bloom_filter_from_graph(r->objects->commit_graph, filter, c))
-                               return filter;
-                       else
-                               return NULL;
-               }
+                       r->objects->commit_graph->chunk_bloom_indexes)
+                       load_bloom_filter_from_graph(r->objects->commit_graph, filter, c);
        }
 
-       if (filter->data || !compute_if_not_present)
+       if (filter->data)
                return filter;
+       if (!compute_if_not_present)
+               return NULL;
 
        repo_diff_setup(r, &diffopt);
        diffopt.flags.recursive = 1;
index 09579e268df975767f88677a17c4971a3eb23860..7ca0fba1b8ed46a86290bd6ed966cb9aa8233de6 100644 (file)
@@ -175,10 +175,8 @@ int cmd_main(int argc, const char **argv)
        /* fopen doesn't offer us an O_EXCL alternative, except with glibc. */
        report = open(report_path.buf, O_CREAT | O_EXCL | O_WRONLY, 0666);
 
-       if (report < 0) {
-               UNLEAK(report_path);
+       if (report < 0)
                die(_("couldn't create a new file at '%s'"), report_path.buf);
-       }
 
        if (write_in_full(report, buffer.buf, buffer.len) < 0)
                die_errno(_("unable to write to %s"), report_path.buf);
index 298e0114f93166b7e3c1d3c2bc376a34afb7a671..b36a99eb7c847fe3f67a716316b148c347d1792b 100644 (file)
@@ -18,7 +18,7 @@
 #include "diffcore.h"
 #include "revision.h"
 #include "bulk-checkin.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "submodule.h"
 #include "add-interactive.h"
 
@@ -188,7 +188,7 @@ int run_add_interactive(const char *revision, const char *patch_mode,
                        const struct pathspec *pathspec)
 {
        int status, i;
-       struct argv_array argv = ARGV_ARRAY_INIT;
+       struct strvec argv = STRVEC_INIT;
        int use_builtin_add_i =
                git_env_bool("GIT_TEST_ADD_I_USE_BUILTIN", -1);
 
@@ -218,18 +218,18 @@ int run_add_interactive(const char *revision, const char *patch_mode,
                return !!run_add_p(the_repository, mode, revision, pathspec);
        }
 
-       argv_array_push(&argv, "add--interactive");
+       strvec_push(&argv, "add--interactive");
        if (patch_mode)
-               argv_array_push(&argv, patch_mode);
+               strvec_push(&argv, patch_mode);
        if (revision)
-               argv_array_push(&argv, revision);
-       argv_array_push(&argv, "--");
+               strvec_push(&argv, revision);
+       strvec_push(&argv, "--");
        for (i = 0; i < pathspec->nr; i++)
                /* pass original pathspec, to be re-parsed */
-               argv_array_push(&argv, pathspec->items[i].original);
+               strvec_push(&argv, pathspec->items[i].original);
 
-       status = run_command_v_opt(argv.argv, RUN_GIT_CMD);
-       argv_array_clear(&argv);
+       status = run_command_v_opt(argv.v, RUN_GIT_CMD);
+       strvec_clear(&argv);
        return status;
 }
 
@@ -534,11 +534,11 @@ int cmd_add(int argc, const char **argv, const char *prefix)
        die_in_unpopulated_submodule(&the_index, prefix);
        die_path_inside_submodule(&the_index, &pathspec);
 
+       dir_init(&dir);
        if (add_new_files) {
                int baselen;
 
                /* Set up the default git porcelain excludes */
-               memset(&dir, 0, sizeof(dir));
                if (!ignored_too) {
                        dir.flags |= DIR_COLLECT_IGNORED;
                        setup_standard_excludes(&dir);
@@ -611,7 +611,7 @@ finish:
                               COMMIT_LOCK | SKIP_IF_UNCHANGED))
                die(_("Unable to write new index file"));
 
+       dir_clear(&dir);
        UNLEAK(pathspec);
-       UNLEAK(dir);
        return exit_status;
 }
index 69e50de018ba01cb2243221f1c7b5d7617afc72d..dd4e6c2d9b7f478c322a469fd64cbaf3de285d17 100644 (file)
@@ -116,7 +116,7 @@ struct am_state {
        int keep; /* enum keep_type */
        int message_id;
        int scissors; /* enum scissors_type */
-       struct argv_array git_apply_opts;
+       struct strvec git_apply_opts;
        const char *resolvemsg;
        int committer_date_is_author_date;
        int ignore_date;
@@ -146,7 +146,7 @@ static void am_state_init(struct am_state *state)
 
        state->scissors = SCISSORS_UNSET;
 
-       argv_array_init(&state->git_apply_opts);
+       strvec_init(&state->git_apply_opts);
 
        if (!git_config_get_bool("commit.gpgsign", &gpgsign))
                state->sign_commit = gpgsign ? "" : NULL;
@@ -162,7 +162,7 @@ static void am_state_release(struct am_state *state)
        free(state->author_email);
        free(state->author_date);
        free(state->msg);
-       argv_array_clear(&state->git_apply_opts);
+       strvec_clear(&state->git_apply_opts);
 }
 
 /**
@@ -398,8 +398,8 @@ static void am_load(struct am_state *state)
                state->scissors = SCISSORS_UNSET;
 
        read_state_file(&sb, state, "apply-opt", 1);
-       argv_array_clear(&state->git_apply_opts);
-       if (sq_dequote_to_argv_array(sb.buf, &state->git_apply_opts) < 0)
+       strvec_clear(&state->git_apply_opts);
+       if (sq_dequote_to_strvec(sb.buf, &state->git_apply_opts) < 0)
                die(_("could not parse %s"), am_path(state, "apply-opt"));
 
        state->rebasing = !!file_exists(am_path(state, "rebasing"));
@@ -452,8 +452,8 @@ static int run_post_rewrite_hook(const struct am_state *state)
        if (!hook)
                return 0;
 
-       argv_array_push(&cp.args, hook);
-       argv_array_push(&cp.args, "rebase");
+       strvec_push(&cp.args, hook);
+       strvec_push(&cp.args, "rebase");
 
        cp.in = xopen(am_path(state, "rewritten"), O_RDONLY);
        cp.stdout_to_stderr = 1;
@@ -651,16 +651,16 @@ static int split_mail_mbox(struct am_state *state, const char **paths,
        int ret;
 
        cp.git_cmd = 1;
-       argv_array_push(&cp.args, "mailsplit");
-       argv_array_pushf(&cp.args, "-d%d", state->prec);
-       argv_array_pushf(&cp.args, "-o%s", state->dir);
-       argv_array_push(&cp.args, "-b");
+       strvec_push(&cp.args, "mailsplit");
+       strvec_pushf(&cp.args, "-d%d", state->prec);
+       strvec_pushf(&cp.args, "-o%s", state->dir);
+       strvec_push(&cp.args, "-b");
        if (keep_cr)
-               argv_array_push(&cp.args, "--keep-cr");
+               strvec_push(&cp.args, "--keep-cr");
        if (mboxrd)
-               argv_array_push(&cp.args, "--mboxrd");
-       argv_array_push(&cp.args, "--");
-       argv_array_pushv(&cp.args, paths);
+               strvec_push(&cp.args, "--mboxrd");
+       strvec_push(&cp.args, "--");
+       strvec_pushv(&cp.args, paths);
 
        ret = capture_command(&cp, &last, 8);
        if (ret)
@@ -787,7 +787,7 @@ static int split_mail_stgit_series(struct am_state *state, const char **paths,
        const char *series_dir;
        char *series_dir_buf;
        FILE *fp;
-       struct argv_array patches = ARGV_ARRAY_INIT;
+       struct strvec patches = STRVEC_INIT;
        struct strbuf sb = STRBUF_INIT;
        int ret;
 
@@ -805,16 +805,16 @@ static int split_mail_stgit_series(struct am_state *state, const char **paths,
                if (*sb.buf == '#')
                        continue; /* skip comment lines */
 
-               argv_array_push(&patches, mkpath("%s/%s", series_dir, sb.buf));
+               strvec_push(&patches, mkpath("%s/%s", series_dir, sb.buf));
        }
 
        fclose(fp);
        strbuf_release(&sb);
        free(series_dir_buf);
 
-       ret = split_mail_conv(stgit_patch_to_mail, state, patches.argv, keep_cr);
+       ret = split_mail_conv(stgit_patch_to_mail, state, patches.v, keep_cr);
 
-       argv_array_clear(&patches);
+       strvec_clear(&patches);
        return ret;
 }
 
@@ -1002,7 +1002,7 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,
        }
        write_state_text(state, "scissors", str);
 
-       sq_quote_argv(&sb, state->git_apply_opts.argv);
+       sq_quote_argv(&sb, state->git_apply_opts.v);
        write_state_text(state, "apply-opt", sb.buf);
 
        if (state->rebasing)
@@ -1390,8 +1390,8 @@ static int parse_mail_rebase(struct am_state *state, const char *mail)
  */
 static int run_apply(const struct am_state *state, const char *index_file)
 {
-       struct argv_array apply_paths = ARGV_ARRAY_INIT;
-       struct argv_array apply_opts = ARGV_ARRAY_INIT;
+       struct strvec apply_paths = STRVEC_INIT;
+       struct strvec apply_opts = STRVEC_INIT;
        struct apply_state apply_state;
        int res, opts_left;
        int force_apply = 0;
@@ -1400,10 +1400,10 @@ static int run_apply(const struct am_state *state, const char *index_file)
        if (init_apply_state(&apply_state, the_repository, NULL))
                BUG("init_apply_state() failed");
 
-       argv_array_push(&apply_opts, "apply");
-       argv_array_pushv(&apply_opts, state->git_apply_opts.argv);
+       strvec_push(&apply_opts, "apply");
+       strvec_pushv(&apply_opts, state->git_apply_opts.v);
 
-       opts_left = apply_parse_options(apply_opts.argc, apply_opts.argv,
+       opts_left = apply_parse_options(apply_opts.nr, apply_opts.v,
                                        &apply_state, &force_apply, &options,
                                        NULL);
 
@@ -1426,12 +1426,12 @@ static int run_apply(const struct am_state *state, const char *index_file)
        if (check_apply_state(&apply_state, force_apply))
                BUG("check_apply_state() failed");
 
-       argv_array_push(&apply_paths, am_path(state, "patch"));
+       strvec_push(&apply_paths, am_path(state, "patch"));
 
-       res = apply_all_patches(&apply_state, apply_paths.argc, apply_paths.argv, options);
+       res = apply_all_patches(&apply_state, apply_paths.nr, apply_paths.v, options);
 
-       argv_array_clear(&apply_paths);
-       argv_array_clear(&apply_opts);
+       strvec_clear(&apply_paths);
+       strvec_clear(&apply_opts);
        clear_apply_state(&apply_state);
 
        if (res)
@@ -1454,10 +1454,10 @@ static int build_fake_ancestor(const struct am_state *state, const char *index_f
        struct child_process cp = CHILD_PROCESS_INIT;
 
        cp.git_cmd = 1;
-       argv_array_push(&cp.args, "apply");
-       argv_array_pushv(&cp.args, state->git_apply_opts.argv);
-       argv_array_pushf(&cp.args, "--build-fake-ancestor=%s", index_file);
-       argv_array_push(&cp.args, am_path(state, "patch"));
+       strvec_push(&cp.args, "apply");
+       strvec_pushv(&cp.args, state->git_apply_opts.v);
+       strvec_pushf(&cp.args, "--build-fake-ancestor=%s", index_file);
+       strvec_push(&cp.args, am_path(state, "patch"));
 
        if (run_command(&cp))
                return -1;
@@ -1676,7 +1676,7 @@ static int do_interactive(struct am_state *state)
                        if (!pager)
                                pager = "cat";
                        prepare_pager_args(&cp, pager);
-                       argv_array_push(&cp.args, am_path(state, "patch"));
+                       strvec_push(&cp.args, am_path(state, "patch"));
                        run_command(&cp);
                }
        }
@@ -2346,7 +2346,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
                if (state.signoff == SIGNOFF_EXPLICIT)
                        am_append_signoff(&state);
        } else {
-               struct argv_array paths = ARGV_ARRAY_INIT;
+               struct strvec paths = STRVEC_INIT;
                int i;
 
                /*
@@ -2371,17 +2371,17 @@ int cmd_am(int argc, const char **argv, const char *prefix)
 
                for (i = 0; i < argc; i++) {
                        if (is_absolute_path(argv[i]) || !prefix)
-                               argv_array_push(&paths, argv[i]);
+                               strvec_push(&paths, argv[i]);
                        else
-                               argv_array_push(&paths, mkpath("%s/%s", prefix, argv[i]));
+                               strvec_push(&paths, mkpath("%s/%s", prefix, argv[i]));
                }
 
-               if (state.interactive && !paths.argc)
+               if (state.interactive && !paths.nr)
                        die(_("interactive mode requires patches on the command line"));
 
-               am_setup(&state, patch_format, paths.argv, keep_cr);
+               am_setup(&state, patch_format, paths.v, keep_cr);
 
-               argv_array_clear(&paths);
+               strvec_clear(&paths);
        }
 
        switch (resume.mode) {
index da413ae0d178b53d6b1e6c193577c23923255245..58ff977a2314e2878ee0c7d3bcd9874b71bfdeef 100644 (file)
@@ -5,18 +5,18 @@
  */
 #include "git-compat-util.h"
 #include "builtin.h"
-#include "argv-array.h"
+#include "strvec.h"
 
 int cmd_annotate(int argc, const char **argv, const char *prefix)
 {
-       struct argv_array args = ARGV_ARRAY_INIT;
+       struct strvec args = STRVEC_INIT;
        int i;
 
-       argv_array_pushl(&args, "annotate", "-c", NULL);
+       strvec_pushl(&args, "annotate", "-c", NULL);
 
        for (i = 1; i < argc; i++) {
-               argv_array_push(&args, argv[i]);
+               strvec_push(&args, argv[i]);
        }
 
-       return cmd_blame(args.argc, args.argv, prefix);
+       return cmd_blame(args.nr, args.v, prefix);
 }
index ec4996282e36e2edcd4109321f83b921a24c5a32..cdda279b23ca3c8ede39058a52a1b3a0f303b43d 100644 (file)
@@ -4,7 +4,7 @@
 #include "bisect.h"
 #include "refs.h"
 #include "dir.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "run-command.h"
 #include "prompt.h"
 #include "quote.h"
@@ -13,13 +13,13 @@ static GIT_PATH_FUNC(git_path_bisect_terms, "BISECT_TERMS")
 static GIT_PATH_FUNC(git_path_bisect_expected_rev, "BISECT_EXPECTED_REV")
 static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, "BISECT_ANCESTORS_OK")
 static GIT_PATH_FUNC(git_path_bisect_start, "BISECT_START")
-static GIT_PATH_FUNC(git_path_bisect_head, "BISECT_HEAD")
 static GIT_PATH_FUNC(git_path_bisect_log, "BISECT_LOG")
 static GIT_PATH_FUNC(git_path_head_name, "head-name")
 static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES")
+static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT")
 
 static const char * const git_bisect_helper_usage[] = {
-       N_("git bisect--helper --next-all [--no-checkout]"),
+       N_("git bisect--helper --next-all"),
        N_("git bisect--helper --write-terms <bad_term> <good_term>"),
        N_("git bisect--helper --bisect-clean-state"),
        N_("git bisect--helper --bisect-reset [<commit>]"),
@@ -28,7 +28,7 @@ static const char * const git_bisect_helper_usage[] = {
        N_("git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]"),
        N_("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]"),
        N_("git bisect--helper --bisect-start [--term-{old,good}=<term> --term-{new,bad}=<term>]"
-                                            "[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]"),
+                                           " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]"),
        NULL
 };
 
@@ -164,19 +164,19 @@ static int bisect_reset(const char *commit)
                strbuf_addstr(&branch, commit);
        }
 
-       if (!file_exists(git_path_bisect_head())) {
-               struct argv_array argv = ARGV_ARRAY_INIT;
+       if (!ref_exists("BISECT_HEAD")) {
+               struct strvec argv = STRVEC_INIT;
 
-               argv_array_pushl(&argv, "checkout", branch.buf, "--", NULL);
-               if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {
+               strvec_pushl(&argv, "checkout", branch.buf, "--", NULL);
+               if (run_command_v_opt(argv.v, RUN_GIT_CMD)) {
                        error(_("could not check out original"
                                " HEAD '%s'. Try 'git bisect"
                                " reset <commit>'."), branch.buf);
                        strbuf_release(&branch);
-                       argv_array_clear(&argv);
+                       strvec_clear(&argv);
                        return -1;
                }
-               argv_array_clear(&argv);
+               strvec_clear(&argv);
        }
 
        strbuf_release(&branch);
@@ -421,9 +421,10 @@ finish:
        return res;
 }
 
-static int bisect_start(struct bisect_terms *terms, int no_checkout,
-                       const char **argv, int argc)
+static int bisect_start(struct bisect_terms *terms, const char **argv, int argc)
 {
+       int no_checkout = 0;
+       int first_parent_only = 0;
        int i, has_double_dash = 0, must_write_terms = 0, bad_seen = 0;
        int flags, pathspec_pos, res = 0;
        struct string_list revs = STRING_LIST_INIT_DUP;
@@ -453,6 +454,8 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,
                        break;
                } else if (!strcmp(arg, "--no-checkout")) {
                        no_checkout = 1;
+               } else if (!strcmp(arg, "--first-parent")) {
+                       first_parent_only = 1;
                } else if (!strcmp(arg, "--term-good") ||
                         !strcmp(arg, "--term-old")) {
                        i++;
@@ -526,11 +529,11 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,
                strbuf_read_file(&start_head, git_path_bisect_start(), 0);
                strbuf_trim(&start_head);
                if (!no_checkout) {
-                       struct argv_array argv = ARGV_ARRAY_INIT;
+                       struct strvec argv = STRVEC_INIT;
 
-                       argv_array_pushl(&argv, "checkout", start_head.buf,
-                                        "--", NULL);
-                       if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {
+                       strvec_pushl(&argv, "checkout", start_head.buf,
+                                    "--", NULL);
+                       if (run_command_v_opt(argv.v, RUN_GIT_CMD)) {
                                res = error(_("checking out '%s' failed."
                                                 " Try 'git bisect start "
                                                 "<valid-branch>'."),
@@ -577,6 +580,9 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,
         */
        write_file(git_path_bisect_start(), "%s\n", start_head.buf);
 
+       if (first_parent_only)
+               write_file(git_path_bisect_first_parent(), "\n");
+
        if (no_checkout) {
                if (get_oid(start_head.buf, &oid) < 0) {
                        res = error(_("invalid ref: '%s'"), start_head.buf);
@@ -632,7 +638,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
                BISECT_TERMS,
                BISECT_START
        } cmdmode = 0;
-       int no_checkout = 0, res = 0, nolog = 0;
+       int res = 0, nolog = 0;
        struct option options[] = {
                OPT_CMDMODE(0, "next-all", &cmdmode,
                         N_("perform 'git bisect next'"), NEXT_ALL),
@@ -654,8 +660,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
                         N_("print out the bisect terms"), BISECT_TERMS),
                OPT_CMDMODE(0, "bisect-start", &cmdmode,
                         N_("start the bisect session"), BISECT_START),
-               OPT_BOOL(0, "no-checkout", &no_checkout,
-                        N_("update BISECT_HEAD instead of checking out the current commit")),
                OPT_BOOL(0, "no-log", &nolog,
                         N_("no log for BISECT_WRITE")),
                OPT_END()
@@ -671,7 +675,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
 
        switch (cmdmode) {
        case NEXT_ALL:
-               res = bisect_next_all(the_repository, prefix, no_checkout);
+               res = bisect_next_all(the_repository, prefix);
                break;
        case WRITE_TERMS:
                if (argc != 2)
@@ -713,7 +717,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
                break;
        case BISECT_START:
                set_terms(&terms, "bad", "good");
-               res = bisect_start(&terms, no_checkout, argv, argc);
+               res = bisect_start(&terms, argv, argc);
                break;
        default:
                return error("BUG: unknown subcommand '%d'", cmdmode);
index 94ef57c1cc304963452772e24125e5939dff0481..eb513fbe60c34a6de505a9b99da0ff033f612622 100644 (file)
@@ -842,7 +842,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
        const char *contents_from = NULL;
        const struct option options[] = {
                OPT_BOOL(0, "incremental", &incremental, N_("Show blame entries as we find them, incrementally")),
-               OPT_BOOL('b', NULL, &blank_boundary, N_("Show blank SHA-1 for boundary commits (Default: off)")),
+               OPT_BOOL('b', NULL, &blank_boundary, N_("Do not show object names of boundary commits (Default: off)")),
                OPT_BOOL(0, "root", &show_root, N_("Do not treat root commits as boundaries (Default: off)")),
                OPT_BOOL(0, "show-stats", &show_stats, N_("Show work cost statistics")),
                OPT_BOOL(0, "progress", &show_progress, N_("Force progress reporting")),
index f049d27a14405d540902ba5d368a59d670f7f614..ea6948110b0fc933c81585a33b67a1121acde35b 100644 (file)
@@ -1,5 +1,5 @@
 #include "builtin.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "parse-options.h"
 #include "cache.h"
 #include "bundle.h"
@@ -59,7 +59,8 @@ static int parse_options_cmd_bundle(int argc,
 static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
        int all_progress_implied = 0;
        int progress = isatty(STDERR_FILENO);
-       struct argv_array pack_opts;
+       struct strvec pack_opts;
+       int version = -1;
 
        struct option options[] = {
                OPT_SET_INT('q', "quiet", &progress,
@@ -71,6 +72,8 @@ static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
                OPT_BOOL(0, "all-progress-implied",
                         &all_progress_implied,
                         N_("similar to --all-progress when progress meter is shown")),
+               OPT_INTEGER(0, "version", &version,
+                           N_("specify bundle format version")),
                OPT_END()
        };
        const char* bundle_file;
@@ -79,19 +82,19 @@ static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
                        builtin_bundle_create_usage, options, &bundle_file);
        /* bundle internals use argv[1] as further parameters */
 
-       argv_array_init(&pack_opts);
+       strvec_init(&pack_opts);
        if (progress == 0)
-               argv_array_push(&pack_opts, "--quiet");
+               strvec_push(&pack_opts, "--quiet");
        else if (progress == 1)
-               argv_array_push(&pack_opts, "--progress");
+               strvec_push(&pack_opts, "--progress");
        else if (progress == 2)
-               argv_array_push(&pack_opts, "--all-progress");
+               strvec_push(&pack_opts, "--all-progress");
        if (progress && all_progress_implied)
-               argv_array_push(&pack_opts, "--all-progress-implied");
+               strvec_push(&pack_opts, "--all-progress-implied");
 
        if (!startup_info->have_repository)
                die(_("Need a repository to create a bundle."));
-       return !!create_bundle(the_repository, bundle_file, argc, argv, &pack_opts);
+       return !!create_bundle(the_repository, bundle_file, argc, argv, &pack_opts, version);
 }
 
 static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {
index ea5d0ae3a6a6fff59424909b8be47aaabb824b7c..3c652748d58c69dec4378d01de58212f65763328 100644 (file)
@@ -180,7 +180,7 @@ int cmd_check_ignore(int argc, const char **argv, const char *prefix)
        if (!no_index && read_cache() < 0)
                die(_("index file corrupt"));
 
-       memset(&dir, 0, sizeof(dir));
+       dir_init(&dir);
        setup_standard_excludes(&dir);
 
        if (stdin_paths) {
@@ -190,7 +190,7 @@ int cmd_check_ignore(int argc, const char **argv, const char *prefix)
                maybe_flush_or_die(stdout, "ignore to stdout");
        }
 
-       clear_directory(&dir);
+       dir_clear(&dir);
 
        return !num_ignored;
 }
index af849c644fec1852845b1dfdb6ce8daa903e0fb5..6ec82097a2a29c73d0b69a9329c93d8057dbb955 100644 (file)
@@ -239,6 +239,8 @@ static int checkout_merged(int pos, const struct checkout *state, int *nr_checko
        mmbuffer_t result_buf;
        struct object_id threeway[3];
        unsigned mode = 0;
+       struct ll_merge_options ll_opts;
+       int renormalize = 0;
 
        memset(threeway, 0, sizeof(threeway));
        while (pos < active_nr) {
@@ -259,13 +261,12 @@ static int checkout_merged(int pos, const struct checkout *state, int *nr_checko
        read_mmblob(&ours, &threeway[1]);
        read_mmblob(&theirs, &threeway[2]);
 
-       /*
-        * NEEDSWORK: re-create conflicts from merges with
-        * merge.renormalize set, too
-        */
+       memset(&ll_opts, 0, sizeof(ll_opts));
+       git_config_get_bool("merge.renormalize", &renormalize);
+       ll_opts.renormalize = renormalize;
        status = ll_merge(&result_buf, path, &ancestor, "base",
                          &ours, "ours", &theirs, "theirs",
-                         state->istate, NULL);
+                         state->istate, &ll_opts);
        free(ancestor.ptr);
        free(ours.ptr);
        free(theirs.ptr);
@@ -771,13 +772,6 @@ static int merge_working_tree(const struct checkout_opts *opts,
                         */
 
                        add_files_to_cache(NULL, NULL, 0);
-                       /*
-                        * NEEDSWORK: carrying over local changes
-                        * when branches have different end-of-line
-                        * normalization (or clean+smudge rules) is
-                        * a pain; plumb in an option to set
-                        * o.renormalize?
-                        */
                        init_merge_options(&o, the_repository);
                        o.verbosity = 0;
                        work = write_in_core_index_as_tree(the_repository);
@@ -1126,8 +1120,10 @@ static void setup_new_branch_info_and_source_tree(
        if (!check_refname_format(new_branch_info->path, 0) &&
            !read_ref(new_branch_info->path, &branch_rev))
                oidcpy(rev, &branch_rev);
-       else
+       else {
+               free((char *)new_branch_info->path);
                new_branch_info->path = NULL; /* not an existing branch */
+       }
 
        new_branch_info->commit = lookup_commit_reference_gently(the_repository, rev, 1);
        if (!new_branch_info->commit) {
@@ -1713,6 +1709,8 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
                die(_("--pathspec-file-nul requires --pathspec-from-file"));
        }
 
+       opts->pathspec.recursive = 1;
+
        if (opts->pathspec.nr) {
                if (1 < !!opts->writeout_stage + !!opts->force + !!opts->merge)
                        die(_("git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
index 5a9c29a558bb1efc383b41256972b3113845be4e..e53ea52d89bbb473e26666e453d549e6720a9cc2 100644 (file)
@@ -667,7 +667,7 @@ static int filter_by_patterns_cmd(void)
                if (!confirm.len)
                        break;
 
-               memset(&dir, 0, sizeof(dir));
+               dir_init(&dir);
                pl = add_pattern_list(&dir, EXC_CMDL, "manual exclude");
                ignore_list = strbuf_split_max(&confirm, ' ', 0);
 
@@ -698,7 +698,7 @@ static int filter_by_patterns_cmd(void)
                }
 
                strbuf_list_free(ignore_list);
-               clear_directory(&dir);
+               dir_clear(&dir);
        }
 
        strbuf_release(&confirm);
@@ -923,7 +923,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
        argc = parse_options(argc, argv, prefix, options, builtin_clean_usage,
                             0);
 
-       memset(&dir, 0, sizeof(dir));
+       dir_init(&dir);
        if (!interactive && !dry_run && !force) {
                if (config_set)
                        die(_("clean.requireForce set to true and neither -i, -n, nor -f given; "
@@ -1021,11 +1021,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
                string_list_append(&del_list, rel);
        }
 
-       for (i = 0; i < dir.nr; i++)
-               free(dir.entries[i]);
-
-       for (i = 0; i < dir.ignored_nr; i++)
-               free(dir.ignored[i]);
+       dir_clear(&dir);
 
        if (interactive && del_list.nr > 0)
                interactive_main_loop();
index bef70745c09a260442685eef111c9914b4a78d0a..b087ee40c28776685e40467785d693e24f1c0cb5 100644 (file)
@@ -742,9 +742,9 @@ static void update_head(const struct ref *our, const struct ref *remote,
 
 static int git_sparse_checkout_init(const char *repo)
 {
-       struct argv_array argv = ARGV_ARRAY_INIT;
+       struct strvec argv = STRVEC_INIT;
        int result = 0;
-       argv_array_pushl(&argv, "-C", repo, "sparse-checkout", "init", NULL);
+       strvec_pushl(&argv, "-C", repo, "sparse-checkout", "init", NULL);
 
        /*
         * We must apply the setting in the current process
@@ -752,12 +752,12 @@ static int git_sparse_checkout_init(const char *repo)
         */
        core_apply_sparse_checkout = 1;
 
-       if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {
+       if (run_command_v_opt(argv.v, RUN_GIT_CMD)) {
                error(_("failed to initialize sparse-checkout"));
                result = 1;
        }
 
-       argv_array_clear(&argv);
+       strvec_clear(&argv);
        return result;
 }
 
@@ -819,33 +819,33 @@ static int checkout(int submodule_progress)
                           oid_to_hex(&oid), "1", NULL);
 
        if (!err && (option_recurse_submodules.nr > 0)) {
-               struct argv_array args = ARGV_ARRAY_INIT;
-               argv_array_pushl(&args, "submodule", "update", "--require-init", "--recursive", NULL);
+               struct strvec args = STRVEC_INIT;
+               strvec_pushl(&args, "submodule", "update", "--require-init", "--recursive", NULL);
 
                if (option_shallow_submodules == 1)
-                       argv_array_push(&args, "--depth=1");
+                       strvec_push(&args, "--depth=1");
 
                if (max_jobs != -1)
-                       argv_array_pushf(&args, "--jobs=%d", max_jobs);
+                       strvec_pushf(&args, "--jobs=%d", max_jobs);
 
                if (submodule_progress)
-                       argv_array_push(&args, "--progress");
+                       strvec_push(&args, "--progress");
 
                if (option_verbosity < 0)
-                       argv_array_push(&args, "--quiet");
+                       strvec_push(&args, "--quiet");
 
                if (option_remote_submodules) {
-                       argv_array_push(&args, "--remote");
-                       argv_array_push(&args, "--no-fetch");
+                       strvec_push(&args, "--remote");
+                       strvec_push(&args, "--no-fetch");
                }
 
                if (option_single_branch >= 0)
-                       argv_array_push(&args, option_single_branch ?
+                       strvec_push(&args, option_single_branch ?
                                               "--single-branch" :
                                               "--no-single-branch");
 
-               err = run_command_v_opt(args.argv, RUN_GIT_CMD);
-               argv_array_clear(&args);
+               err = run_command_v_opt(args.v, RUN_GIT_CMD);
+               strvec_clear(&args);
        }
 
        return err;
@@ -946,7 +946,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        int is_bundle = 0, is_local;
        const char *repo_name, *repo, *work_tree, *git_dir;
        char *path, *dir, *display_repo = NULL;
-       int dest_exists;
+       int dest_exists, real_dest_exists = 0;
        const struct ref *refs, *remote_head;
        const struct ref *remote_head_points_at;
        const struct ref *our_head_points_at;
@@ -961,7 +961,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        int err = 0, complete_refs_before_fetch = 1;
        int submodule_progress;
 
-       struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
+       struct strvec ref_prefixes = STRVEC_INIT;
 
        packet_trace_identity("clone");
        argc = parse_options(argc, argv, prefix, builtin_clone_options,
@@ -1021,6 +1021,14 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                die(_("destination path '%s' already exists and is not "
                        "an empty directory."), dir);
 
+       if (real_git_dir) {
+               real_dest_exists = path_exists(real_git_dir);
+               if (real_dest_exists && !is_empty_dir(real_git_dir))
+                       die(_("repository path '%s' already exists and is not "
+                               "an empty directory."), real_git_dir);
+       }
+
+
        strbuf_addf(&reflog_msg, "clone: from %s",
                    display_repo ? display_repo : repo);
        free(display_repo);
@@ -1057,7 +1065,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        }
 
        if (real_git_dir) {
-               if (path_exists(real_git_dir))
+               if (real_dest_exists)
                        junk_git_dir_flags |= REMOVE_DIR_KEEP_TOPLEVEL;
                junk_git_dir = real_git_dir;
        } else {
@@ -1211,12 +1219,12 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                transport->smart_options->check_self_contained_and_connected = 1;
 
 
-       argv_array_push(&ref_prefixes, "HEAD");
+       strvec_push(&ref_prefixes, "HEAD");
        refspec_ref_prefixes(&remote->fetch, &ref_prefixes);
        if (option_branch)
                expand_ref_prefix(&ref_prefixes, option_branch);
        if (!option_no_tags)
-               argv_array_push(&ref_prefixes, "refs/tags/");
+               strvec_push(&ref_prefixes, "refs/tags/");
 
        refs = transport_get_remote_refs(transport, &ref_prefixes);
 
@@ -1327,6 +1335,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        strbuf_release(&default_refspec);
        junk_mode = JUNK_LEAVE_ALL;
 
-       argv_array_clear(&ref_prefixes);
+       strvec_clear(&ref_prefixes);
        return err;
 }
index 16c9f6101aa7627f5914cc7f08d2ddd3af96cc1e..523501f21743bb039df6f951975f705d6689889f 100644 (file)
@@ -201,6 +201,7 @@ static int graph_write(int argc, const char **argv)
        };
 
        opts.progress = isatty(2);
+       opts.enable_changed_paths = -1;
        split_opts.size_multiple = 2;
        split_opts.max_commits = 0;
        split_opts.expire_time = 0;
@@ -221,7 +222,9 @@ static int graph_write(int argc, const char **argv)
                flags |= COMMIT_GRAPH_WRITE_SPLIT;
        if (opts.progress)
                flags |= COMMIT_GRAPH_WRITE_PROGRESS;
-       if (opts.enable_changed_paths ||
+       if (!opts.enable_changed_paths)
+               flags |= COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS;
+       if (opts.enable_changed_paths == 1 ||
            git_env_bool(GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS, 0))
                flags |= COMMIT_GRAPH_WRITE_BLOOM_FILTERS;
 
index d1b7396052a2449f3ebda88df62cf7b89499090f..671721c385d14f147210eeef977db7fec90645a9 100644 (file)
@@ -847,21 +847,19 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
                        if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS &&
                                !merge_contains_scissors)
                                wt_status_add_cut_line(s->fp);
-                       status_printf_ln(s, GIT_COLOR_NORMAL,
-                           whence == FROM_MERGE
-                               ? _("\n"
-                                       "It looks like you may be committing a merge.\n"
-                                       "If this is not correct, please remove the file\n"
-                                       "       %s\n"
-                                       "and try again.\n")
-                               : _("\n"
-                                       "It looks like you may be committing a cherry-pick.\n"
-                                       "If this is not correct, please remove the file\n"
-                                       "       %s\n"
-                                       "and try again.\n"),
+                       status_printf_ln(
+                               s, GIT_COLOR_NORMAL,
                                whence == FROM_MERGE ?
-                                       git_path_merge_head(the_repository) :
-                                       git_path_cherry_pick_head(the_repository));
+                                             _("\n"
+                                         "It looks like you may be committing a merge.\n"
+                                         "If this is not correct, please run\n"
+                                         "     git update-ref -d MERGE_HEAD\n"
+                                         "and try again.\n") :
+                                             _("\n"
+                                         "It looks like you may be committing a cherry-pick.\n"
+                                         "If this is not correct, please run\n"
+                                         "     git update-ref -d CHERRY_PICK_HEAD\n"
+                                         "and try again.\n"));
                }
 
                fprintf(s->fp, "\n");
@@ -1005,15 +1003,15 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
                return 0;
 
        if (use_editor) {
-               struct argv_array env = ARGV_ARRAY_INIT;
+               struct strvec env = STRVEC_INIT;
 
-               argv_array_pushf(&env, "GIT_INDEX_FILE=%s", index_file);
-               if (launch_editor(git_path_commit_editmsg(), NULL, env.argv)) {
+               strvec_pushf(&env, "GIT_INDEX_FILE=%s", index_file);
+               if (launch_editor(git_path_commit_editmsg(), NULL, env.v)) {
                        fprintf(stderr,
                        _("Please supply the message using either -m or -F option.\n"));
                        exit(1);
                }
-               argv_array_clear(&env);
+               strvec_clear(&env);
        }
 
        if (!no_verify &&
index 21d2cb9e57f4bf5c33f47989128710411c431d5d..7668591d575acc3fe744763b7e53128c76aaf862 100644 (file)
@@ -12,7 +12,7 @@
 #include "revision.h"
 #include "diff.h"
 #include "hashmap.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "run-command.h"
 #include "object-store.h"
 #include "list-objects.h"
@@ -501,15 +501,15 @@ static void process_object(struct object *obj, const char *path, void *data)
 static void describe_blob(struct object_id oid, struct strbuf *dst)
 {
        struct rev_info revs;
-       struct argv_array args = ARGV_ARRAY_INIT;
+       struct strvec args = STRVEC_INIT;
        struct process_commit_data pcd = { null_oid, oid, dst, &revs};
 
-       argv_array_pushl(&args, "internal: The first arg is not parsed",
-               "--objects", "--in-commit-order", "--reverse", "HEAD",
-               NULL);
+       strvec_pushl(&args, "internal: The first arg is not parsed",
+                    "--objects", "--in-commit-order", "--reverse", "HEAD",
+                    NULL);
 
        repo_init_revisions(the_repository, &revs, NULL);
-       if (setup_revisions(args.argc, args.argv, &revs, NULL) > 1)
+       if (setup_revisions(args.nr, args.v, &revs, NULL) > 1)
                BUG("setup_revisions could not handle all args?");
 
        if (prepare_revision_walk(&revs))
@@ -594,26 +594,26 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 
        if (contains) {
                struct string_list_item *item;
-               struct argv_array args;
+               struct strvec args;
 
-               argv_array_init(&args);
-               argv_array_pushl(&args, "name-rev",
-                                "--peel-tag", "--name-only", "--no-undefined",
-                                NULL);
+               strvec_init(&args);
+               strvec_pushl(&args, "name-rev",
+                            "--peel-tag", "--name-only", "--no-undefined",
+                            NULL);
                if (always)
-                       argv_array_push(&args, "--always");
+                       strvec_push(&args, "--always");
                if (!all) {
-                       argv_array_push(&args, "--tags");
+                       strvec_push(&args, "--tags");
                        for_each_string_list_item(item, &patterns)
-                               argv_array_pushf(&args, "--refs=refs/tags/%s", item->string);
+                               strvec_pushf(&args, "--refs=refs/tags/%s", item->string);
                        for_each_string_list_item(item, &exclude_patterns)
-                               argv_array_pushf(&args, "--exclude=refs/tags/%s", item->string);
+                               strvec_pushf(&args, "--exclude=refs/tags/%s", item->string);
                }
                if (argc)
-                       argv_array_pushv(&args, argv);
+                       strvec_pushv(&args, argv);
                else
-                       argv_array_push(&args, "HEAD");
-               return cmd_name_rev(args.argc, args.argv, prefix);
+                       strvec_push(&args, "HEAD");
+               return cmd_name_rev(args.nr, args.v, prefix);
        }
 
        hashmap_init(&names, commit_name_neq, NULL, 0);
@@ -624,7 +624,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
        if (argc == 0) {
                if (broken) {
                        struct child_process cp = CHILD_PROCESS_INIT;
-                       argv_array_pushv(&cp.args, diff_index_args);
+                       strvec_pushv(&cp.args, diff_index_args);
                        cp.git_cmd = 1;
                        cp.no_stdin = 1;
                        cp.no_stdout = 1;
@@ -646,7 +646,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
                } else if (dirty) {
                        struct lock_file index_lock = LOCK_INIT;
                        struct rev_info revs;
-                       struct argv_array args = ARGV_ARRAY_INIT;
+                       struct strvec args = STRVEC_INIT;
                        int fd, result;
 
                        setup_work_tree();
@@ -658,8 +658,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
                                repo_update_index_if_able(the_repository, &index_lock);
 
                        repo_init_revisions(the_repository, &revs, prefix);
-                       argv_array_pushv(&args, diff_index_args);
-                       if (setup_revisions(args.argc, args.argv, &revs, NULL) != 1)
+                       strvec_pushv(&args, diff_index_args);
+                       if (setup_revisions(args.nr, args.v, &revs, NULL) != 1)
                                BUG("malformed internal diff-index command line");
                        result = run_diff_index(&revs, 0);
 
index c280e682b2aec8ba8d136576d2c3039b1d62b985..7ac432b88193e7468048821a372dae8c2a81919a 100644 (file)
@@ -18,7 +18,7 @@
 #include "run-command.h"
 #include "exec-cmd.h"
 #include "parse-options.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "strbuf.h"
 #include "lockfile.h"
 #include "object-store.h"
@@ -210,10 +210,10 @@ static void changed_files(struct hashmap *result, const char *index_path,
        strbuf_addf(&index_env, "GIT_INDEX_FILE=%s", index_path);
        env[0] = index_env.buf;
 
-       argv_array_pushl(&update_index.args,
-                        "--git-dir", git_dir, "--work-tree", workdir,
-                        "update-index", "--really-refresh", "-q",
-                        "--unmerged", NULL);
+       strvec_pushl(&update_index.args,
+                    "--git-dir", git_dir, "--work-tree", workdir,
+                    "update-index", "--really-refresh", "-q",
+                    "--unmerged", NULL);
        update_index.no_stdin = 1;
        update_index.no_stdout = 1;
        update_index.no_stderr = 1;
@@ -225,9 +225,9 @@ static void changed_files(struct hashmap *result, const char *index_path,
        /* Ignore any errors of update-index */
        run_command(&update_index);
 
-       argv_array_pushl(&diff_files.args,
-                        "--git-dir", git_dir, "--work-tree", workdir,
-                        "diff-files", "--name-only", "-z", NULL);
+       strvec_pushl(&diff_files.args,
+                    "--git-dir", git_dir, "--work-tree", workdir,
+                    "diff-files", "--name-only", "-z", NULL);
        diff_files.no_stdin = 1;
        diff_files.git_cmd = 1;
        diff_files.use_shell = 0;
@@ -393,10 +393,10 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
        child.clean_on_exit = 1;
        child.dir = prefix;
        child.out = -1;
-       argv_array_pushl(&child.args, "diff", "--raw", "--no-abbrev", "-z",
-                        NULL);
+       strvec_pushl(&child.args, "diff", "--raw", "--no-abbrev", "-z",
+                    NULL);
        for (i = 0; i < argc; i++)
-               argv_array_push(&child.args, argv[i]);
+               strvec_push(&child.args, argv[i]);
        if (start_command(&child))
                die("could not obtain raw diff");
        fp = xfdopen(child.out, "r");
@@ -667,7 +667,7 @@ finish:
 static int run_file_diff(int prompt, const char *prefix,
                         int argc, const char **argv)
 {
-       struct argv_array args = ARGV_ARRAY_INIT;
+       struct strvec args = STRVEC_INIT;
        const char *env[] = {
                "GIT_PAGER=", "GIT_EXTERNAL_DIFF=git-difftool--helper", NULL,
                NULL
@@ -680,10 +680,10 @@ static int run_file_diff(int prompt, const char *prefix,
                env[2] = "GIT_DIFFTOOL_NO_PROMPT=true";
 
 
-       argv_array_push(&args, "diff");
+       strvec_push(&args, "diff");
        for (i = 0; i < argc; i++)
-               argv_array_push(&args, argv[i]);
-       ret = run_command_v_opt_cd_env(args.argv, RUN_GIT_CMD, prefix, env);
+               strvec_push(&args, argv[i]);
+       ret = run_command_v_opt_cd_env(args.v, RUN_GIT_CMD, prefix, env);
        exit(ret);
 }
 
index 82ac4be8a5200c7f6ac89c07cb486ac74f548ea3..0f23dd4b8ce942dae6b9a5a0ee6352b225b99e43 100644 (file)
@@ -19,7 +19,7 @@
 #include "submodule-config.h"
 #include "submodule.h"
 #include "connected.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "utf8.h"
 #include "packfile.h"
 #include "list-objects-filter-options.h"
@@ -56,6 +56,7 @@ static int prune_tags = -1; /* unspecified */
 #define PRUNE_TAGS_BY_DEFAULT 0 /* do we prune tags by default? */
 
 static int all, append, dry_run, force, keep, multiple, update_head_ok;
+static int write_fetch_head = 1;
 static int verbosity, deepen_relative, set_upstream;
 static int progress = -1;
 static int enable_auto_gc = 1;
@@ -162,6 +163,8 @@ static struct option builtin_fetch_options[] = {
                    PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules),
        OPT_BOOL(0, "dry-run", &dry_run,
                 N_("dry run")),
+       OPT_BOOL(0, "write-fetch-head", &write_fetch_head,
+                N_("write fetched references to the FETCH_HEAD file")),
        OPT_BOOL('k', "keep", &keep, N_("keep downloaded pack")),
        OPT_BOOL('u', "update-head-ok", &update_head_ok,
                    N_("allow updating of HEAD ref")),
@@ -645,7 +648,7 @@ static void prepare_format_display(struct ref *ref_map)
        struct ref *rm;
        const char *format = "full";
 
-       git_config_get_string_const("fetch.output", &format);
+       git_config_get_string_tmp("fetch.output", &format);
        if (!strcasecmp(format, "full"))
                compact_format = 0;
        else if (!strcasecmp(format, "compact"))
@@ -893,7 +896,9 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
        const char *what, *kind;
        struct ref *rm;
        char *url;
-       const char *filename = dry_run ? "/dev/null" : git_path_fetch_head(the_repository);
+       const char *filename = (!write_fetch_head
+                               ? "/dev/null"
+                               : git_path_fetch_head(the_repository));
        int want_status;
        int summary_width = transport_summary_width(ref_map);
 
@@ -1316,7 +1321,7 @@ static int do_fetch(struct transport *transport,
        int autotags = (transport->remote->fetch_tags == 1);
        int retcode = 0;
        const struct ref *remote_refs;
-       struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
+       struct strvec ref_prefixes = STRVEC_INIT;
        int must_list_refs = 1;
 
        if (tags == TAGS_DEFAULT) {
@@ -1327,7 +1332,7 @@ static int do_fetch(struct transport *transport,
        }
 
        /* if not appending, truncate FETCH_HEAD */
-       if (!append && !dry_run) {
+       if (!append && write_fetch_head) {
                retcode = truncate_fetch_head();
                if (retcode)
                        goto cleanup;
@@ -1354,8 +1359,8 @@ static int do_fetch(struct transport *transport,
 
        if (tags == TAGS_SET || tags == TAGS_DEFAULT) {
                must_list_refs = 1;
-               if (ref_prefixes.argc)
-                       argv_array_push(&ref_prefixes, "refs/tags/");
+               if (ref_prefixes.nr)
+                       strvec_push(&ref_prefixes, "refs/tags/");
        }
 
        if (must_list_refs) {
@@ -1365,7 +1370,7 @@ static int do_fetch(struct transport *transport,
        } else
                remote_refs = NULL;
 
-       argv_array_clear(&ref_prefixes);
+       strvec_clear(&ref_prefixes);
 
        ref_map = get_ref_map(transport->remote, remote_refs, rs,
                              tags, &autotags);
@@ -1503,34 +1508,34 @@ static int add_remote_or_group(const char *name, struct string_list *list)
        return 1;
 }
 
-static void add_options_to_argv(struct argv_array *argv)
+static void add_options_to_argv(struct strvec *argv)
 {
        if (dry_run)
-               argv_array_push(argv, "--dry-run");
+               strvec_push(argv, "--dry-run");
        if (prune != -1)
-               argv_array_push(argv, prune ? "--prune" : "--no-prune");
+               strvec_push(argv, prune ? "--prune" : "--no-prune");
        if (prune_tags != -1)
-               argv_array_push(argv, prune_tags ? "--prune-tags" : "--no-prune-tags");
+               strvec_push(argv, prune_tags ? "--prune-tags" : "--no-prune-tags");
        if (update_head_ok)
-               argv_array_push(argv, "--update-head-ok");
+               strvec_push(argv, "--update-head-ok");
        if (force)
-               argv_array_push(argv, "--force");
+               strvec_push(argv, "--force");
        if (keep)
-               argv_array_push(argv, "--keep");
+               strvec_push(argv, "--keep");
        if (recurse_submodules == RECURSE_SUBMODULES_ON)
-               argv_array_push(argv, "--recurse-submodules");
+               strvec_push(argv, "--recurse-submodules");
        else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)
-               argv_array_push(argv, "--recurse-submodules=on-demand");
+               strvec_push(argv, "--recurse-submodules=on-demand");
        if (tags == TAGS_SET)
-               argv_array_push(argv, "--tags");
+               strvec_push(argv, "--tags");
        else if (tags == TAGS_UNSET)
-               argv_array_push(argv, "--no-tags");
+               strvec_push(argv, "--no-tags");
        if (verbosity >= 2)
-               argv_array_push(argv, "-v");
+               strvec_push(argv, "-v");
        if (verbosity >= 1)
-               argv_array_push(argv, "-v");
+               strvec_push(argv, "-v");
        else if (verbosity < 0)
-               argv_array_push(argv, "-q");
+               strvec_push(argv, "-q");
 
 }
 
@@ -1554,8 +1559,8 @@ static int fetch_next_remote(struct child_process *cp, struct strbuf *out,
        remote = state->remotes->items[state->next++].string;
        *task_cb = remote;
 
-       argv_array_pushv(&cp->args, state->argv);
-       argv_array_push(&cp->args, remote);
+       strvec_pushv(&cp->args, state->argv);
+       strvec_push(&cp->args, remote);
        cp->git_cmd = 1;
 
        if (verbosity >= 0)
@@ -1592,22 +1597,22 @@ static int fetch_finished(int result, struct strbuf *out,
 static int fetch_multiple(struct string_list *list, int max_children)
 {
        int i, result = 0;
-       struct argv_array argv = ARGV_ARRAY_INIT;
+       struct strvec argv = STRVEC_INIT;
 
-       if (!append && !dry_run) {
+       if (!append && write_fetch_head) {
                int errcode = truncate_fetch_head();
                if (errcode)
                        return errcode;
        }
 
-       argv_array_pushl(&argv, "fetch", "--append", "--no-auto-gc",
-                       "--no-write-commit-graph", NULL);
+       strvec_pushl(&argv, "fetch", "--append", "--no-auto-gc",
+                    "--no-write-commit-graph", NULL);
        add_options_to_argv(&argv);
 
        if (max_children != 1 && list->nr != 1) {
-               struct parallel_fetch_state state = { argv.argv, list, 0, 0 };
+               struct parallel_fetch_state state = { argv.v, list, 0, 0 };
 
-               argv_array_push(&argv, "--end-of-options");
+               strvec_push(&argv, "--end-of-options");
                result = run_processes_parallel_tr2(max_children,
                                                    &fetch_next_remote,
                                                    &fetch_failed_to_start,
@@ -1620,17 +1625,17 @@ static int fetch_multiple(struct string_list *list, int max_children)
        } else
                for (i = 0; i < list->nr; i++) {
                        const char *name = list->items[i].string;
-                       argv_array_push(&argv, name);
+                       strvec_push(&argv, name);
                        if (verbosity >= 0)
                                printf(_("Fetching %s\n"), name);
-                       if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {
+                       if (run_command_v_opt(argv.v, RUN_GIT_CMD)) {
                                error(_("Could not fetch %s"), name);
                                result = 1;
                        }
-                       argv_array_pop(&argv);
+                       strvec_pop(&argv);
                }
 
-       argv_array_clear(&argv);
+       strvec_clear(&argv);
        return !!result;
 }
 
@@ -1795,6 +1800,10 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        if (depth || deepen_since || deepen_not.nr)
                deepen = 1;
 
+       /* FETCH_HEAD never gets updated in --dry-run mode */
+       if (dry_run)
+               write_fetch_head = 0;
+
        if (all) {
                if (argc == 1)
                        die(_("fetch --all does not take a repository argument"));
@@ -1844,7 +1853,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        }
 
        if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) {
-               struct argv_array options = ARGV_ARRAY_INIT;
+               struct strvec options = STRVEC_INIT;
                int max_children = max_jobs;
 
                if (max_children < 0)
@@ -1860,7 +1869,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
                                                    recurse_submodules_default,
                                                    verbosity < 0,
                                                    max_children);
-               argv_array_clear(&options);
+               strvec_clear(&options);
        }
 
        string_list_clear(&list, 0);
index 37aa07da78ebe9130c4d48865810bfc87d9f4ea0..fbf26cafcfd7d42fa779f449cf53eb7d9a6d5ea0 100644 (file)
@@ -168,7 +168,7 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt
                return 0;
 
        if (!(obj->flags & HAS_OBJ)) {
-               if (parent && !has_object_file(&obj->oid)) {
+               if (parent && !has_object(the_repository, &obj->oid, 1)) {
                        printf_ln(_("broken link from %7s %s\n"
                                    "              to %7s %s"),
                                  printable_type(&parent->oid, parent->type),
index 8e0b9cf41b3d3f43c7e13677468ca7099ea3fe9f..aafa0946f5245792a573c6e8d0326a72fa815df7 100644 (file)
@@ -18,7 +18,7 @@
 #include "parse-options.h"
 #include "run-command.h"
 #include "sigchain.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "commit.h"
 #include "commit-graph.h"
 #include "packfile.h"
@@ -50,12 +50,12 @@ static const char *prune_worktrees_expire = "3.months.ago";
 static unsigned long big_pack_threshold;
 static unsigned long max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE;
 
-static struct argv_array pack_refs_cmd = ARGV_ARRAY_INIT;
-static struct argv_array reflog = ARGV_ARRAY_INIT;
-static struct argv_array repack = ARGV_ARRAY_INIT;
-static struct argv_array prune = ARGV_ARRAY_INIT;
-static struct argv_array prune_worktrees = ARGV_ARRAY_INIT;
-static struct argv_array rerere = ARGV_ARRAY_INIT;
+static struct strvec pack_refs_cmd = STRVEC_INIT;
+static struct strvec reflog = STRVEC_INIT;
+static struct strvec repack = STRVEC_INIT;
+static struct strvec prune = STRVEC_INIT;
+static struct strvec prune_worktrees = STRVEC_INIT;
+static struct strvec rerere = STRVEC_INIT;
 
 static struct tempfile *pidfile;
 static struct lock_file log_lock;
@@ -311,18 +311,18 @@ static uint64_t estimate_repack_memory(struct packed_git *pack)
 
 static int keep_one_pack(struct string_list_item *item, void *data)
 {
-       argv_array_pushf(&repack, "--keep-pack=%s", basename(item->string));
+       strvec_pushf(&repack, "--keep-pack=%s", basename(item->string));
        return 0;
 }
 
 static void add_repack_all_option(struct string_list *keep_pack)
 {
        if (prune_expire && !strcmp(prune_expire, "now"))
-               argv_array_push(&repack, "-a");
+               strvec_push(&repack, "-a");
        else {
-               argv_array_push(&repack, "-A");
+               strvec_push(&repack, "-A");
                if (prune_expire)
-                       argv_array_pushf(&repack, "--unpack-unreachable=%s", prune_expire);
+                       strvec_pushf(&repack, "--unpack-unreachable=%s", prune_expire);
        }
 
        if (keep_pack)
@@ -331,7 +331,7 @@ static void add_repack_all_option(struct string_list *keep_pack)
 
 static void add_repack_incremental_option(void)
 {
-       argv_array_push(&repack, "--no-write-bitmap-index");
+       strvec_push(&repack, "--no-write-bitmap-index");
 }
 
 static int need_to_gc(void)
@@ -514,11 +514,11 @@ static void gc_before_repack(void)
        if (done++)
                return;
 
-       if (pack_refs && run_command_v_opt(pack_refs_cmd.argv, RUN_GIT_CMD))
-               die(FAILED_RUN, pack_refs_cmd.argv[0]);
+       if (pack_refs && run_command_v_opt(pack_refs_cmd.v, RUN_GIT_CMD))
+               die(FAILED_RUN, pack_refs_cmd.v[0]);
 
-       if (prune_reflogs && run_command_v_opt(reflog.argv, RUN_GIT_CMD))
-               die(FAILED_RUN, reflog.argv[0]);
+       if (prune_reflogs && run_command_v_opt(reflog.v, RUN_GIT_CMD))
+               die(FAILED_RUN, reflog.v[0]);
 }
 
 int cmd_gc(int argc, const char **argv, const char *prefix)
@@ -552,12 +552,12 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
        if (argc == 2 && !strcmp(argv[1], "-h"))
                usage_with_options(builtin_gc_usage, builtin_gc_options);
 
-       argv_array_pushl(&pack_refs_cmd, "pack-refs", "--all", "--prune", NULL);
-       argv_array_pushl(&reflog, "reflog", "expire", "--all", NULL);
-       argv_array_pushl(&repack, "repack", "-d", "-l", NULL);
-       argv_array_pushl(&prune, "prune", "--expire", NULL);
-       argv_array_pushl(&prune_worktrees, "worktree", "prune", "--expire", NULL);
-       argv_array_pushl(&rerere, "rerere", "gc", NULL);
+       strvec_pushl(&pack_refs_cmd, "pack-refs", "--all", "--prune", NULL);
+       strvec_pushl(&reflog, "reflog", "expire", "--all", NULL);
+       strvec_pushl(&repack, "repack", "-d", "-l", NULL);
+       strvec_pushl(&prune, "prune", "--expire", NULL);
+       strvec_pushl(&prune_worktrees, "worktree", "prune", "--expire", NULL);
+       strvec_pushl(&rerere, "rerere", "gc", NULL);
 
        /* default expiry time, overwritten in gc_config */
        gc_config();
@@ -576,14 +576,14 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
                die(_("failed to parse prune expiry value %s"), prune_expire);
 
        if (aggressive) {
-               argv_array_push(&repack, "-f");
+               strvec_push(&repack, "-f");
                if (aggressive_depth > 0)
-                       argv_array_pushf(&repack, "--depth=%d", aggressive_depth);
+                       strvec_pushf(&repack, "--depth=%d", aggressive_depth);
                if (aggressive_window > 0)
-                       argv_array_pushf(&repack, "--window=%d", aggressive_window);
+                       strvec_pushf(&repack, "--window=%d", aggressive_window);
        }
        if (quiet)
-               argv_array_push(&repack, "-q");
+               strvec_push(&repack, "-q");
 
        if (auto_gc) {
                /*
@@ -653,29 +653,29 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
 
        if (!repository_format_precious_objects) {
                close_object_store(the_repository->objects);
-               if (run_command_v_opt(repack.argv, RUN_GIT_CMD))
-                       die(FAILED_RUN, repack.argv[0]);
+               if (run_command_v_opt(repack.v, RUN_GIT_CMD))
+                       die(FAILED_RUN, repack.v[0]);
 
                if (prune_expire) {
-                       argv_array_push(&prune, prune_expire);
+                       strvec_push(&prune, prune_expire);
                        if (quiet)
-                               argv_array_push(&prune, "--no-progress");
+                               strvec_push(&prune, "--no-progress");
                        if (has_promisor_remote())
-                               argv_array_push(&prune,
-                                               "--exclude-promisor-objects");
-                       if (run_command_v_opt(prune.argv, RUN_GIT_CMD))
-                               die(FAILED_RUN, prune.argv[0]);
+                               strvec_push(&prune,
+                                           "--exclude-promisor-objects");
+                       if (run_command_v_opt(prune.v, RUN_GIT_CMD))
+                               die(FAILED_RUN, prune.v[0]);
                }
        }
 
        if (prune_worktrees_expire) {
-               argv_array_push(&prune_worktrees, prune_worktrees_expire);
-               if (run_command_v_opt(prune_worktrees.argv, RUN_GIT_CMD))
-                       die(FAILED_RUN, prune_worktrees.argv[0]);
+               strvec_push(&prune_worktrees, prune_worktrees_expire);
+               if (run_command_v_opt(prune_worktrees.v, RUN_GIT_CMD))
+                       die(FAILED_RUN, prune_worktrees.v[0]);
        }
 
-       if (run_command_v_opt(rerere.argv, RUN_GIT_CMD))
-               die(FAILED_RUN, rerere.argv[0]);
+       if (run_command_v_opt(rerere.v, RUN_GIT_CMD))
+               die(FAILED_RUN, rerere.v[0]);
 
        report_garbage = report_pack_garbage;
        reprepare_packed_git(the_repository);
index a5056f395aae16e21b032592558f4389b6953294..f58979bc3f07a6ca5adbd8704b1df41bf4215048 100644 (file)
@@ -397,7 +397,7 @@ static void run_pager(struct grep_opt *opt, const char *prefix)
        int i, status;
 
        for (i = 0; i < path_list->nr; i++)
-               argv_array_push(&child.args, path_list->items[i].string);
+               strvec_push(&child.args, path_list->items[i].string);
        child.dir = prefix;
        child.use_shell = 1;
 
@@ -466,7 +466,7 @@ static int grep_submodule(struct grep_opt *opt,
                struct strbuf base = STRBUF_INIT;
 
                obj_read_lock();
-               object = parse_object_or_die(oid, oid_to_hex(oid));
+               object = parse_object_or_die(oid, NULL);
                obj_read_unlock();
                data = read_object_with_reference(&subrepo,
                                                  &object->oid, tree_type,
@@ -693,7 +693,7 @@ static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec,
        struct dir_struct dir;
        int i, hit = 0;
 
-       memset(&dir, 0, sizeof(dir));
+       dir_init(&dir);
        if (!use_index)
                dir.flags |= DIR_NO_GITLINKS;
        if (exc_std)
@@ -705,6 +705,7 @@ static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec,
                if (hit && opt->status_only)
                        break;
        }
+       dir_clear(&dir);
        return hit;
 }
 
index 299206eb573985370330fd10e619c2343209de9c..bb339f0fc80298185f330fe6fbff9dd385da5e0d 100644 (file)
@@ -579,7 +579,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)
        }
 
        if (show_guides)
-               list_common_guides_help();
+               list_guides_help();
 
        if (show_all || show_guides) {
                printf("%s\n", _(git_more_info_string));
index f865666db9ee62ba0b1dd60111912b233df47d7c..9721bf1ffe8eafad1d002203541d6a9d30a91f8e 100644 (file)
@@ -1798,9 +1798,22 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 
        if (HAVE_THREADS && !nr_threads) {
                nr_threads = online_cpus();
-               /* An experiment showed that more threads does not mean faster */
-               if (nr_threads > 3)
-                       nr_threads = 3;
+               /*
+                * Experiments show that going above 20 threads doesn't help,
+                * no matter how many cores you have. Below that, we tend to
+                * max at half the number of online_cpus(), presumably because
+                * half of those are hyperthreads rather than full cores. We'll
+                * never reduce the level below "3", though, to match a
+                * historical value that nobody complained about.
+                */
+               if (nr_threads < 4)
+                       ; /* too few cores to consider capping */
+               else if (nr_threads < 6)
+                       nr_threads = 3; /* historic cap */
+               else if (nr_threads < 40)
+                       nr_threads /= 2;
+               else
+                       nr_threads = 20; /* hard cap */
        }
 
        curr_pack = open_pack_file(pack_name);
index cee64823cbb500a8df0f19f486a2d3593492b1e6..bbc9bc78f9d5a32ed9d167a79426ba0329bdea95 100644 (file)
@@ -183,11 +183,6 @@ void initialize_repository_version(int hash_algo)
        char repo_version_string[10];
        int repo_version = GIT_REPO_VERSION;
 
-#ifndef ENABLE_SHA256
-       if (hash_algo != GIT_HASH_SHA1)
-               die(_("The hash algorithm %s is not supported in this build."), hash_algos[hash_algo].name);
-#endif
-
        if (hash_algo != GIT_HASH_SHA1)
                repo_version = GIT_REPO_VERSION_READ;
 
@@ -568,6 +563,9 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 
        argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);
 
+       if (real_git_dir && is_bare_repository_cfg == 1)
+               die(_("--separate-git-dir and --bare are mutually exclusive"));
+
        if (real_git_dir && !is_absolute_path(real_git_dir))
                real_git_dir = real_pathdup(real_git_dir, 1);
 
@@ -663,6 +661,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
                                   get_git_work_tree());
        }
        else {
+               if (real_git_dir)
+                       die(_("--separate-git-dir incompatible with bare repository"));
                if (work_tree)
                        set_git_work_tree(work_tree);
        }
index d104d5c6889ba2d2ffaaeafa08fbfcd759d8bc92..b58f8da09ef7a16a1df0a99aba36003dc8732a24 100644 (file)
@@ -599,8 +599,8 @@ static int show_tree_object(const struct object_id *oid,
 static void show_setup_revisions_tweak(struct rev_info *rev,
                                       struct setup_revision_opt *opt)
 {
-       if (rev->ignore_merges) {
-               /* There was no "-m" on the command line */
+       if (rev->ignore_merges < 0) {
+               /* There was no "-m" variant on the command line */
                rev->ignore_merges = 0;
                if (!rev->first_parent_only && !rev->combine_merges) {
                        /* No "--first-parent", "-c", or "--cc" */
@@ -732,8 +732,7 @@ static void log_setup_revisions_tweak(struct rev_info *rev,
        if (!rev->diffopt.output_format && rev->combine_merges)
                rev->diffopt.output_format = DIFF_FORMAT_PATCH;
 
-       /* Turn -m on when --cc/-c was given */
-       if (rev->combine_merges)
+       if (rev->first_parent_only && rev->ignore_merges < 0)
                rev->ignore_merges = 0;
 }
 
@@ -1128,18 +1127,18 @@ do_pp:
 
 static int get_notes_refs(struct string_list_item *item, void *arg)
 {
-       argv_array_pushf(arg, "--notes=%s", item->string);
+       strvec_pushf(arg, "--notes=%s", item->string);
        return 0;
 }
 
-static void get_notes_args(struct argv_array *arg, struct rev_info *rev)
+static void get_notes_args(struct strvec *arg, struct rev_info *rev)
 {
        if (!rev->show_notes) {
-               argv_array_push(arg, "--no-notes");
+               strvec_push(arg, "--no-notes");
        } else if (rev->notes_opt.use_default_notes > 0 ||
                   (rev->notes_opt.use_default_notes == -1 &&
                    !rev->notes_opt.extra_notes_refs.nr)) {
-               argv_array_push(arg, "--notes");
+               strvec_push(arg, "--notes");
        } else {
                for_each_string_list(&rev->notes_opt.extra_notes_refs, get_notes_refs, arg);
        }
@@ -1217,7 +1216,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
                 * can be added later if deemed desirable.
                 */
                struct diff_options opts;
-               struct argv_array other_arg = ARGV_ARRAY_INIT;
+               struct strvec other_arg = STRVEC_INIT;
                diff_setup(&opts);
                opts.file = rev->diffopt.file;
                opts.use_color = rev->diffopt.use_color;
@@ -1226,7 +1225,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
                get_notes_args(&other_arg, rev);
                show_range_diff(rev->rdiff1, rev->rdiff2,
                                rev->creation_factor, 1, &opts, &other_arg);
-               argv_array_clear(&other_arg);
+               strvec_clear(&other_arg);
        }
 }
 
index 30a4c10334982e9ea34729a979a83027fa83c940..c8eae899b82a83ebc3487ffa99ba2bcf73d3369f 100644 (file)
@@ -584,7 +584,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
        if (argc == 2 && !strcmp(argv[1], "-h"))
                usage_with_options(ls_files_usage, builtin_ls_files_options);
 
-       memset(&dir, 0, sizeof(dir));
+       dir_init(&dir);
        prefix = cmd_prefix;
        if (prefix)
                prefix_len = strlen(prefix);
@@ -688,6 +688,6 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
                return bad ? 1 : 0;
        }
 
-       UNLEAK(dir);
+       dir_clear(&dir);
        return 0;
 }
index 3a4dd12903206ae47fd4683e3bef1a7371d67d55..092917eca29b76f27bce31cbf6a5fff562fae7f0 100644 (file)
@@ -45,7 +45,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
        int show_symref_target = 0;
        const char *uploadpack = NULL;
        const char **pattern = NULL;
-       struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
+       struct strvec ref_prefixes = STRVEC_INIT;
        int i;
        struct string_list server_options = STRING_LIST_INIT_DUP;
 
@@ -83,6 +83,8 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
                             PARSE_OPT_STOP_AT_NON_OPTION);
        dest = argv[0];
 
+       UNLEAK(sorting);
+
        if (argc > 1) {
                int i;
                pattern = xcalloc(argc, sizeof(const char *));
@@ -92,9 +94,9 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
        }
 
        if (flags & REF_TAGS)
-               argv_array_push(&ref_prefixes, "refs/tags/");
+               strvec_push(&ref_prefixes, "refs/tags/");
        if (flags & REF_HEADS)
-               argv_array_push(&ref_prefixes, "refs/heads/");
+               strvec_push(&ref_prefixes, "refs/heads/");
 
        remote = remote_get(dest);
        if (!remote) {
@@ -107,7 +109,6 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
 
        if (get_url) {
                printf("%s\n", *remote->url);
-               UNLEAK(sorting);
                return 0;
        }
 
@@ -122,10 +123,8 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
                int hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
                repo_set_hash_algo(the_repository, hash_algo);
        }
-       if (transport_disconnect(transport)) {
-               UNLEAK(sorting);
+       if (transport_disconnect(transport))
                return 1;
-       }
 
        if (!dest && !quiet)
                fprintf(stderr, "From %s\n", *remote->url);
@@ -150,7 +149,6 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
                status = 0; /* we found something */
        }
 
-       UNLEAK(sorting);
        ref_array_clear(&ref_array);
        return status;
 }
index 7da707bf55d94f0a151fb03954b3b107e408e551..b9a89ba858a366a162ea21a54a63c857f70278c7 100644 (file)
@@ -72,7 +72,6 @@ static const char **xopts;
 static size_t xopts_nr, xopts_alloc;
 static const char *branch;
 static char *branch_mergeoptions;
-static int option_renormalize;
 static int verbosity;
 static int allow_rerere_auto;
 static int abort_current_merge;
@@ -621,8 +620,6 @@ static int git_merge_config(const char *k, const char *v, void *cb)
                return git_config_string(&pull_octopus, k, v);
        else if (!strcmp(k, "commit.cleanup"))
                return git_config_string(&cleanup_arg, k, v);
-       else if (!strcmp(k, "merge.renormalize"))
-               option_renormalize = git_config_bool(k, v);
        else if (!strcmp(k, "merge.ff")) {
                int boolval = git_parse_maybe_bool(v);
                if (0 <= boolval) {
@@ -721,7 +718,6 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
                if (!strcmp(strategy, "subtree"))
                        o.subtree_shift = "";
 
-               o.renormalize = option_renormalize;
                o.show_rename_progress =
                        show_progress == -1 ? isatty(2) : show_progress;
 
@@ -1352,7 +1348,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                else
                        die(_("You have not concluded your merge (MERGE_HEAD exists)."));
        }
-       if (file_exists(git_path_cherry_pick_head(the_repository))) {
+       if (ref_exists("CHERRY_PICK_HEAD")) {
                if (advice_resolve_conflict)
                        die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
                            "Please, commit your changes before you merge."));
index be15ba7044e0eeeee216a9e6c4615214cd7cdc1e..7dac714af908789c675a158cf44067771dd62ad2 100644 (file)
@@ -132,6 +132,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
        struct stat st;
        struct string_list src_for_dst = STRING_LIST_INIT_NODUP;
        struct lock_file lock_file = LOCK_INIT;
+       struct cache_entry *ce;
 
        git_config(git_default_config, NULL);
 
@@ -220,9 +221,11 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
                                }
                                argc += last - first;
                        }
-               } else if (cache_name_pos(src, length) < 0)
+               } else if (!(ce = cache_file_exists(src, length, ignore_case))) {
                        bad = _("not under version control");
-               else if (lstat(dst, &st) == 0 &&
+               } else if (ce_stage(ce)) {
+                       bad = _("conflicted");
+               } else if (lstat(dst, &st) == 0 &&
                         (!ignore_case || strcasecmp(src, dst))) {
                        bad = _("destination exists");
                        if (force) {
index a9dcd25e46477ef5294dd501f1048816b27b3cdf..725dd04519133595dc212ce6c68e511b07c6b92a 100644 (file)
@@ -521,7 +521,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
        int all = 0, transform_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0;
        struct name_ref_data data = { 0, 0, STRING_LIST_INIT_NODUP, STRING_LIST_INIT_NODUP };
        struct option opts[] = {
-               OPT_BOOL(0, "name-only", &data.name_only, N_("print only names (no SHA-1)")),
+               OPT_BOOL(0, "name-only", &data.name_only, N_("print only ref-based names (no object names)")),
                OPT_BOOL(0, "tags", &data.tags_only, N_("only use tags to name the commits")),
                OPT_STRING_LIST(0, "refs", &data.ref_filters, N_("pattern"),
                                   N_("only use refs matching <pattern>")),
index 7016b28485b43f9df360f4f6df23cb7e0e3881dd..5617c01b5aae0dafd33467cecabe8b58fd36d568 100644 (file)
@@ -27,7 +27,7 @@
 #include "delta-islands.h"
 #include "reachable.h"
 #include "oid-array.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "list.h"
 #include "packfile.h"
 #include "object-store.h"
@@ -35,6 +35,7 @@
 #include "midx.h"
 #include "trace2.h"
 #include "shallow.h"
+#include "promisor-remote.h"
 
 #define IN_PACK(obj) oe_in_pack(&to_pack, obj)
 #define SIZE(obj) oe_size(&to_pack, obj)
@@ -1704,9 +1705,30 @@ static int can_reuse_delta(const struct object_id *base_oid,
        return 0;
 }
 
-static void check_object(struct object_entry *entry)
+static void prefetch_to_pack(uint32_t object_index_start) {
+       struct oid_array to_fetch = OID_ARRAY_INIT;
+       uint32_t i;
+
+       for (i = object_index_start; i < to_pack.nr_objects; i++) {
+               struct object_entry *entry = to_pack.objects + i;
+
+               if (!oid_object_info_extended(the_repository,
+                                             &entry->idx.oid,
+                                             NULL,
+                                             OBJECT_INFO_FOR_PREFETCH))
+                       continue;
+               oid_array_append(&to_fetch, &entry->idx.oid);
+       }
+       promisor_remote_get_direct(the_repository,
+                                  to_fetch.oid, to_fetch.nr);
+       oid_array_clear(&to_fetch);
+}
+
+static void check_object(struct object_entry *entry, uint32_t object_index)
 {
        unsigned long canonical_size;
+       enum object_type type;
+       struct object_info oi = {.typep = &type, .sizep = &canonical_size};
 
        if (IN_PACK(entry)) {
                struct packed_git *p = IN_PACK(entry);
@@ -1840,8 +1862,18 @@ static void check_object(struct object_entry *entry)
                unuse_pack(&w_curs);
        }
 
-       oe_set_type(entry,
-                   oid_object_info(the_repository, &entry->idx.oid, &canonical_size));
+       if (oid_object_info_extended(the_repository, &entry->idx.oid, &oi,
+                                    OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_LOOKUP_REPLACE) < 0) {
+               if (has_promisor_remote()) {
+                       prefetch_to_pack(object_index);
+                       if (oid_object_info_extended(the_repository, &entry->idx.oid, &oi,
+                                                    OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_LOOKUP_REPLACE) < 0)
+                               type = -1;
+               } else {
+                       type = -1;
+               }
+       }
+       oe_set_type(entry, type);
        if (entry->type_valid) {
                SET_SIZE(entry, canonical_size);
        } else {
@@ -2061,7 +2093,7 @@ static void get_object_details(void)
 
        for (i = 0; i < to_pack.nr_objects; i++) {
                struct object_entry *entry = sorted_by_offset[i];
-               check_object(entry);
+               check_object(entry, i);
                if (entry->type_valid &&
                    oe_size_greater_than(&to_pack, entry, big_file_threshold))
                        entry->no_try_delta = 1;
@@ -3016,7 +3048,7 @@ static void show_object__ma_allow_any(struct object *obj, const char *name, void
         * Quietly ignore ALL missing objects.  This avoids problems with
         * staging them now and getting an odd error later.
         */
-       if (!has_object_file(&obj->oid))
+       if (!has_object(the_repository, &obj->oid, 0))
                return;
 
        show_object(obj, name, data);
@@ -3030,7 +3062,7 @@ static void show_object__ma_allow_promisor(struct object *obj, const char *name,
         * Quietly ignore EXPECTED missing objects.  This avoids problems with
         * staging them now and getting an odd error later.
         */
-       if (!has_object_file(&obj->oid) && is_promisor_object(&obj->oid))
+       if (!has_object(the_repository, &obj->oid, 0) && is_promisor_object(&obj->oid))
                return;
 
        show_object(obj, name, data);
@@ -3325,7 +3357,7 @@ static void get_object_list(int ac, const char **av)
                        if (starts_with(line, "--shallow ")) {
                                struct object_id oid;
                                if (get_oid_hex(line + 10, &oid))
-                                       die("not an SHA-1 '%s'", line + 10);
+                                       die("not an object name '%s'", line + 10);
                                register_shallow(the_repository, &oid);
                                use_bitmap_index = 0;
                                continue;
@@ -3439,7 +3471,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
        int use_internal_rev_list = 0;
        int shallow = 0;
        int all_progress_implied = 0;
-       struct argv_array rp = ARGV_ARRAY_INIT;
+       struct strvec rp = STRVEC_INIT;
        int rev_list_unpacked = 0, rev_list_all = 0, rev_list_reflog = 0;
        int rev_list_index = 0;
        struct string_list keep_pack_list = STRING_LIST_INIT_NODUP;
@@ -3575,36 +3607,36 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                cache_max_small_delta_size = (1U << OE_Z_DELTA_BITS) - 1;
        }
 
-       argv_array_push(&rp, "pack-objects");
+       strvec_push(&rp, "pack-objects");
        if (thin) {
                use_internal_rev_list = 1;
-               argv_array_push(&rp, shallow
+               strvec_push(&rp, shallow
                                ? "--objects-edge-aggressive"
                                : "--objects-edge");
        } else
-               argv_array_push(&rp, "--objects");
+               strvec_push(&rp, "--objects");
 
        if (rev_list_all) {
                use_internal_rev_list = 1;
-               argv_array_push(&rp, "--all");
+               strvec_push(&rp, "--all");
        }
        if (rev_list_reflog) {
                use_internal_rev_list = 1;
-               argv_array_push(&rp, "--reflog");
+               strvec_push(&rp, "--reflog");
        }
        if (rev_list_index) {
                use_internal_rev_list = 1;
-               argv_array_push(&rp, "--indexed-objects");
+               strvec_push(&rp, "--indexed-objects");
        }
        if (rev_list_unpacked) {
                use_internal_rev_list = 1;
-               argv_array_push(&rp, "--unpacked");
+               strvec_push(&rp, "--unpacked");
        }
 
        if (exclude_promisor_objects) {
                use_internal_rev_list = 1;
                fetch_if_missing = 0;
-               argv_array_push(&rp, "--exclude-promisor-objects");
+               strvec_push(&rp, "--exclude-promisor-objects");
        }
        if (unpack_unreachable || keep_unreachable || pack_loose_unreachable)
                use_internal_rev_list = 1;
@@ -3666,7 +3698,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                write_bitmap_index = 0;
 
        if (use_delta_islands)
-               argv_array_push(&rp, "--topo-order");
+               strvec_push(&rp, "--topo-order");
 
        if (progress && all_progress_implied)
                progress = 2;
@@ -3704,8 +3736,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
        if (!use_internal_rev_list)
                read_object_list_from_stdin();
        else {
-               get_object_list(rp.argc, rp.argv);
-               argv_array_clear(&rp);
+               get_object_list(rp.nr, rp.v);
+               strvec_clear(&rp);
        }
        cleanup_preferred_base();
        if (include_tag && nr_result)
index 8159c5d7c9651497a658b3880fef26b67089bd29..015f6ded0badf82760557fc0c890513de2c147dc 100644 (file)
@@ -87,8 +87,8 @@ static char *opt_verify_signatures;
 static int opt_autostash = -1;
 static int config_autostash;
 static int check_trust_level = 1;
-static struct argv_array opt_strategies = ARGV_ARRAY_INIT;
-static struct argv_array opt_strategy_opts = ARGV_ARRAY_INIT;
+static struct strvec opt_strategies = STRVEC_INIT;
+static struct strvec opt_strategy_opts = STRVEC_INIT;
 static char *opt_gpg_sign;
 static int opt_allow_unrelated_histories;
 
@@ -110,7 +110,7 @@ static char *opt_ipv4;
 static char *opt_ipv6;
 static int opt_show_forced_updates = -1;
 static char *set_upstream;
-static struct argv_array opt_fetch = ARGV_ARRAY_INIT;
+static struct strvec opt_fetch = STRVEC_INIT;
 
 static struct option pull_options[] = {
        /* Shared options */
@@ -251,25 +251,25 @@ static struct option pull_options[] = {
 /**
  * Pushes "-q" or "-v" switches into arr to match the opt_verbosity level.
  */
-static void argv_push_verbosity(struct argv_array *arr)
+static void argv_push_verbosity(struct strvec *arr)
 {
        int verbosity;
 
        for (verbosity = opt_verbosity; verbosity > 0; verbosity--)
-               argv_array_push(arr, "-v");
+               strvec_push(arr, "-v");
 
        for (verbosity = opt_verbosity; verbosity < 0; verbosity++)
-               argv_array_push(arr, "-q");
+               strvec_push(arr, "-q");
 }
 
 /**
  * Pushes "-f" switches into arr to match the opt_force level.
  */
-static void argv_push_force(struct argv_array *arr)
+static void argv_push_force(struct strvec *arr)
 {
        int force = opt_force;
        while (force-- > 0)
-               argv_array_push(arr, "-f");
+               strvec_push(arr, "-f");
 }
 
 /**
@@ -524,75 +524,75 @@ static void parse_repo_refspecs(int argc, const char **argv, const char **repo,
  */
 static int run_fetch(const char *repo, const char **refspecs)
 {
-       struct argv_array args = ARGV_ARRAY_INIT;
+       struct strvec args = STRVEC_INIT;
        int ret;
 
-       argv_array_pushl(&args, "fetch", "--update-head-ok", NULL);
+       strvec_pushl(&args, "fetch", "--update-head-ok", NULL);
 
        /* Shared options */
        argv_push_verbosity(&args);
        if (opt_progress)
-               argv_array_push(&args, opt_progress);
+               strvec_push(&args, opt_progress);
 
        /* Options passed to git-fetch */
        if (opt_all)
-               argv_array_push(&args, opt_all);
+               strvec_push(&args, opt_all);
        if (opt_append)
-               argv_array_push(&args, opt_append);
+               strvec_push(&args, opt_append);
        if (opt_upload_pack)
-               argv_array_push(&args, opt_upload_pack);
+               strvec_push(&args, opt_upload_pack);
        argv_push_force(&args);
        if (opt_tags)
-               argv_array_push(&args, opt_tags);
+               strvec_push(&args, opt_tags);
        if (opt_prune)
-               argv_array_push(&args, opt_prune);
+               strvec_push(&args, opt_prune);
        if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT)
                switch (recurse_submodules) {
                case RECURSE_SUBMODULES_ON:
-                       argv_array_push(&args, "--recurse-submodules=on");
+                       strvec_push(&args, "--recurse-submodules=on");
                        break;
                case RECURSE_SUBMODULES_OFF:
-                       argv_array_push(&args, "--recurse-submodules=no");
+                       strvec_push(&args, "--recurse-submodules=no");
                        break;
                case RECURSE_SUBMODULES_ON_DEMAND:
-                       argv_array_push(&args, "--recurse-submodules=on-demand");
+                       strvec_push(&args, "--recurse-submodules=on-demand");
                        break;
                default:
                        BUG("submodule recursion option not understood");
                }
        if (max_children)
-               argv_array_push(&args, max_children);
+               strvec_push(&args, max_children);
        if (opt_dry_run)
-               argv_array_push(&args, "--dry-run");
+               strvec_push(&args, "--dry-run");
        if (opt_keep)
-               argv_array_push(&args, opt_keep);
+               strvec_push(&args, opt_keep);
        if (opt_depth)
-               argv_array_push(&args, opt_depth);
+               strvec_push(&args, opt_depth);
        if (opt_unshallow)
-               argv_array_push(&args, opt_unshallow);
+               strvec_push(&args, opt_unshallow);
        if (opt_update_shallow)
-               argv_array_push(&args, opt_update_shallow);
+               strvec_push(&args, opt_update_shallow);
        if (opt_refmap)
-               argv_array_push(&args, opt_refmap);
+               strvec_push(&args, opt_refmap);
        if (opt_ipv4)
-               argv_array_push(&args, opt_ipv4);
+               strvec_push(&args, opt_ipv4);
        if (opt_ipv6)
-               argv_array_push(&args, opt_ipv6);
+               strvec_push(&args, opt_ipv6);
        if (opt_show_forced_updates > 0)
-               argv_array_push(&args, "--show-forced-updates");
+               strvec_push(&args, "--show-forced-updates");
        else if (opt_show_forced_updates == 0)
-               argv_array_push(&args, "--no-show-forced-updates");
+               strvec_push(&args, "--no-show-forced-updates");
        if (set_upstream)
-               argv_array_push(&args, set_upstream);
-       argv_array_pushv(&args, opt_fetch.argv);
+               strvec_push(&args, set_upstream);
+       strvec_pushv(&args, opt_fetch.v);
 
        if (repo) {
-               argv_array_push(&args, repo);
-               argv_array_pushv(&args, refspecs);
+               strvec_push(&args, repo);
+               strvec_pushv(&args, refspecs);
        } else if (*refspecs)
                BUG("refspecs without repo?");
-       ret = run_command_v_opt(args.argv, RUN_GIT_CMD);
-       argv_array_clear(&args);
+       ret = run_command_v_opt(args.v, RUN_GIT_CMD);
+       strvec_clear(&args);
        return ret;
 }
 
@@ -637,8 +637,8 @@ static int rebase_submodules(void)
 
        cp.git_cmd = 1;
        cp.no_stdin = 1;
-       argv_array_pushl(&cp.args, "submodule", "update",
-                                  "--recursive", "--rebase", NULL);
+       strvec_pushl(&cp.args, "submodule", "update",
+                    "--recursive", "--rebase", NULL);
        argv_push_verbosity(&cp.args);
 
        return run_command(&cp);
@@ -650,8 +650,8 @@ static int update_submodules(void)
 
        cp.git_cmd = 1;
        cp.no_stdin = 1;
-       argv_array_pushl(&cp.args, "submodule", "update",
-                                  "--recursive", "--checkout", NULL);
+       strvec_pushl(&cp.args, "submodule", "update",
+                    "--recursive", "--checkout", NULL);
        argv_push_verbosity(&cp.args);
 
        return run_command(&cp);
@@ -663,48 +663,48 @@ static int update_submodules(void)
 static int run_merge(void)
 {
        int ret;
-       struct argv_array args = ARGV_ARRAY_INIT;
+       struct strvec args = STRVEC_INIT;
 
-       argv_array_pushl(&args, "merge", NULL);
+       strvec_pushl(&args, "merge", NULL);
 
        /* Shared options */
        argv_push_verbosity(&args);
        if (opt_progress)
-               argv_array_push(&args, opt_progress);
+               strvec_push(&args, opt_progress);
 
        /* Options passed to git-merge */
        if (opt_diffstat)
-               argv_array_push(&args, opt_diffstat);
+               strvec_push(&args, opt_diffstat);
        if (opt_log)
-               argv_array_push(&args, opt_log);
+               strvec_push(&args, opt_log);
        if (opt_signoff)
-               argv_array_push(&args, opt_signoff);
+               strvec_push(&args, opt_signoff);
        if (opt_squash)
-               argv_array_push(&args, opt_squash);
+               strvec_push(&args, opt_squash);
        if (opt_commit)
-               argv_array_push(&args, opt_commit);
+               strvec_push(&args, opt_commit);
        if (opt_edit)
-               argv_array_push(&args, opt_edit);
+               strvec_push(&args, opt_edit);
        if (cleanup_arg)
-               argv_array_pushf(&args, "--cleanup=%s", cleanup_arg);
+               strvec_pushf(&args, "--cleanup=%s", cleanup_arg);
        if (opt_ff)
-               argv_array_push(&args, opt_ff);
+               strvec_push(&args, opt_ff);
        if (opt_verify_signatures)
-               argv_array_push(&args, opt_verify_signatures);
-       argv_array_pushv(&args, opt_strategies.argv);
-       argv_array_pushv(&args, opt_strategy_opts.argv);
+               strvec_push(&args, opt_verify_signatures);
+       strvec_pushv(&args, opt_strategies.v);
+       strvec_pushv(&args, opt_strategy_opts.v);
        if (opt_gpg_sign)
-               argv_array_push(&args, opt_gpg_sign);
+               strvec_push(&args, opt_gpg_sign);
        if (opt_autostash == 0)
-               argv_array_push(&args, "--no-autostash");
+               strvec_push(&args, "--no-autostash");
        else if (opt_autostash == 1)
-               argv_array_push(&args, "--autostash");
+               strvec_push(&args, "--autostash");
        if (opt_allow_unrelated_histories > 0)
-               argv_array_push(&args, "--allow-unrelated-histories");
+               strvec_push(&args, "--allow-unrelated-histories");
 
-       argv_array_push(&args, "FETCH_HEAD");
-       ret = run_command_v_opt(args.argv, RUN_GIT_CMD);
-       argv_array_clear(&args);
+       strvec_push(&args, "FETCH_HEAD");
+       ret = run_command_v_opt(args.v, RUN_GIT_CMD);
+       strvec_clear(&args);
        return ret;
 }
 
@@ -801,8 +801,8 @@ static int get_rebase_fork_point(struct object_id *fork_point, const char *repo,
        if (!remote_branch)
                return -1;
 
-       argv_array_pushl(&cp.args, "merge-base", "--fork-point",
-                       remote_branch, curr_branch->name, NULL);
+       strvec_pushl(&cp.args, "merge-base", "--fork-point",
+                    remote_branch, curr_branch->name, NULL);
        cp.no_stdin = 1;
        cp.no_stderr = 1;
        cp.git_cmd = 1;
@@ -862,48 +862,48 @@ static int run_rebase(const struct object_id *curr_head,
 {
        int ret;
        struct object_id oct_merge_base;
-       struct argv_array args = ARGV_ARRAY_INIT;
+       struct strvec args = STRVEC_INIT;
 
        if (!get_octopus_merge_base(&oct_merge_base, curr_head, merge_head, fork_point))
                if (!is_null_oid(fork_point) && oideq(&oct_merge_base, fork_point))
                        fork_point = NULL;
 
-       argv_array_push(&args, "rebase");
+       strvec_push(&args, "rebase");
 
        /* Shared options */
        argv_push_verbosity(&args);
 
        /* Options passed to git-rebase */
        if (opt_rebase == REBASE_MERGES)
-               argv_array_push(&args, "--rebase-merges");
+               strvec_push(&args, "--rebase-merges");
        else if (opt_rebase == REBASE_PRESERVE)
-               argv_array_push(&args, "--preserve-merges");
+               strvec_push(&args, "--preserve-merges");
        else if (opt_rebase == REBASE_INTERACTIVE)
-               argv_array_push(&args, "--interactive");
+               strvec_push(&args, "--interactive");
        if (opt_diffstat)
-               argv_array_push(&args, opt_diffstat);
-       argv_array_pushv(&args, opt_strategies.argv);
-       argv_array_pushv(&args, opt_strategy_opts.argv);
+               strvec_push(&args, opt_diffstat);
+       strvec_pushv(&args, opt_strategies.v);
+       strvec_pushv(&args, opt_strategy_opts.v);
        if (opt_gpg_sign)
-               argv_array_push(&args, opt_gpg_sign);
+               strvec_push(&args, opt_gpg_sign);
        if (opt_autostash == 0)
-               argv_array_push(&args, "--no-autostash");
+               strvec_push(&args, "--no-autostash");
        else if (opt_autostash == 1)
-               argv_array_push(&args, "--autostash");
+               strvec_push(&args, "--autostash");
        if (opt_verify_signatures &&
            !strcmp(opt_verify_signatures, "--verify-signatures"))
                warning(_("ignoring --verify-signatures for rebase"));
 
-       argv_array_push(&args, "--onto");
-       argv_array_push(&args, oid_to_hex(merge_head));
+       strvec_push(&args, "--onto");
+       strvec_push(&args, oid_to_hex(merge_head));
 
        if (fork_point && !is_null_oid(fork_point))
-               argv_array_push(&args, oid_to_hex(fork_point));
+               strvec_push(&args, oid_to_hex(fork_point));
        else
-               argv_array_push(&args, oid_to_hex(merge_head));
+               strvec_push(&args, oid_to_hex(merge_head));
 
-       ret = run_command_v_opt(args.argv, RUN_GIT_CMD);
-       argv_array_clear(&args);
+       ret = run_command_v_opt(args.v, RUN_GIT_CMD);
+       strvec_clear(&args);
        return ret;
 }
 
index d8a467062990889797a60dc8a17df08354baa459..24c4162f7446ce89ff2fe9866bb0dc678785bed4 100644 (file)
@@ -15,7 +15,7 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix)
 {
        int creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT;
        struct diff_options diffopt = { NULL };
-       struct argv_array other_arg = ARGV_ARRAY_INIT;
+       struct strvec other_arg = STRVEC_INIT;
        int simple_color = -1;
        struct option range_diff_options[] = {
                OPT_INTEGER(0, "creation-factor", &creation_factor,
@@ -84,7 +84,7 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix)
        res = show_range_diff(range1.buf, range2.buf, creation_factor,
                              simple_color < 1, &diffopt, &other_arg);
 
-       argv_array_clear(&other_arg);
+       strvec_clear(&other_arg);
        strbuf_release(&range1);
        strbuf_release(&range2);
 
index 37ba76ac3d26f86ef3c16b65d2293b873efd8ee5..dadb52fa92e7f28e0c81b27b74b9a23b289e4be9 100644 (file)
@@ -8,7 +8,7 @@
 #include "builtin.h"
 #include "run-command.h"
 #include "exec-cmd.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "dir.h"
 #include "packfile.h"
 #include "refs.h"
@@ -84,7 +84,7 @@ struct rebase_options {
                REBASE_FORCE = 1<<3,
                REBASE_INTERACTIVE_EXPLICIT = 1<<4,
        } flags;
-       struct argv_array git_am_opts;
+       struct strvec git_am_opts;
        const char *action;
        int signoff;
        int allow_rerere_autoupdate;
@@ -108,7 +108,7 @@ struct rebase_options {
                .keep_empty = 1,                        \
                .default_backend = "merge",             \
                .flags = REBASE_NO_QUIET,               \
-               .git_am_opts = ARGV_ARRAY_INIT,         \
+               .git_am_opts = STRVEC_INIT,             \
                .git_format_patch_opt = STRBUF_INIT     \
        }
 
@@ -323,7 +323,7 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
        int ret;
        const char *head_hash = NULL;
        char *revisions = NULL, *shortrevisions = NULL;
-       struct argv_array make_script_args = ARGV_ARRAY_INIT;
+       struct strvec make_script_args = STRVEC_INIT;
        struct todo_list todo_list = TODO_LIST_INIT;
        struct replay_opts replay = get_replay_opts(opts);
        struct string_list commands = STRING_LIST_INIT_DUP;
@@ -345,13 +345,13 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
                write_file(path_squash_onto(), "%s\n",
                           oid_to_hex(opts->squash_onto));
 
-       argv_array_pushl(&make_script_args, "", revisions, NULL);
+       strvec_pushl(&make_script_args, "", revisions, NULL);
        if (opts->restrict_revision)
-               argv_array_pushf(&make_script_args, "^%s",
-                                oid_to_hex(&opts->restrict_revision->object.oid));
+               strvec_pushf(&make_script_args, "^%s",
+                            oid_to_hex(&opts->restrict_revision->object.oid));
 
        ret = sequencer_make_script(the_repository, &todo_list.buf,
-                                   make_script_args.argc, make_script_args.argv,
+                                   make_script_args.nr, make_script_args.v,
                                    flags);
 
        if (ret)
@@ -372,7 +372,7 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
        free(revisions);
        free(shortrevisions);
        todo_list_release(&todo_list);
-       argv_array_clear(&make_script_args);
+       strvec_clear(&make_script_args);
 
        return ret;
 }
@@ -420,7 +420,7 @@ static int run_sequencer_rebase(struct rebase_options *opts,
                struct child_process cmd = CHILD_PROCESS_INIT;
 
                cmd.git_cmd = 1;
-               argv_array_pushl(&cmd.args, "show", "REBASE_HEAD", "--", NULL);
+               strvec_pushl(&cmd.args, "show", "REBASE_HEAD", "--", NULL);
                ret = run_command(&cmd);
 
                break;
@@ -811,13 +811,13 @@ static int run_am(struct rebase_options *opts)
        char *rebased_patches;
 
        am.git_cmd = 1;
-       argv_array_push(&am.args, "am");
+       strvec_push(&am.args, "am");
 
        if (opts->action && !strcmp("continue", opts->action)) {
-               argv_array_push(&am.args, "--resolved");
-               argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
+               strvec_push(&am.args, "--resolved");
+               strvec_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
                if (opts->gpg_sign_opt)
-                       argv_array_push(&am.args, opts->gpg_sign_opt);
+                       strvec_push(&am.args, opts->gpg_sign_opt);
                status = run_command(&am);
                if (status)
                        return status;
@@ -825,8 +825,8 @@ static int run_am(struct rebase_options *opts)
                return move_to_original_branch(opts);
        }
        if (opts->action && !strcmp("skip", opts->action)) {
-               argv_array_push(&am.args, "--skip");
-               argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
+               strvec_push(&am.args, "--skip");
+               strvec_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
                status = run_command(&am);
                if (status)
                        return status;
@@ -834,7 +834,7 @@ static int run_am(struct rebase_options *opts)
                return move_to_original_branch(opts);
        }
        if (opts->action && !strcmp("show-current-patch", opts->action)) {
-               argv_array_push(&am.args, "--show-current-patch");
+               strvec_push(&am.args, "--show-current-patch");
                return run_command(&am);
        }
 
@@ -852,29 +852,29 @@ static int run_am(struct rebase_options *opts)
                status = error_errno(_("could not open '%s' for writing"),
                                     rebased_patches);
                free(rebased_patches);
-               argv_array_clear(&am.args);
+               strvec_clear(&am.args);
                return status;
        }
 
        format_patch.git_cmd = 1;
-       argv_array_pushl(&format_patch.args, "format-patch", "-k", "--stdout",
-                        "--full-index", "--cherry-pick", "--right-only",
-                        "--src-prefix=a/", "--dst-prefix=b/", "--no-renames",
-                        "--no-cover-letter", "--pretty=mboxrd", "--topo-order",
-                        "--no-base", NULL);
+       strvec_pushl(&format_patch.args, "format-patch", "-k", "--stdout",
+                    "--full-index", "--cherry-pick", "--right-only",
+                    "--src-prefix=a/", "--dst-prefix=b/", "--no-renames",
+                    "--no-cover-letter", "--pretty=mboxrd", "--topo-order",
+                    "--no-base", NULL);
        if (opts->git_format_patch_opt.len)
-               argv_array_split(&format_patch.args,
-                                opts->git_format_patch_opt.buf);
-       argv_array_push(&format_patch.args, revisions.buf);
+               strvec_split(&format_patch.args,
+                            opts->git_format_patch_opt.buf);
+       strvec_push(&format_patch.args, revisions.buf);
        if (opts->restrict_revision)
-               argv_array_pushf(&format_patch.args, "^%s",
-                                oid_to_hex(&opts->restrict_revision->object.oid));
+               strvec_pushf(&format_patch.args, "^%s",
+                            oid_to_hex(&opts->restrict_revision->object.oid));
 
        status = run_command(&format_patch);
        if (status) {
                unlink(rebased_patches);
                free(rebased_patches);
-               argv_array_clear(&am.args);
+               strvec_clear(&am.args);
 
                reset_head(the_repository, &opts->orig_head, "checkout",
                           opts->head_name, 0,
@@ -896,20 +896,20 @@ static int run_am(struct rebase_options *opts)
                status = error_errno(_("could not open '%s' for reading"),
                                     rebased_patches);
                free(rebased_patches);
-               argv_array_clear(&am.args);
+               strvec_clear(&am.args);
                return status;
        }
 
-       argv_array_pushv(&am.args, opts->git_am_opts.argv);
-       argv_array_push(&am.args, "--rebasing");
-       argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
-       argv_array_push(&am.args, "--patch-format=mboxrd");
+       strvec_pushv(&am.args, opts->git_am_opts.v);
+       strvec_push(&am.args, "--rebasing");
+       strvec_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
+       strvec_push(&am.args, "--patch-format=mboxrd");
        if (opts->allow_rerere_autoupdate == RERERE_AUTOUPDATE)
-               argv_array_push(&am.args, "--rerere-autoupdate");
+               strvec_push(&am.args, "--rerere-autoupdate");
        else if (opts->allow_rerere_autoupdate == RERERE_NOAUTOUPDATE)
-               argv_array_push(&am.args, "--no-rerere-autoupdate");
+               strvec_push(&am.args, "--no-rerere-autoupdate");
        if (opts->gpg_sign_opt)
-               argv_array_push(&am.args, opts->gpg_sign_opt);
+               strvec_push(&am.args, opts->gpg_sign_opt);
        status = run_command(&am);
        unlink(rebased_patches);
        free(rebased_patches);
@@ -969,7 +969,7 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action)
        add_var(&script_snippet, "revisions", opts->revisions);
        add_var(&script_snippet, "restrict_revision", opts->restrict_revision ?
                oid_to_hex(&opts->restrict_revision->object.oid) : NULL);
-       sq_quote_argv_pretty(&buf, opts->git_am_opts.argv);
+       sq_quote_argv_pretty(&buf, opts->git_am_opts.v);
        add_var(&script_snippet, "git_am_opt", buf.buf);
        strbuf_release(&buf);
        add_var(&script_snippet, "verbose",
@@ -1625,8 +1625,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                allow_preemptive_ff = 0;
        }
 
-       for (i = 0; i < options.git_am_opts.argc; i++) {
-               const char *option = options.git_am_opts.argv[i], *p;
+       for (i = 0; i < options.git_am_opts.nr; i++) {
+               const char *option = options.git_am_opts.v[i], *p;
                if (!strcmp(option, "--committer-date-is-author-date") ||
                    !strcmp(option, "--ignore-date") ||
                    !strcmp(option, "--whitespace=fix") ||
@@ -1649,7 +1649,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                        exit(1);
 
        if (!(options.flags & REBASE_NO_QUIET))
-               argv_array_push(&options.git_am_opts, "-q");
+               strvec_push(&options.git_am_opts, "-q");
 
        if (options.empty != EMPTY_UNSPECIFIED)
                imply_merge(&options, "--empty");
@@ -1721,10 +1721,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
        if (isatty(2) && options.flags & REBASE_NO_QUIET)
                strbuf_addstr(&options.git_format_patch_opt, " --progress");
 
-       if (options.git_am_opts.argc || options.type == REBASE_APPLY) {
+       if (options.git_am_opts.nr || options.type == REBASE_APPLY) {
                /* all am options except -q are compatible only with --apply */
-               for (i = options.git_am_opts.argc - 1; i >= 0; i--)
-                       if (strcmp(options.git_am_opts.argv[i], "-q"))
+               for (i = options.git_am_opts.nr - 1; i >= 0; i--)
+                       if (strcmp(options.git_am_opts.v[i], "-q"))
                                break;
 
                if (i >= 0) {
@@ -1776,7 +1776,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                if (options.type == REBASE_PRESERVE_MERGES)
                        die("cannot combine '--signoff' with "
                            "'--preserve-merges'");
-               argv_array_push(&options.git_am_opts, "--signoff");
+               strvec_push(&options.git_am_opts, "--signoff");
                options.flags |= REBASE_FORCE;
        }
 
index d43663bb0a9e8f410371ac06a34794060101578f..439f29d6c7f4c5bc856611a3e900ff7e9a77b9f5 100644 (file)
@@ -15,7 +15,7 @@
 #include "string-list.h"
 #include "oid-array.h"
 #include "connected.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "version.h"
 #include "tag.h"
 #include "gpg-interface.h"
@@ -667,25 +667,25 @@ static void prepare_push_cert_sha1(struct child_process *proc)
                nonce_status = check_nonce(push_cert.buf, bogs);
        }
        if (!is_null_oid(&push_cert_oid)) {
-               argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT=%s",
-                                oid_to_hex(&push_cert_oid));
-               argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT_SIGNER=%s",
-                                sigcheck.signer ? sigcheck.signer : "");
-               argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT_KEY=%s",
-                                sigcheck.key ? sigcheck.key : "");
-               argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT_STATUS=%c",
-                                sigcheck.result);
+               strvec_pushf(&proc->env_array, "GIT_PUSH_CERT=%s",
+                            oid_to_hex(&push_cert_oid));
+               strvec_pushf(&proc->env_array, "GIT_PUSH_CERT_SIGNER=%s",
+                            sigcheck.signer ? sigcheck.signer : "");
+               strvec_pushf(&proc->env_array, "GIT_PUSH_CERT_KEY=%s",
+                            sigcheck.key ? sigcheck.key : "");
+               strvec_pushf(&proc->env_array, "GIT_PUSH_CERT_STATUS=%c",
+                            sigcheck.result);
                if (push_cert_nonce) {
-                       argv_array_pushf(&proc->env_array,
-                                        "GIT_PUSH_CERT_NONCE=%s",
-                                        push_cert_nonce);
-                       argv_array_pushf(&proc->env_array,
-                                        "GIT_PUSH_CERT_NONCE_STATUS=%s",
-                                        nonce_status);
+                       strvec_pushf(&proc->env_array,
+                                    "GIT_PUSH_CERT_NONCE=%s",
+                                    push_cert_nonce);
+                       strvec_pushf(&proc->env_array,
+                                    "GIT_PUSH_CERT_NONCE_STATUS=%s",
+                                    nonce_status);
                        if (nonce_status == NONCE_SLOP)
-                               argv_array_pushf(&proc->env_array,
-                                                "GIT_PUSH_CERT_NONCE_SLOP=%ld",
-                                                nonce_stamp_slop);
+                               strvec_pushf(&proc->env_array,
+                                            "GIT_PUSH_CERT_NONCE_SLOP=%ld",
+                                            nonce_stamp_slop);
                }
        }
 }
@@ -720,16 +720,16 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed,
        if (feed_state->push_options) {
                int i;
                for (i = 0; i < feed_state->push_options->nr; i++)
-                       argv_array_pushf(&proc.env_array,
-                               "GIT_PUSH_OPTION_%d=%s", i,
-                               feed_state->push_options->items[i].string);
-               argv_array_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT=%d",
-                                feed_state->push_options->nr);
+                       strvec_pushf(&proc.env_array,
+                                    "GIT_PUSH_OPTION_%d=%s", i,
+                                    feed_state->push_options->items[i].string);
+               strvec_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT=%d",
+                            feed_state->push_options->nr);
        } else
-               argv_array_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT");
+               strvec_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT");
 
        if (tmp_objdir)
-               argv_array_pushv(&proc.env_array, tmp_objdir_env(tmp_objdir));
+               strvec_pushv(&proc.env_array, tmp_objdir_env(tmp_objdir));
 
        if (use_sideband) {
                memset(&muxer, 0, sizeof(muxer));
@@ -931,7 +931,7 @@ static int head_has_history(void)
 }
 
 static const char *push_to_deploy(unsigned char *sha1,
-                                 struct argv_array *env,
+                                 struct strvec *env,
                                  const char *work_tree)
 {
        const char *update_refresh[] = {
@@ -950,7 +950,7 @@ static const char *push_to_deploy(unsigned char *sha1,
        struct child_process child = CHILD_PROCESS_INIT;
 
        child.argv = update_refresh;
-       child.env = env->argv;
+       child.env = env->v;
        child.dir = work_tree;
        child.no_stdin = 1;
        child.stdout_to_stderr = 1;
@@ -961,7 +961,7 @@ static const char *push_to_deploy(unsigned char *sha1,
        /* run_command() does not clean up completely; reinitialize */
        child_process_init(&child);
        child.argv = diff_files;
-       child.env = env->argv;
+       child.env = env->v;
        child.dir = work_tree;
        child.no_stdin = 1;
        child.stdout_to_stderr = 1;
@@ -974,7 +974,7 @@ static const char *push_to_deploy(unsigned char *sha1,
 
        child_process_init(&child);
        child.argv = diff_index;
-       child.env = env->argv;
+       child.env = env->v;
        child.no_stdin = 1;
        child.no_stdout = 1;
        child.stdout_to_stderr = 0;
@@ -985,7 +985,7 @@ static const char *push_to_deploy(unsigned char *sha1,
        read_tree[3] = hash_to_hex(sha1);
        child_process_init(&child);
        child.argv = read_tree;
-       child.env = env->argv;
+       child.env = env->v;
        child.dir = work_tree;
        child.no_stdin = 1;
        child.no_stdout = 1;
@@ -1000,11 +1000,11 @@ static const char *push_to_deploy(unsigned char *sha1,
 static const char *push_to_checkout_hook = "push-to-checkout";
 
 static const char *push_to_checkout(unsigned char *hash,
-                                   struct argv_array *env,
+                                   struct strvec *env,
                                    const char *work_tree)
 {
-       argv_array_pushf(env, "GIT_WORK_TREE=%s", absolute_path(work_tree));
-       if (run_hook_le(env->argv, push_to_checkout_hook,
+       strvec_pushf(env, "GIT_WORK_TREE=%s", absolute_path(work_tree));
+       if (run_hook_le(env->v, push_to_checkout_hook,
                        hash_to_hex(hash), NULL))
                return "push-to-checkout hook declined";
        else
@@ -1014,7 +1014,7 @@ static const char *push_to_checkout(unsigned char *hash,
 static const char *update_worktree(unsigned char *sha1, const struct worktree *worktree)
 {
        const char *retval, *work_tree, *git_dir = NULL;
-       struct argv_array env = ARGV_ARRAY_INIT;
+       struct strvec env = STRVEC_INIT;
 
        if (worktree && worktree->path)
                work_tree = worktree->path;
@@ -1030,14 +1030,14 @@ static const char *update_worktree(unsigned char *sha1, const struct worktree *w
        if (!git_dir)
                git_dir = get_git_dir();
 
-       argv_array_pushf(&env, "GIT_DIR=%s", absolute_path(git_dir));
+       strvec_pushf(&env, "GIT_DIR=%s", absolute_path(git_dir));
 
        if (!find_hook(push_to_checkout_hook))
                retval = push_to_deploy(sha1, &env, work_tree);
        else
                retval = push_to_checkout(sha1, &env, work_tree);
 
-       argv_array_clear(&env);
+       strvec_clear(&env);
        return retval;
 }
 
@@ -1205,11 +1205,11 @@ static void run_update_post_hook(struct command *commands)
        for (cmd = commands; cmd; cmd = cmd->next) {
                if (cmd->error_string || cmd->did_not_exist)
                        continue;
-               if (!proc.args.argc)
-                       argv_array_push(&proc.args, hook);
-               argv_array_push(&proc.args, cmd->ref_name);
+               if (!proc.args.nr)
+                       strvec_push(&proc.args, hook);
+               strvec_push(&proc.args, cmd->ref_name);
        }
-       if (!proc.args.argc)
+       if (!proc.args.nr)
                return;
 
        proc.no_stdin = 1;
@@ -1715,10 +1715,10 @@ static const char *parse_pack_header(struct pack_header *hdr)
 
 static const char *pack_lockfile;
 
-static void push_header_arg(struct argv_array *args, struct pack_header *hdr)
+static void push_header_arg(struct strvec *args, struct pack_header *hdr)
 {
-       argv_array_pushf(args, "--pack_header=%"PRIu32",%"PRIu32,
-                       ntohl(hdr->hdr_version), ntohl(hdr->hdr_entries));
+       strvec_pushf(args, "--pack_header=%"PRIu32",%"PRIu32,
+                    ntohl(hdr->hdr_version), ntohl(hdr->hdr_entries));
 }
 
 static const char *unpack(int err_fd, struct shallow_info *si)
@@ -1742,8 +1742,8 @@ static const char *unpack(int err_fd, struct shallow_info *si)
 
        if (si->nr_ours || si->nr_theirs) {
                alt_shallow_file = setup_temporary_shallow(si->shallow);
-               argv_array_push(&child.args, "--shallow-file");
-               argv_array_push(&child.args, alt_shallow_file);
+               strvec_push(&child.args, "--shallow-file");
+               strvec_push(&child.args, alt_shallow_file);
        }
 
        tmp_objdir = tmp_objdir_create();
@@ -1762,16 +1762,16 @@ static const char *unpack(int err_fd, struct shallow_info *si)
        tmp_objdir_add_as_alternate(tmp_objdir);
 
        if (ntohl(hdr.hdr_entries) < unpack_limit) {
-               argv_array_push(&child.args, "unpack-objects");
+               strvec_push(&child.args, "unpack-objects");
                push_header_arg(&child.args, &hdr);
                if (quiet)
-                       argv_array_push(&child.args, "-q");
+                       strvec_push(&child.args, "-q");
                if (fsck_objects)
-                       argv_array_pushf(&child.args, "--strict%s",
-                               fsck_msg_types.buf);
+                       strvec_pushf(&child.args, "--strict%s",
+                                    fsck_msg_types.buf);
                if (max_input_size)
-                       argv_array_pushf(&child.args, "--max-input-size=%"PRIuMAX,
-                               (uintmax_t)max_input_size);
+                       strvec_pushf(&child.args, "--max-input-size=%"PRIuMAX,
+                                    (uintmax_t)max_input_size);
                child.no_stdout = 1;
                child.err = err_fd;
                child.git_cmd = 1;
@@ -1781,28 +1781,28 @@ static const char *unpack(int err_fd, struct shallow_info *si)
        } else {
                char hostname[HOST_NAME_MAX + 1];
 
-               argv_array_pushl(&child.args, "index-pack", "--stdin", NULL);
+               strvec_pushl(&child.args, "index-pack", "--stdin", NULL);
                push_header_arg(&child.args, &hdr);
 
                if (xgethostname(hostname, sizeof(hostname)))
                        xsnprintf(hostname, sizeof(hostname), "localhost");
-               argv_array_pushf(&child.args,
-                                "--keep=receive-pack %"PRIuMAX" on %s",
-                                (uintmax_t)getpid(),
-                                hostname);
+               strvec_pushf(&child.args,
+                            "--keep=receive-pack %"PRIuMAX" on %s",
+                            (uintmax_t)getpid(),
+                            hostname);
 
                if (!quiet && err_fd)
-                       argv_array_push(&child.args, "--show-resolving-progress");
+                       strvec_push(&child.args, "--show-resolving-progress");
                if (use_sideband)
-                       argv_array_push(&child.args, "--report-end-of-input");
+                       strvec_push(&child.args, "--report-end-of-input");
                if (fsck_objects)
-                       argv_array_pushf(&child.args, "--strict%s",
-                               fsck_msg_types.buf);
+                       strvec_pushf(&child.args, "--strict%s",
+                                    fsck_msg_types.buf);
                if (!reject_thin)
-                       argv_array_push(&child.args, "--fix-thin");
+                       strvec_push(&child.args, "--fix-thin");
                if (max_input_size)
-                       argv_array_pushf(&child.args, "--max-input-size=%"PRIuMAX,
-                               (uintmax_t)max_input_size);
+                       strvec_pushf(&child.args, "--max-input-size=%"PRIuMAX,
+                                    (uintmax_t)max_input_size);
                child.out = -1;
                child.err = err_fd;
                child.git_cmd = 1;
index 6a9127a33c019c5e6336075b5f68c7514d720b04..fd3538d4f0e6924214bedc36c132f631d17f4c8b 100644 (file)
@@ -117,12 +117,12 @@ static char *strip_escapes(const char *str, const char *service,
        }
 }
 
-static void parse_argv(struct argv_array *out, const char *arg, const char *service)
+static void parse_argv(struct strvec *out, const char *arg, const char *service)
 {
        while (*arg) {
                char *expanded = strip_escapes(arg, service, &arg);
                if (expanded)
-                       argv_array_push(out, expanded);
+                       strvec_push(out, expanded);
                free(expanded);
        }
 }
index e8377994e57a2286f9cea329578c8f104a392b88..542f56e3878b6694e7da6c6141b5e249c511a51e 100644 (file)
@@ -10,7 +10,7 @@
 #include "refs.h"
 #include "refspec.h"
 #include "object-store.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "commit-reach.h"
 
 static const char * const builtin_remote_usage[] = {
@@ -478,6 +478,7 @@ static int get_head_names(const struct ref *remote_refs, struct ref_states *stat
        struct ref *fetch_map = NULL, **fetch_map_tail = &fetch_map;
        struct refspec_item refspec;
 
+       memset(&refspec, 0, sizeof(refspec));
        refspec.force = 0;
        refspec.pattern = 1;
        refspec.src = refspec.dst = "refs/heads/*";
@@ -1451,35 +1452,35 @@ static int update(int argc, const char **argv)
                         N_("prune remotes after fetching")),
                OPT_END()
        };
-       struct argv_array fetch_argv = ARGV_ARRAY_INIT;
+       struct strvec fetch_argv = STRVEC_INIT;
        int default_defined = 0;
        int retval;
 
        argc = parse_options(argc, argv, NULL, options, builtin_remote_update_usage,
                             PARSE_OPT_KEEP_ARGV0);
 
-       argv_array_push(&fetch_argv, "fetch");
+       strvec_push(&fetch_argv, "fetch");
 
        if (prune != -1)
-               argv_array_push(&fetch_argv, prune ? "--prune" : "--no-prune");
+               strvec_push(&fetch_argv, prune ? "--prune" : "--no-prune");
        if (verbose)
-               argv_array_push(&fetch_argv, "-v");
-       argv_array_push(&fetch_argv, "--multiple");
+               strvec_push(&fetch_argv, "-v");
+       strvec_push(&fetch_argv, "--multiple");
        if (argc < 2)
-               argv_array_push(&fetch_argv, "default");
+               strvec_push(&fetch_argv, "default");
        for (i = 1; i < argc; i++)
-               argv_array_push(&fetch_argv, argv[i]);
+               strvec_push(&fetch_argv, argv[i]);
 
-       if (strcmp(fetch_argv.argv[fetch_argv.argc-1], "default") == 0) {
+       if (strcmp(fetch_argv.v[fetch_argv.nr-1], "default") == 0) {
                git_config(get_remote_default, &default_defined);
                if (!default_defined) {
-                       argv_array_pop(&fetch_argv);
-                       argv_array_push(&fetch_argv, "--all");
+                       strvec_pop(&fetch_argv);
+                       strvec_push(&fetch_argv, "--all");
                }
        }
 
-       retval = run_command_v_opt(fetch_argv.argv, RUN_GIT_CMD);
-       argv_array_clear(&fetch_argv);
+       retval = run_command_v_opt(fetch_argv.v, RUN_GIT_CMD);
+       strvec_clear(&fetch_argv);
        return retval;
 }
 
index df287739d9081cbccb203ca3f8cc744490e949ca..04c5ceaf7ec7e6de32b21d4a07ebb8384ee3068f 100644 (file)
@@ -7,7 +7,7 @@
 #include "sigchain.h"
 #include "strbuf.h"
 #include "string-list.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "midx.h"
 #include "packfile.h"
 #include "prune-packed.h"
@@ -153,28 +153,28 @@ struct pack_objects_args {
 static void prepare_pack_objects(struct child_process *cmd,
                                 const struct pack_objects_args *args)
 {
-       argv_array_push(&cmd->args, "pack-objects");
+       strvec_push(&cmd->args, "pack-objects");
        if (args->window)
-               argv_array_pushf(&cmd->args, "--window=%s", args->window);
+               strvec_pushf(&cmd->args, "--window=%s", args->window);
        if (args->window_memory)
-               argv_array_pushf(&cmd->args, "--window-memory=%s", args->window_memory);
+               strvec_pushf(&cmd->args, "--window-memory=%s", args->window_memory);
        if (args->depth)
-               argv_array_pushf(&cmd->args, "--depth=%s", args->depth);
+               strvec_pushf(&cmd->args, "--depth=%s", args->depth);
        if (args->threads)
-               argv_array_pushf(&cmd->args, "--threads=%s", args->threads);
+               strvec_pushf(&cmd->args, "--threads=%s", args->threads);
        if (args->max_pack_size)
-               argv_array_pushf(&cmd->args, "--max-pack-size=%s", args->max_pack_size);
+               strvec_pushf(&cmd->args, "--max-pack-size=%s", args->max_pack_size);
        if (args->no_reuse_delta)
-               argv_array_pushf(&cmd->args, "--no-reuse-delta");
+               strvec_pushf(&cmd->args, "--no-reuse-delta");
        if (args->no_reuse_object)
-               argv_array_pushf(&cmd->args, "--no-reuse-object");
+               strvec_pushf(&cmd->args, "--no-reuse-object");
        if (args->local)
-               argv_array_push(&cmd->args,  "--local");
+               strvec_push(&cmd->args,  "--local");
        if (args->quiet)
-               argv_array_push(&cmd->args,  "--quiet");
+               strvec_push(&cmd->args,  "--quiet");
        if (delta_base_offset)
-               argv_array_push(&cmd->args,  "--delta-base-offset");
-       argv_array_push(&cmd->args, packtmp);
+               strvec_push(&cmd->args,  "--delta-base-offset");
+       strvec_push(&cmd->args, packtmp);
        cmd->git_cmd = 1;
        cmd->out = -1;
 }
@@ -361,24 +361,24 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
        prepare_pack_objects(&cmd, &po_args);
 
-       argv_array_push(&cmd.args, "--keep-true-parents");
+       strvec_push(&cmd.args, "--keep-true-parents");
        if (!pack_kept_objects)
-               argv_array_push(&cmd.args, "--honor-pack-keep");
+               strvec_push(&cmd.args, "--honor-pack-keep");
        for (i = 0; i < keep_pack_list.nr; i++)
-               argv_array_pushf(&cmd.args, "--keep-pack=%s",
-                                keep_pack_list.items[i].string);
-       argv_array_push(&cmd.args, "--non-empty");
-       argv_array_push(&cmd.args, "--all");
-       argv_array_push(&cmd.args, "--reflog");
-       argv_array_push(&cmd.args, "--indexed-objects");
+               strvec_pushf(&cmd.args, "--keep-pack=%s",
+                            keep_pack_list.items[i].string);
+       strvec_push(&cmd.args, "--non-empty");
+       strvec_push(&cmd.args, "--all");
+       strvec_push(&cmd.args, "--reflog");
+       strvec_push(&cmd.args, "--indexed-objects");
        if (has_promisor_remote())
-               argv_array_push(&cmd.args, "--exclude-promisor-objects");
+               strvec_push(&cmd.args, "--exclude-promisor-objects");
        if (write_bitmaps > 0)
-               argv_array_push(&cmd.args, "--write-bitmap-index");
+               strvec_push(&cmd.args, "--write-bitmap-index");
        else if (write_bitmaps < 0)
-               argv_array_push(&cmd.args, "--write-bitmap-index-quiet");
+               strvec_push(&cmd.args, "--write-bitmap-index-quiet");
        if (use_delta_islands)
-               argv_array_push(&cmd.args, "--delta-islands");
+               strvec_push(&cmd.args, "--delta-islands");
 
        if (pack_everything & ALL_INTO_ONE) {
                get_non_kept_pack_filenames(&existing_packs, &keep_pack_list);
@@ -387,23 +387,23 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
                if (existing_packs.nr && delete_redundant) {
                        if (unpack_unreachable) {
-                               argv_array_pushf(&cmd.args,
-                                               "--unpack-unreachable=%s",
-                                               unpack_unreachable);
-                               argv_array_push(&cmd.env_array, "GIT_REF_PARANOIA=1");
+                               strvec_pushf(&cmd.args,
+                                            "--unpack-unreachable=%s",
+                                            unpack_unreachable);
+                               strvec_push(&cmd.env_array, "GIT_REF_PARANOIA=1");
                        } else if (pack_everything & LOOSEN_UNREACHABLE) {
-                               argv_array_push(&cmd.args,
-                                               "--unpack-unreachable");
+                               strvec_push(&cmd.args,
+                                           "--unpack-unreachable");
                        } else if (keep_unreachable) {
-                               argv_array_push(&cmd.args, "--keep-unreachable");
-                               argv_array_push(&cmd.args, "--pack-loose-unreachable");
+                               strvec_push(&cmd.args, "--keep-unreachable");
+                               strvec_push(&cmd.args, "--pack-loose-unreachable");
                        } else {
-                               argv_array_push(&cmd.env_array, "GIT_REF_PARANOIA=1");
+                               strvec_push(&cmd.env_array, "GIT_REF_PARANOIA=1");
                        }
                }
        } else {
-               argv_array_push(&cmd.args, "--unpacked");
-               argv_array_push(&cmd.args, "--incremental");
+               strvec_push(&cmd.args, "--unpacked");
+               strvec_push(&cmd.args, "--incremental");
        }
 
        cmd.no_stdin = 1;
index b36d17a657f3e62ae4abc450b616e9c7398377c9..cd48765911746420766736eaa3be7160cc790ce2 100644 (file)
@@ -228,13 +228,13 @@ static int export_object(const struct object_id *oid, enum object_type type,
        if (fd < 0)
                return error_errno(_("unable to open %s for writing"), filename);
 
-       argv_array_push(&cmd.args, "--no-replace-objects");
-       argv_array_push(&cmd.args, "cat-file");
+       strvec_push(&cmd.args, "--no-replace-objects");
+       strvec_push(&cmd.args, "cat-file");
        if (raw)
-               argv_array_push(&cmd.args, type_name(type));
+               strvec_push(&cmd.args, type_name(type));
        else
-               argv_array_push(&cmd.args, "-p");
-       argv_array_push(&cmd.args, oid_to_hex(oid));
+               strvec_push(&cmd.args, "-p");
+       strvec_push(&cmd.args, oid_to_hex(oid));
        cmd.git_cmd = 1;
        cmd.out = fd;
 
@@ -502,7 +502,7 @@ static int convert_graft_file(int force)
        const char *graft_file = get_graft_file(the_repository);
        FILE *fp = fopen_or_warn(graft_file, "r");
        struct strbuf buf = STRBUF_INIT, err = STRBUF_INIT;
-       struct argv_array args = ARGV_ARRAY_INIT;
+       struct strvec args = STRVEC_INIT;
 
        if (!fp)
                return -1;
@@ -512,10 +512,10 @@ static int convert_graft_file(int force)
                if (*buf.buf == '#')
                        continue;
 
-               argv_array_split(&args, buf.buf);
-               if (args.argc && create_graft(args.argc, args.argv, force, 1))
+               strvec_split(&args, buf.buf);
+               if (args.nr && create_graft(args.nr, args.v, force, 1))
                        strbuf_addf(&err, "\n\t%s", buf.buf);
-               argv_array_clear(&args);
+               strvec_clear(&args);
        }
        fclose(fp);
 
index f520111eda09f1d167524b31919daaea3e5a5a31..25c6c3b38d4b120687bb02220c3db25af2ae66de 100644 (file)
@@ -637,8 +637,15 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 
        if (bisect_list) {
                int reaches, all;
+               unsigned bisect_flags = 0;
 
-               find_bisection(&revs.commits, &reaches, &all, bisect_find_all);
+               if (bisect_find_all)
+                       bisect_flags |= FIND_BISECTION_ALL;
+
+               if (revs.first_parent_only)
+                       bisect_flags |= FIND_BISECTION_FIRST_PARENT_ONLY;
+
+               find_bisection(&revs.commits, &reaches, &all, bisect_flags);
 
                if (bisect_show_vars)
                        return show_bisect_vars(&info, reaches, all);
index 7e52ee91264a63713da5178add167f8d62c36877..7eae5f38016dab4b0f4e9a4fdc7d496962389464 100644 (file)
@@ -4,7 +4,7 @@
 #include "refs.h"
 #include "builtin.h"
 #include "color.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "parse-options.h"
 #include "dir.h"
 #include "commit-slab.h"
@@ -20,7 +20,7 @@ static const char* show_branch_usage[] = {
 
 static int showbranch_use_color = -1;
 
-static struct argv_array default_args = ARGV_ARRAY_INIT;
+static struct strvec default_args = STRVEC_INIT;
 
 /*
  * TODO: convert this use of commit->object.flags to commit-slab
@@ -561,9 +561,9 @@ static int git_show_branch_config(const char *var, const char *value, void *cb)
                 * default_arg is now passed to parse_options(), so we need to
                 * mimic the real argv a bit better.
                 */
-               if (!default_args.argc)
-                       argv_array_push(&default_args, "show-branch");
-               argv_array_push(&default_args, value);
+               if (!default_args.nr)
+                       strvec_push(&default_args, "show-branch");
+               strvec_push(&default_args, value);
                return 0;
        }
 
@@ -684,9 +684,9 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
        git_config(git_show_branch_config, NULL);
 
        /* If nothing is specified, try the default first */
-       if (ac == 1 && default_args.argc) {
-               ac = default_args.argc;
-               av = default_args.argv;
+       if (ac == 1 && default_args.nr) {
+               ac = default_args.nr;
+               av = default_args.v;
        }
 
        ac = parse_options(ac, av, prefix, builtin_show_branch_options,
index 0c52a3b849c4c6f811995f3be89284052c2dd313..4bdfaf839705a69c58fa631055eb4fc8fdff0ed4 100644 (file)
@@ -7,7 +7,7 @@
 #include "cache-tree.h"
 #include "unpack-trees.h"
 #include "merge-recursive.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "run-command.h"
 #include "dir.h"
 #include "rerere.h"
@@ -277,8 +277,8 @@ static int diff_tree_binary(struct strbuf *out, struct object_id *w_commit)
         * however it should be done together with apply_cached.
         */
        cp.git_cmd = 1;
-       argv_array_pushl(&cp.args, "diff-tree", "--binary", NULL);
-       argv_array_pushf(&cp.args, "%s^2^..%s^2", w_commit_hex, w_commit_hex);
+       strvec_pushl(&cp.args, "diff-tree", "--binary", NULL);
+       strvec_pushf(&cp.args, "%s^2^..%s^2", w_commit_hex, w_commit_hex);
 
        return pipe_command(&cp, NULL, 0, out, 0, NULL, 0);
 }
@@ -293,7 +293,7 @@ static int apply_cached(struct strbuf *out)
         * buffer.
         */
        cp.git_cmd = 1;
-       argv_array_pushl(&cp.args, "apply", "--cached", NULL);
+       strvec_pushl(&cp.args, "apply", "--cached", NULL);
        return pipe_command(&cp, out->buf, out->len, NULL, 0, NULL, 0);
 }
 
@@ -306,7 +306,7 @@ static int reset_head(void)
         * API for resetting.
         */
        cp.git_cmd = 1;
-       argv_array_push(&cp.args, "reset");
+       strvec_push(&cp.args, "reset");
 
        return run_command(&cp);
 }
@@ -335,9 +335,9 @@ static int get_newly_staged(struct strbuf *out, struct object_id *c_tree)
         * converted together with update_index.
         */
        cp.git_cmd = 1;
-       argv_array_pushl(&cp.args, "diff-index", "--cached", "--name-only",
-                        "--diff-filter=A", NULL);
-       argv_array_push(&cp.args, c_tree_hex);
+       strvec_pushl(&cp.args, "diff-index", "--cached", "--name-only",
+                    "--diff-filter=A", NULL);
+       strvec_push(&cp.args, c_tree_hex);
        return pipe_command(&cp, NULL, 0, out, 0, NULL, 0);
 }
 
@@ -350,7 +350,7 @@ static int update_index(struct strbuf *out)
         * function exposed in order to remove this forking.
         */
        cp.git_cmd = 1;
-       argv_array_pushl(&cp.args, "update-index", "--add", "--stdin", NULL);
+       strvec_pushl(&cp.args, "update-index", "--add", "--stdin", NULL);
        return pipe_command(&cp, out->buf, out->len, NULL, 0, NULL, 0);
 }
 
@@ -365,10 +365,10 @@ static int restore_untracked(struct object_id *u_tree)
         * run_command to fork processes that will not interfere.
         */
        cp.git_cmd = 1;
-       argv_array_push(&cp.args, "read-tree");
-       argv_array_push(&cp.args, oid_to_hex(u_tree));
-       argv_array_pushf(&cp.env_array, "GIT_INDEX_FILE=%s",
-                        stash_index_path.buf);
+       strvec_push(&cp.args, "read-tree");
+       strvec_push(&cp.args, oid_to_hex(u_tree));
+       strvec_pushf(&cp.env_array, "GIT_INDEX_FILE=%s",
+                    stash_index_path.buf);
        if (run_command(&cp)) {
                remove_path(stash_index_path.buf);
                return -1;
@@ -376,9 +376,9 @@ static int restore_untracked(struct object_id *u_tree)
 
        child_process_init(&cp);
        cp.git_cmd = 1;
-       argv_array_pushl(&cp.args, "checkout-index", "--all", NULL);
-       argv_array_pushf(&cp.env_array, "GIT_INDEX_FILE=%s",
-                        stash_index_path.buf);
+       strvec_pushl(&cp.args, "checkout-index", "--all", NULL);
+       strvec_pushf(&cp.env_array, "GIT_INDEX_FILE=%s",
+                    stash_index_path.buf);
 
        res = run_command(&cp);
        remove_path(stash_index_path.buf);
@@ -499,11 +499,11 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
                 */
                cp.git_cmd = 1;
                cp.dir = prefix;
-               argv_array_pushf(&cp.env_array, GIT_WORK_TREE_ENVIRONMENT"=%s",
-                                absolute_path(get_git_work_tree()));
-               argv_array_pushf(&cp.env_array, GIT_DIR_ENVIRONMENT"=%s",
-                                absolute_path(get_git_dir()));
-               argv_array_push(&cp.args, "status");
+               strvec_pushf(&cp.env_array, GIT_WORK_TREE_ENVIRONMENT"=%s",
+                            absolute_path(get_git_work_tree()));
+               strvec_pushf(&cp.env_array, GIT_DIR_ENVIRONMENT"=%s",
+                            absolute_path(get_git_dir()));
+               strvec_push(&cp.args, "status");
                run_command(&cp);
        }
 
@@ -546,9 +546,9 @@ static int do_drop_stash(struct stash_info *info, int quiet)
         */
 
        cp_reflog.git_cmd = 1;
-       argv_array_pushl(&cp_reflog.args, "reflog", "delete", "--updateref",
-                        "--rewrite", NULL);
-       argv_array_push(&cp_reflog.args, info->revision.buf);
+       strvec_pushl(&cp_reflog.args, "reflog", "delete", "--updateref",
+                    "--rewrite", NULL);
+       strvec_push(&cp_reflog.args, info->revision.buf);
        ret = run_command(&cp_reflog);
        if (!ret) {
                if (!quiet)
@@ -566,8 +566,8 @@ static int do_drop_stash(struct stash_info *info, int quiet)
        cp.git_cmd = 1;
        /* Even though --quiet is specified, rev-parse still outputs the hash */
        cp.no_stdout = 1;
-       argv_array_pushl(&cp.args, "rev-parse", "--verify", "--quiet", NULL);
-       argv_array_pushf(&cp.args, "%s@{0}", ref_stash);
+       strvec_pushl(&cp.args, "rev-parse", "--verify", "--quiet", NULL);
+       strvec_pushf(&cp.args, "%s@{0}", ref_stash);
        ret = run_command(&cp);
 
        /* do_clear_stash if we just dropped the last stash entry */
@@ -663,9 +663,9 @@ static int branch_stash(int argc, const char **argv, const char *prefix)
                return -1;
 
        cp.git_cmd = 1;
-       argv_array_pushl(&cp.args, "checkout", "-b", NULL);
-       argv_array_push(&cp.args, branch);
-       argv_array_push(&cp.args, oid_to_hex(&info.b_commit));
+       strvec_pushl(&cp.args, "checkout", "-b", NULL);
+       strvec_push(&cp.args, branch);
+       strvec_push(&cp.args, oid_to_hex(&info.b_commit));
        ret = run_command(&cp);
        if (!ret)
                ret = do_apply_stash(prefix, &info, 1, 0);
@@ -692,11 +692,11 @@ static int list_stash(int argc, const char **argv, const char *prefix)
                return 0;
 
        cp.git_cmd = 1;
-       argv_array_pushl(&cp.args, "log", "--format=%gd: %gs", "-g",
-                        "--first-parent", "-m", NULL);
-       argv_array_pushv(&cp.args, argv);
-       argv_array_push(&cp.args, ref_stash);
-       argv_array_push(&cp.args, "--");
+       strvec_pushl(&cp.args, "log", "--format=%gd: %gs", "-g",
+                    "--first-parent", "-m", NULL);
+       strvec_pushv(&cp.args, argv);
+       strvec_push(&cp.args, ref_stash);
+       strvec_push(&cp.args, "--");
        return run_command(&cp);
 }
 
@@ -727,8 +727,8 @@ static int show_stash(int argc, const char **argv, const char *prefix)
        int ret = 0;
        struct stash_info info;
        struct rev_info rev;
-       struct argv_array stash_args = ARGV_ARRAY_INIT;
-       struct argv_array revision_args = ARGV_ARRAY_INIT;
+       struct strvec stash_args = STRVEC_INIT;
+       struct strvec revision_args = STRVEC_INIT;
        struct option options[] = {
                OPT_END()
        };
@@ -737,16 +737,16 @@ static int show_stash(int argc, const char **argv, const char *prefix)
        git_config(git_diff_ui_config, NULL);
        init_revisions(&rev, prefix);
 
-       argv_array_push(&revision_args, argv[0]);
+       strvec_push(&revision_args, argv[0]);
        for (i = 1; i < argc; i++) {
                if (argv[i][0] != '-')
-                       argv_array_push(&stash_args, argv[i]);
+                       strvec_push(&stash_args, argv[i]);
                else
-                       argv_array_push(&revision_args, argv[i]);
+                       strvec_push(&revision_args, argv[i]);
        }
 
-       ret = get_stash_info(&info, stash_args.argc, stash_args.argv);
-       argv_array_clear(&stash_args);
+       ret = get_stash_info(&info, stash_args.nr, stash_args.v);
+       strvec_clear(&stash_args);
        if (ret)
                return -1;
 
@@ -754,7 +754,7 @@ static int show_stash(int argc, const char **argv, const char *prefix)
         * The config settings are applied only if there are not passed
         * any options.
         */
-       if (revision_args.argc == 1) {
+       if (revision_args.nr == 1) {
                if (show_stat)
                        rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT;
 
@@ -767,7 +767,7 @@ static int show_stash(int argc, const char **argv, const char *prefix)
                }
        }
 
-       argc = setup_revisions(revision_args.argc, revision_args.argv, &rev, NULL);
+       argc = setup_revisions(revision_args.nr, revision_args.v, &rev, NULL);
        if (argc > 1) {
                free_stash_info(&info);
                usage_with_options(git_stash_show_usage, options);
@@ -842,12 +842,12 @@ static int store_stash(int argc, const char **argv, const char *prefix)
        return do_store_stash(&obj, stash_msg, quiet);
 }
 
-static void add_pathspecs(struct argv_array *args,
+static void add_pathspecs(struct strvec *args,
                          const struct pathspec *ps) {
        int i;
 
        for (i = 0; i < ps->nr; i++)
-               argv_array_push(args, ps->items[i].original);
+               strvec_push(args, ps->items[i].original);
 }
 
 /*
@@ -864,7 +864,7 @@ static int get_untracked_files(const struct pathspec *ps, int include_untracked,
        int found = 0;
        struct dir_struct dir;
 
-       memset(&dir, 0, sizeof(dir));
+       dir_init(&dir);
        if (include_untracked != INCLUDE_ALL_FILES)
                setup_standard_excludes(&dir);
 
@@ -875,12 +875,9 @@ static int get_untracked_files(const struct pathspec *ps, int include_untracked,
                strbuf_addstr(untracked_files, ent->name);
                /* NUL-terminate: will be fed to update-index -z */
                strbuf_addch(untracked_files, '\0');
-               free(ent);
        }
 
-       free(dir.entries);
-       free(dir.ignored);
-       clear_directory(&dir);
+       dir_clear(&dir);
        return found;
 }
 
@@ -960,9 +957,9 @@ static int save_untracked_files(struct stash_info *info, struct strbuf *msg,
        struct index_state istate = { NULL };
 
        cp_upd_index.git_cmd = 1;
-       argv_array_pushl(&cp_upd_index.args, "update-index", "-z", "--add",
-                        "--remove", "--stdin", NULL);
-       argv_array_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s",
+       strvec_pushl(&cp_upd_index.args, "update-index", "-z", "--add",
+                    "--remove", "--stdin", NULL);
+       strvec_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s",
                         stash_index_path.buf);
 
        strbuf_addf(&untracked_msg, "untracked files on %s\n", msg->buf);
@@ -1003,9 +1000,9 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
        remove_path(stash_index_path.buf);
 
        cp_read_tree.git_cmd = 1;
-       argv_array_pushl(&cp_read_tree.args, "read-tree", "HEAD", NULL);
-       argv_array_pushf(&cp_read_tree.env_array, "GIT_INDEX_FILE=%s",
-                        stash_index_path.buf);
+       strvec_pushl(&cp_read_tree.args, "read-tree", "HEAD", NULL);
+       strvec_pushf(&cp_read_tree.env_array, "GIT_INDEX_FILE=%s",
+                    stash_index_path.buf);
        if (run_command(&cp_read_tree)) {
                ret = -1;
                goto done;
@@ -1034,8 +1031,8 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
        }
 
        cp_diff_tree.git_cmd = 1;
-       argv_array_pushl(&cp_diff_tree.args, "diff-tree", "-p", "-U1", "HEAD",
-                        oid_to_hex(&info->w_tree), "--", NULL);
+       strvec_pushl(&cp_diff_tree.args, "diff-tree", "-p", "-U1", "HEAD",
+                    oid_to_hex(&info->w_tree), "--", NULL);
        if (pipe_command(&cp_diff_tree, NULL, 0, out_patch, 0, NULL, 0)) {
                ret = -1;
                goto done;
@@ -1088,11 +1085,11 @@ static int stash_working_tree(struct stash_info *info, const struct pathspec *ps
        }
 
        cp_upd_index.git_cmd = 1;
-       argv_array_pushl(&cp_upd_index.args, "update-index",
-                        "--ignore-skip-worktree-entries",
-                        "-z", "--add", "--remove", "--stdin", NULL);
-       argv_array_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s",
-                        stash_index_path.buf);
+       strvec_pushl(&cp_upd_index.args, "update-index",
+                    "--ignore-skip-worktree-entries",
+                    "-z", "--add", "--remove", "--stdin", NULL);
+       strvec_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s",
+                    stash_index_path.buf);
 
        if (pipe_command(&cp_upd_index, diff_output.buf, diff_output.len,
                         NULL, 0, NULL, 0)) {
@@ -1342,10 +1339,10 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
                        struct child_process cp = CHILD_PROCESS_INIT;
 
                        cp.git_cmd = 1;
-                       argv_array_pushl(&cp.args, "clean", "--force",
-                                        "--quiet", "-d", NULL);
+                       strvec_pushl(&cp.args, "clean", "--force",
+                                    "--quiet", "-d", NULL);
                        if (include_untracked == INCLUDE_ALL_FILES)
-                               argv_array_push(&cp.args, "-x");
+                               strvec_push(&cp.args, "-x");
                        if (run_command(&cp)) {
                                ret = -1;
                                goto done;
@@ -1359,12 +1356,12 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
                        struct strbuf out = STRBUF_INIT;
 
                        cp_add.git_cmd = 1;
-                       argv_array_push(&cp_add.args, "add");
+                       strvec_push(&cp_add.args, "add");
                        if (!include_untracked)
-                               argv_array_push(&cp_add.args, "-u");
+                               strvec_push(&cp_add.args, "-u");
                        if (include_untracked == INCLUDE_ALL_FILES)
-                               argv_array_push(&cp_add.args, "--force");
-                       argv_array_push(&cp_add.args, "--");
+                               strvec_push(&cp_add.args, "--force");
+                       strvec_push(&cp_add.args, "--");
                        add_pathspecs(&cp_add.args, ps);
                        if (run_command(&cp_add)) {
                                ret = -1;
@@ -1372,9 +1369,9 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
                        }
 
                        cp_diff.git_cmd = 1;
-                       argv_array_pushl(&cp_diff.args, "diff-index", "-p",
-                                        "--cached", "--binary", "HEAD", "--",
-                                        NULL);
+                       strvec_pushl(&cp_diff.args, "diff-index", "-p",
+                                    "--cached", "--binary", "HEAD", "--",
+                                    NULL);
                        add_pathspecs(&cp_diff.args, ps);
                        if (pipe_command(&cp_diff, NULL, 0, &out, 0, NULL, 0)) {
                                ret = -1;
@@ -1382,8 +1379,8 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
                        }
 
                        cp_apply.git_cmd = 1;
-                       argv_array_pushl(&cp_apply.args, "apply", "--index",
-                                        "-R", NULL);
+                       strvec_pushl(&cp_apply.args, "apply", "--index",
+                                    "-R", NULL);
                        if (pipe_command(&cp_apply, out.buf, out.len, NULL, 0,
                                         NULL, 0)) {
                                ret = -1;
@@ -1392,8 +1389,8 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
                } else {
                        struct child_process cp = CHILD_PROCESS_INIT;
                        cp.git_cmd = 1;
-                       argv_array_pushl(&cp.args, "reset", "--hard", "-q",
-                                        "--no-recurse-submodules", NULL);
+                       strvec_pushl(&cp.args, "reset", "--hard", "-q",
+                                    "--no-recurse-submodules", NULL);
                        if (run_command(&cp)) {
                                ret = -1;
                                goto done;
@@ -1404,10 +1401,10 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
                        struct child_process cp = CHILD_PROCESS_INIT;
 
                        cp.git_cmd = 1;
-                       argv_array_pushl(&cp.args, "checkout", "--no-overlay",
-                                        oid_to_hex(&info.i_tree), "--", NULL);
+                       strvec_pushl(&cp.args, "checkout", "--no-overlay",
+                                    oid_to_hex(&info.i_tree), "--", NULL);
                        if (!ps->nr)
-                               argv_array_push(&cp.args, ":/");
+                               strvec_push(&cp.args, ":/");
                        else
                                add_pathspecs(&cp.args, ps);
                        if (run_command(&cp)) {
@@ -1420,7 +1417,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
                struct child_process cp = CHILD_PROCESS_INIT;
 
                cp.git_cmd = 1;
-               argv_array_pushl(&cp.args, "apply", "-R", NULL);
+               strvec_pushl(&cp.args, "apply", "-R", NULL);
 
                if (pipe_command(&cp, patch.buf, patch.len, NULL, 0, NULL, 0)) {
                        if (!quiet)
@@ -1434,7 +1431,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
                        struct child_process cp = CHILD_PROCESS_INIT;
 
                        cp.git_cmd = 1;
-                       argv_array_pushl(&cp.args, "reset", "-q", "--", NULL);
+                       strvec_pushl(&cp.args, "reset", "-q", "--", NULL);
                        add_pathspecs(&cp.args, ps);
                        if (run_command(&cp)) {
                                ret = -1;
@@ -1560,7 +1557,7 @@ int cmd_stash(int argc, const char **argv, const char *prefix)
 {
        pid_t pid = getpid();
        const char *index_file;
-       struct argv_array args = ARGV_ARRAY_INIT;
+       struct strvec args = STRVEC_INIT;
 
        struct option options[] = {
                OPT_END()
@@ -1609,7 +1606,7 @@ int cmd_stash(int argc, const char **argv, const char *prefix)
                              git_stash_usage, options);
 
        /* Assume 'stash push' */
-       argv_array_push(&args, "push");
-       argv_array_pushv(&args, argv);
-       return !!push_stash(args.argc, args.argv, prefix, 1);
+       strvec_push(&args, "push");
+       strvec_pushv(&args, argv);
+       return !!push_stash(args.nr, args.v, prefix, 1);
 }
index a1c75607c72e190a10cc7af0184a41b04f5e77b5..a59d8e4bda615cf843515da2312febdf2c72c213 100644 (file)
@@ -294,9 +294,9 @@ static char *compute_rev_name(const char *sub_path, const char* object_id)
                cp.git_cmd = 1;
                cp.no_stderr = 1;
 
-               argv_array_push(&cp.args, "describe");
-               argv_array_pushv(&cp.args, *d);
-               argv_array_push(&cp.args, object_id);
+               strvec_push(&cp.args, "describe");
+               strvec_pushv(&cp.args, *d);
+               strvec_push(&cp.args, object_id);
 
                if (!capture_command(&cp, &sb, 0)) {
                        strbuf_strip_suffix(&sb, "\n");
@@ -495,12 +495,12 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
                char *toplevel = xgetcwd();
                struct strbuf sb = STRBUF_INIT;
 
-               argv_array_pushf(&cp.env_array, "name=%s", sub->name);
-               argv_array_pushf(&cp.env_array, "sm_path=%s", path);
-               argv_array_pushf(&cp.env_array, "displaypath=%s", displaypath);
-               argv_array_pushf(&cp.env_array, "sha1=%s",
-                               oid_to_hex(ce_oid));
-               argv_array_pushf(&cp.env_array, "toplevel=%s", toplevel);
+               strvec_pushf(&cp.env_array, "name=%s", sub->name);
+               strvec_pushf(&cp.env_array, "sm_path=%s", path);
+               strvec_pushf(&cp.env_array, "displaypath=%s", displaypath);
+               strvec_pushf(&cp.env_array, "sha1=%s",
+                            oid_to_hex(ce_oid));
+               strvec_pushf(&cp.env_array, "toplevel=%s", toplevel);
 
                /*
                 * Since the path variable was accessible from the script
@@ -509,15 +509,15 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
                 * on windows. And since environment variables are
                 * case-insensitive in windows, it interferes with the
                 * existing PATH variable. Hence, to avoid that, we expose
-                * path via the args argv_array and not via env_array.
+                * path via the args strvec and not via env_array.
                 */
                sq_quote_buf(&sb, path);
-               argv_array_pushf(&cp.args, "path=%s; %s",
-                                sb.buf, info->argv[0]);
+               strvec_pushf(&cp.args, "path=%s; %s",
+                            sb.buf, info->argv[0]);
                strbuf_release(&sb);
                free(toplevel);
        } else {
-               argv_array_pushv(&cp.args, info->argv);
+               strvec_pushv(&cp.args, info->argv);
        }
 
        if (!info->quiet)
@@ -534,16 +534,16 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
                cpr.dir = path;
                prepare_submodule_repo_env(&cpr.env_array);
 
-               argv_array_pushl(&cpr.args, "--super-prefix", NULL);
-               argv_array_pushf(&cpr.args, "%s/", displaypath);
-               argv_array_pushl(&cpr.args, "submodule--helper", "foreach", "--recursive",
-                               NULL);
+               strvec_pushl(&cpr.args, "--super-prefix", NULL);
+               strvec_pushf(&cpr.args, "%s/", displaypath);
+               strvec_pushl(&cpr.args, "submodule--helper", "foreach", "--recursive",
+                            NULL);
 
                if (info->quiet)
-                       argv_array_push(&cpr.args, "--quiet");
+                       strvec_push(&cpr.args, "--quiet");
 
-               argv_array_push(&cpr.args, "--");
-               argv_array_pushv(&cpr.args, info->argv);
+               strvec_push(&cpr.args, "--");
+               strvec_pushv(&cpr.args, info->argv);
 
                if (run_command(&cpr))
                        die(_("run_command returned non-zero status while "
@@ -779,7 +779,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
                             unsigned int flags)
 {
        char *displaypath;
-       struct argv_array diff_files_args = ARGV_ARRAY_INIT;
+       struct strvec diff_files_args = STRVEC_INIT;
        struct rev_info rev;
        int diff_files_result;
        struct strbuf buf = STRBUF_INIT;
@@ -809,17 +809,17 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
        }
        strbuf_release(&buf);
 
-       argv_array_pushl(&diff_files_args, "diff-files",
-                        "--ignore-submodules=dirty", "--quiet", "--",
-                        path, NULL);
+       strvec_pushl(&diff_files_args, "diff-files",
+                    "--ignore-submodules=dirty", "--quiet", "--",
+                    path, NULL);
 
        git_config(git_diff_basic_config, NULL);
 
        repo_init_revisions(the_repository, &rev, NULL);
        rev.abbrev = 0;
-       diff_files_args.argc = setup_revisions(diff_files_args.argc,
-                                              diff_files_args.argv,
-                                              &rev, NULL);
+       diff_files_args.nr = setup_revisions(diff_files_args.nr,
+                                            diff_files_args.v,
+                                            &rev, NULL);
        diff_files_result = run_diff_files(&rev, 0);
 
        if (!diff_result_code(&rev.diffopt, diff_files_result)) {
@@ -849,23 +849,23 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
                cpr.dir = path;
                prepare_submodule_repo_env(&cpr.env_array);
 
-               argv_array_push(&cpr.args, "--super-prefix");
-               argv_array_pushf(&cpr.args, "%s/", displaypath);
-               argv_array_pushl(&cpr.args, "submodule--helper", "status",
-                                "--recursive", NULL);
+               strvec_push(&cpr.args, "--super-prefix");
+               strvec_pushf(&cpr.args, "%s/", displaypath);
+               strvec_pushl(&cpr.args, "submodule--helper", "status",
+                            "--recursive", NULL);
 
                if (flags & OPT_CACHED)
-                       argv_array_push(&cpr.args, "--cached");
+                       strvec_push(&cpr.args, "--cached");
 
                if (flags & OPT_QUIET)
-                       argv_array_push(&cpr.args, "--quiet");
+                       strvec_push(&cpr.args, "--quiet");
 
                if (run_command(&cpr))
                        die(_("failed to recurse into submodule '%s'"), path);
        }
 
 cleanup:
-       argv_array_clear(&diff_files_args);
+       strvec_clear(&diff_files_args);
        free(displaypath);
 }
 
@@ -995,8 +995,8 @@ static void sync_submodule(const char *path, const char *prefix,
        prepare_submodule_repo_env(&cp.env_array);
        cp.git_cmd = 1;
        cp.dir = path;
-       argv_array_pushl(&cp.args, "submodule--helper",
-                        "print-default-remote", NULL);
+       strvec_pushl(&cp.args, "submodule--helper",
+                    "print-default-remote", NULL);
 
        strbuf_reset(&sb);
        if (capture_command(&cp, &sb, 0))
@@ -1021,13 +1021,13 @@ static void sync_submodule(const char *path, const char *prefix,
                cpr.dir = path;
                prepare_submodule_repo_env(&cpr.env_array);
 
-               argv_array_push(&cpr.args, "--super-prefix");
-               argv_array_pushf(&cpr.args, "%s/", displaypath);
-               argv_array_pushl(&cpr.args, "submodule--helper", "sync",
-                                "--recursive", NULL);
+               strvec_push(&cpr.args, "--super-prefix");
+               strvec_pushf(&cpr.args, "%s/", displaypath);
+               strvec_pushl(&cpr.args, "submodule--helper", "sync",
+                            "--recursive", NULL);
 
                if (flags & OPT_QUIET)
-                       argv_array_push(&cpr.args, "--quiet");
+                       strvec_push(&cpr.args, "--quiet");
 
                if (run_command(&cpr))
                        die(_("failed to recurse into submodule '%s'"),
@@ -1127,8 +1127,8 @@ static void deinit_submodule(const char *path, const char *prefix,
                if (!(flags & OPT_FORCE)) {
                        struct child_process cp_rm = CHILD_PROCESS_INIT;
                        cp_rm.git_cmd = 1;
-                       argv_array_pushl(&cp_rm.args, "rm", "-qn",
-                                        path, NULL);
+                       strvec_pushl(&cp_rm.args, "rm", "-qn",
+                                    path, NULL);
 
                        if (run_command(&cp_rm))
                                die(_("Submodule work tree '%s' contains local "
@@ -1156,8 +1156,8 @@ static void deinit_submodule(const char *path, const char *prefix,
                      displaypath);
 
        cp_config.git_cmd = 1;
-       argv_array_pushl(&cp_config.args, "config", "--get-regexp", NULL);
-       argv_array_pushf(&cp_config.args, "submodule.%s\\.", sub->name);
+       strvec_pushl(&cp_config.args, "config", "--get-regexp", NULL);
+       strvec_pushf(&cp_config.args, "submodule.%s\\.", sub->name);
 
        /* remove the .git/config entries (unless the user already did it) */
        if (!capture_command(&cp_config, &sb_config, 0) && sb_config.len) {
@@ -1239,32 +1239,32 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url
 {
        struct child_process cp = CHILD_PROCESS_INIT;
 
-       argv_array_push(&cp.args, "clone");
-       argv_array_push(&cp.args, "--no-checkout");
+       strvec_push(&cp.args, "clone");
+       strvec_push(&cp.args, "--no-checkout");
        if (quiet)
-               argv_array_push(&cp.args, "--quiet");
+               strvec_push(&cp.args, "--quiet");
        if (progress)
-               argv_array_push(&cp.args, "--progress");
+               strvec_push(&cp.args, "--progress");
        if (depth && *depth)
-               argv_array_pushl(&cp.args, "--depth", depth, NULL);
+               strvec_pushl(&cp.args, "--depth", depth, NULL);
        if (reference->nr) {
                struct string_list_item *item;
                for_each_string_list_item(item, reference)
-                       argv_array_pushl(&cp.args, "--reference",
-                                        item->string, NULL);
+                       strvec_pushl(&cp.args, "--reference",
+                                    item->string, NULL);
        }
        if (dissociate)
-               argv_array_push(&cp.args, "--dissociate");
+               strvec_push(&cp.args, "--dissociate");
        if (gitdir && *gitdir)
-               argv_array_pushl(&cp.args, "--separate-git-dir", gitdir, NULL);
+               strvec_pushl(&cp.args, "--separate-git-dir", gitdir, NULL);
        if (single_branch >= 0)
-               argv_array_push(&cp.args, single_branch ?
+               strvec_push(&cp.args, single_branch ?
                                          "--single-branch" :
                                          "--no-single-branch");
 
-       argv_array_push(&cp.args, "--");
-       argv_array_push(&cp.args, url);
-       argv_array_push(&cp.args, path);
+       strvec_push(&cp.args, "--");
+       strvec_push(&cp.args, url);
+       strvec_push(&cp.args, path);
 
        cp.git_cmd = 1;
        prepare_submodule_repo_env(&cp.env_array);
@@ -1511,7 +1511,7 @@ static void determine_submodule_update_strategy(struct repository *r,
                if (parse_submodule_update_strategy(update, out) < 0)
                        die(_("Invalid update mode '%s' for submodule path '%s'"),
                                update, path);
-       } else if (!repo_config_get_string_const(r, key, &val)) {
+       } else if (!repo_config_get_string_tmp(r, key, &val)) {
                if (parse_submodule_update_strategy(val, out) < 0)
                        die(_("Invalid update mode '%s' configured for submodule path '%s'"),
                                val, path);
@@ -1667,7 +1667,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
        }
 
        key = xstrfmt("submodule.%s.update", sub->name);
-       if (!repo_config_get_string_const(the_repository, key, &update_string)) {
+       if (!repo_config_get_string_tmp(the_repository, key, &update_string)) {
                update_type = parse_submodule_update_type(update_string);
        } else {
                update_type = sub->update_strategy.type;
@@ -1690,7 +1690,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
 
        strbuf_reset(&sb);
        strbuf_addf(&sb, "submodule.%s.url", sub->name);
-       if (repo_config_get_string_const(the_repository, sb.buf, &url)) {
+       if (repo_config_get_string_tmp(the_repository, sb.buf, &url)) {
                if (starts_with_dot_slash(sub->url) ||
                    starts_with_dot_dot_slash(sub->url)) {
                        url = compute_submodule_clone_url(sub->url);
@@ -1717,38 +1717,38 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
        child->no_stdin = 1;
        child->stdout_to_stderr = 1;
        child->err = -1;
-       argv_array_push(&child->args, "submodule--helper");
-       argv_array_push(&child->args, "clone");
+       strvec_push(&child->args, "submodule--helper");
+       strvec_push(&child->args, "clone");
        if (suc->progress)
-               argv_array_push(&child->args, "--progress");
+               strvec_push(&child->args, "--progress");
        if (suc->quiet)
-               argv_array_push(&child->args, "--quiet");
+               strvec_push(&child->args, "--quiet");
        if (suc->prefix)
-               argv_array_pushl(&child->args, "--prefix", suc->prefix, NULL);
+               strvec_pushl(&child->args, "--prefix", suc->prefix, NULL);
        if (suc->recommend_shallow && sub->recommend_shallow == 1)
-               argv_array_push(&child->args, "--depth=1");
+               strvec_push(&child->args, "--depth=1");
        if (suc->require_init)
-               argv_array_push(&child->args, "--require-init");
-       argv_array_pushl(&child->args, "--path", sub->path, NULL);
-       argv_array_pushl(&child->args, "--name", sub->name, NULL);
-       argv_array_pushl(&child->args, "--url", url, NULL);
+               strvec_push(&child->args, "--require-init");
+       strvec_pushl(&child->args, "--path", sub->path, NULL);
+       strvec_pushl(&child->args, "--name", sub->name, NULL);
+       strvec_pushl(&child->args, "--url", url, NULL);
        if (suc->references.nr) {
                struct string_list_item *item;
                for_each_string_list_item(item, &suc->references)
-                       argv_array_pushl(&child->args, "--reference", item->string, NULL);
+                       strvec_pushl(&child->args, "--reference", item->string, NULL);
        }
        if (suc->dissociate)
-               argv_array_push(&child->args, "--dissociate");
+               strvec_push(&child->args, "--dissociate");
        if (suc->depth)
-               argv_array_push(&child->args, suc->depth);
+               strvec_push(&child->args, suc->depth);
        if (suc->single_branch >= 0)
-               argv_array_push(&child->args, suc->single_branch ?
+               strvec_push(&child->args, suc->single_branch ?
                                              "--single-branch" :
                                              "--no-single-branch");
 
 cleanup:
-       strbuf_reset(&displaypath_sb);
-       strbuf_reset(&sb);
+       strbuf_release(&displaypath_sb);
+       strbuf_release(&sb);
        if (need_free_url)
                free((void*)url);
 
@@ -1976,7 +1976,7 @@ static const char *remote_submodule_branch(const char *path)
                return NULL;
 
        key = xstrfmt("submodule.%s.branch", sub->name);
-       if (repo_config_get_string_const(the_repository, key, &branch))
+       if (repo_config_get_string_tmp(the_repository, key, &branch))
                branch = sub->branch;
        free(key);
 
@@ -2101,7 +2101,7 @@ static int ensure_core_worktree(int argc, const char **argv, const char *prefix)
 {
        const struct submodule *sub;
        const char *path;
-       char *cw;
+       const char *cw;
        struct repository subrepo;
 
        if (argc != 2)
@@ -2116,7 +2116,7 @@ static int ensure_core_worktree(int argc, const char **argv, const char *prefix)
        if (repo_submodule_init(&subrepo, the_repository, sub))
                die(_("could not get a repository handle for submodule '%s'"), path);
 
-       if (!repo_config_get_string(&subrepo, "core.worktree", &cw)) {
+       if (!repo_config_get_string_tmp(&subrepo, "core.worktree", &cw)) {
                char *cfg_file, *abs_path;
                const char *rel_path;
                struct strbuf sb = STRBUF_INIT;
index b74dd9a69d992bcbac678f5b463a5e00b5299140..8a2df4459c66389d0fc24fed93dc4e0c1f87efe1 100644 (file)
@@ -4,7 +4,7 @@
 #include "builtin.h"
 #include "parse-options.h"
 #include "quote.h"
-#include "argv-array.h"
+#include "strvec.h"
 
 static const char * const git_update_ref_usage[] = {
        N_("git update-ref [<options>] -d <refname> [<old-val>]"),
index 018879737aeedc245a1473247df16ed0dcd26e50..24654b4c9bf0664e4a2f41b42d3224062199ca81 100644 (file)
@@ -7,7 +7,7 @@
 #include "pkt-line.h"
 #include "sideband.h"
 #include "run-command.h"
-#include "argv-array.h"
+#include "strvec.h"
 
 static const char upload_archive_usage[] =
        "git upload-archive <repo>";
@@ -19,7 +19,7 @@ static const char deadchild[] =
 
 int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix)
 {
-       struct argv_array sent_argv = ARGV_ARRAY_INIT;
+       struct strvec sent_argv = STRVEC_INIT;
        const char *arg_cmd = "argument ";
 
        if (argc != 2 || !strcmp(argv[1], "-h"))
@@ -31,21 +31,21 @@ int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix)
        init_archivers();
 
        /* put received options in sent_argv[] */
-       argv_array_push(&sent_argv, "git-upload-archive");
+       strvec_push(&sent_argv, "git-upload-archive");
        for (;;) {
                char *buf = packet_read_line(0, NULL);
                if (!buf)
                        break;  /* got a flush */
-               if (sent_argv.argc > MAX_ARGS)
+               if (sent_argv.nr > MAX_ARGS)
                        die("Too many options (>%d)", MAX_ARGS - 1);
 
                if (!starts_with(buf, arg_cmd))
                        die("'argument' token or flush expected");
-               argv_array_push(&sent_argv, buf + strlen(arg_cmd));
+               strvec_push(&sent_argv, buf + strlen(arg_cmd));
        }
 
        /* parse all options sent by the client */
-       return write_archive(sent_argv.argc, sent_argv.argv, prefix,
+       return write_archive(sent_argv.nr, sent_argv.v, prefix,
                             the_repository, NULL, 1);
 }
 
index c2a1a5c5048412abaa545862dbd0f3dd93338dc5..05c52135946b77ba6014f69b203d3e979df94ffd 100644 (file)
@@ -7,21 +7,26 @@
 #define VERIFY_PACK_VERBOSE 01
 #define VERIFY_PACK_STAT_ONLY 02
 
-static int verify_one_pack(const char *path, unsigned int flags)
+static int verify_one_pack(const char *path, unsigned int flags, const char *hash_algo)
 {
        struct child_process index_pack = CHILD_PROCESS_INIT;
-       const char *argv[] = {"index-pack", NULL, NULL, NULL };
+       struct strvec *argv = &index_pack.args;
        struct strbuf arg = STRBUF_INIT;
        int verbose = flags & VERIFY_PACK_VERBOSE;
        int stat_only = flags & VERIFY_PACK_STAT_ONLY;
        int err;
 
+       strvec_push(argv, "index-pack");
+
        if (stat_only)
-               argv[1] = "--verify-stat-only";
+               strvec_push(argv, "--verify-stat-only");
        else if (verbose)
-               argv[1] = "--verify-stat";
+               strvec_push(argv, "--verify-stat");
        else
-               argv[1] = "--verify";
+               strvec_push(argv, "--verify");
+
+       if (hash_algo)
+               strvec_pushf(argv, "--object-format=%s", hash_algo);
 
        /*
         * In addition to "foo.pack" we accept "foo.idx" and "foo";
@@ -31,9 +36,8 @@ static int verify_one_pack(const char *path, unsigned int flags)
        if (strbuf_strip_suffix(&arg, ".idx") ||
            !ends_with(arg.buf, ".pack"))
                strbuf_addstr(&arg, ".pack");
-       argv[2] = arg.buf;
+       strvec_push(argv, arg.buf);
 
-       index_pack.argv = argv;
        index_pack.git_cmd = 1;
 
        err = run_command(&index_pack);
@@ -60,12 +64,15 @@ int cmd_verify_pack(int argc, const char **argv, const char *prefix)
 {
        int err = 0;
        unsigned int flags = 0;
+       const char *object_format = NULL;
        int i;
        const struct option verify_pack_options[] = {
                OPT_BIT('v', "verbose", &flags, N_("verbose"),
                        VERIFY_PACK_VERBOSE),
                OPT_BIT('s', "stat-only", &flags, N_("show statistics only"),
                        VERIFY_PACK_STAT_ONLY),
+               OPT_STRING(0, "object-format", &object_format, N_("hash"),
+                          N_("specify the hash algorithm to use")),
                OPT_END()
        };
 
@@ -75,7 +82,7 @@ int cmd_verify_pack(int argc, const char **argv, const char *prefix)
        if (argc < 1)
                usage_with_options(verify_pack_usage, verify_pack_options);
        for (i = 0; i < argc; i++) {
-               if (verify_one_pack(argv[i], flags))
+               if (verify_one_pack(argv[i], flags, object_format))
                        err = 1;
        }
 
index f0cbdef718215d1ff71a2a71204c10d296a9b2c8..378f332b5d07edb55b48559ba328f980b84927e6 100644 (file)
@@ -4,7 +4,7 @@
 #include "builtin.h"
 #include "dir.h"
 #include "parse-options.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "branch.h"
 #include "refs.h"
 #include "run-command.h"
@@ -316,7 +316,7 @@ static int add_worktree(const char *path, const char *refname,
        struct strbuf sb = STRBUF_INIT, realpath = STRBUF_INIT;
        const char *name;
        struct child_process cp = CHILD_PROCESS_INIT;
-       struct argv_array child_env = ARGV_ARRAY_INIT;
+       struct strvec child_env = STRVEC_INIT;
        unsigned int counter = 0;
        int len, ret;
        struct strbuf symref = STRBUF_INIT;
@@ -408,32 +408,32 @@ static int add_worktree(const char *path, const char *refname,
        strbuf_addf(&sb, "%s/commondir", sb_repo.buf);
        write_file(sb.buf, "../..");
 
-       argv_array_pushf(&child_env, "%s=%s", GIT_DIR_ENVIRONMENT, sb_git.buf);
-       argv_array_pushf(&child_env, "%s=%s", GIT_WORK_TREE_ENVIRONMENT, path);
+       strvec_pushf(&child_env, "%s=%s", GIT_DIR_ENVIRONMENT, sb_git.buf);
+       strvec_pushf(&child_env, "%s=%s", GIT_WORK_TREE_ENVIRONMENT, path);
        cp.git_cmd = 1;
 
        if (!is_branch)
-               argv_array_pushl(&cp.args, "update-ref", "HEAD",
-                                oid_to_hex(&commit->object.oid), NULL);
+               strvec_pushl(&cp.args, "update-ref", "HEAD",
+                            oid_to_hex(&commit->object.oid), NULL);
        else {
-               argv_array_pushl(&cp.args, "symbolic-ref", "HEAD",
-                                symref.buf, NULL);
+               strvec_pushl(&cp.args, "symbolic-ref", "HEAD",
+                            symref.buf, NULL);
                if (opts->quiet)
-                       argv_array_push(&cp.args, "--quiet");
+                       strvec_push(&cp.args, "--quiet");
        }
 
-       cp.env = child_env.argv;
+       cp.env = child_env.v;
        ret = run_command(&cp);
        if (ret)
                goto done;
 
        if (opts->checkout) {
                cp.argv = NULL;
-               argv_array_clear(&cp.args);
-               argv_array_pushl(&cp.args, "reset", "--hard", "--no-recurse-submodules", NULL);
+               strvec_clear(&cp.args);
+               strvec_pushl(&cp.args, "reset", "--hard", "--no-recurse-submodules", NULL);
                if (opts->quiet)
-                       argv_array_push(&cp.args, "--quiet");
-               cp.env = child_env.argv;
+                       strvec_push(&cp.args, "--quiet");
+               cp.env = child_env.v;
                ret = run_command(&cp);
                if (ret)
                        goto done;
@@ -465,15 +465,15 @@ done:
                        cp.env = env;
                        cp.argv = NULL;
                        cp.trace2_hook_name = "post-checkout";
-                       argv_array_pushl(&cp.args, absolute_path(hook),
-                                        oid_to_hex(&null_oid),
-                                        oid_to_hex(&commit->object.oid),
-                                        "1", NULL);
+                       strvec_pushl(&cp.args, absolute_path(hook),
+                                    oid_to_hex(&null_oid),
+                                    oid_to_hex(&commit->object.oid),
+                                    "1", NULL);
                        ret = run_command(&cp);
                }
        }
 
-       argv_array_clear(&child_env);
+       strvec_clear(&child_env);
        strbuf_release(&sb);
        strbuf_release(&symref);
        strbuf_release(&sb_repo);
@@ -619,15 +619,15 @@ static int add(int ac, const char **av, const char *prefix)
        if (new_branch) {
                struct child_process cp = CHILD_PROCESS_INIT;
                cp.git_cmd = 1;
-               argv_array_push(&cp.args, "branch");
+               strvec_push(&cp.args, "branch");
                if (new_branch_force)
-                       argv_array_push(&cp.args, "--force");
+                       strvec_push(&cp.args, "--force");
                if (opts.quiet)
-                       argv_array_push(&cp.args, "--quiet");
-               argv_array_push(&cp.args, new_branch);
-               argv_array_push(&cp.args, branch);
+                       strvec_push(&cp.args, "--quiet");
+               strvec_push(&cp.args, new_branch);
+               strvec_push(&cp.args, branch);
                if (opt_track)
-                       argv_array_push(&cp.args, opt_track);
+                       strvec_push(&cp.args, opt_track);
                if (run_command(&cp))
                        return -1;
                branch = new_branch;
@@ -924,7 +924,7 @@ static int move_worktree(int ac, const char **av, const char *prefix)
 static void check_clean_worktree(struct worktree *wt,
                                 const char *original_path)
 {
-       struct argv_array child_env = ARGV_ARRAY_INIT;
+       struct strvec child_env = STRVEC_INIT;
        struct child_process cp;
        char buf[1];
        int ret;
@@ -935,15 +935,15 @@ static void check_clean_worktree(struct worktree *wt,
         */
        validate_no_submodules(wt);
 
-       argv_array_pushf(&child_env, "%s=%s/.git",
-                        GIT_DIR_ENVIRONMENT, wt->path);
-       argv_array_pushf(&child_env, "%s=%s",
-                        GIT_WORK_TREE_ENVIRONMENT, wt->path);
+       strvec_pushf(&child_env, "%s=%s/.git",
+                    GIT_DIR_ENVIRONMENT, wt->path);
+       strvec_pushf(&child_env, "%s=%s",
+                    GIT_WORK_TREE_ENVIRONMENT, wt->path);
        memset(&cp, 0, sizeof(cp));
-       argv_array_pushl(&cp.args, "status",
-                        "--porcelain", "--ignore-submodules=none",
-                        NULL);
-       cp.env = child_env.argv;
+       strvec_pushl(&cp.args, "status",
+                    "--porcelain", "--ignore-submodules=none",
+                    NULL);
+       cp.env = child_env.v;
        cp.git_cmd = 1;
        cp.dir = wt->path;
        cp.out = -1;
index 2a0d744d3fa51b2bbbb307a04f7e32a45b1b690d..995a940dfd65864bb88251d486f37d67ddae728e 100644 (file)
--- a/bundle.c
+++ b/bundle.c
 #include "list-objects.h"
 #include "run-command.h"
 #include "refs.h"
-#include "argv-array.h"
+#include "strvec.h"
 
-static const char bundle_signature[] = "# v2 git bundle\n";
+
+static const char v2_bundle_signature[] = "# v2 git bundle\n";
+static const char v3_bundle_signature[] = "# v3 git bundle\n";
+static struct {
+       int version;
+       const char *signature;
+} bundle_sigs[] = {
+       { 2, v2_bundle_signature },
+       { 3, v3_bundle_signature },
+};
 
 static void add_to_ref_list(const struct object_id *oid, const char *name,
                struct ref_list *list)
@@ -23,15 +32,30 @@ static void add_to_ref_list(const struct object_id *oid, const char *name,
        list->nr++;
 }
 
-static const struct git_hash_algo *detect_hash_algo(struct strbuf *buf)
+static int parse_capability(struct bundle_header *header, const char *capability)
+{
+       const char *arg;
+       if (skip_prefix(capability, "object-format=", &arg)) {
+               int algo = hash_algo_by_name(arg);
+               if (algo == GIT_HASH_UNKNOWN)
+                       return error(_("unrecognized bundle hash algorithm: %s"), arg);
+               header->hash_algo = &hash_algos[algo];
+               return 0;
+       }
+       return error(_("unknown capability '%s'"), capability);
+}
+
+static int parse_bundle_signature(struct bundle_header *header, const char *line)
 {
-       size_t len = strcspn(buf->buf, " \n");
-       int algo;
+       int i;
 
-       algo = hash_algo_by_length(len / 2);
-       if (algo == GIT_HASH_UNKNOWN)
-               return NULL;
-       return &hash_algos[algo];
+       for (i = 0; i < ARRAY_SIZE(bundle_sigs); i++) {
+               if (!strcmp(line, bundle_sigs[i].signature)) {
+                       header->version = bundle_sigs[i].version;
+                       return 0;
+               }
+       }
+       return -1;
 }
 
 static int parse_bundle_header(int fd, struct bundle_header *header,
@@ -42,14 +66,16 @@ static int parse_bundle_header(int fd, struct bundle_header *header,
 
        /* The bundle header begins with the signature */
        if (strbuf_getwholeline_fd(&buf, fd, '\n') ||
-           strcmp(buf.buf, bundle_signature)) {
+           parse_bundle_signature(header, buf.buf)) {
                if (report_path)
-                       error(_("'%s' does not look like a v2 bundle file"),
+                       error(_("'%s' does not look like a v2 or v3 bundle file"),
                              report_path);
                status = -1;
                goto abort;
        }
 
+       header->hash_algo = the_hash_algo;
+
        /* The bundle header ends with an empty line */
        while (!strbuf_getwholeline_fd(&buf, fd, '\n') &&
               buf.len && buf.buf[0] != '\n') {
@@ -57,19 +83,19 @@ static int parse_bundle_header(int fd, struct bundle_header *header,
                int is_prereq = 0;
                const char *p;
 
-               if (*buf.buf == '-') {
-                       is_prereq = 1;
-                       strbuf_remove(&buf, 0, 1);
-               }
                strbuf_rtrim(&buf);
 
-               if (!header->hash_algo) {
-                       header->hash_algo = detect_hash_algo(&buf);
-                       if (!header->hash_algo) {
-                               error(_("unknown hash algorithm length"));
+               if (header->version == 3 && *buf.buf == '@') {
+                       if (parse_capability(header, buf.buf + 1)) {
                                status = -1;
                                break;
                        }
+                       continue;
+               }
+
+               if (*buf.buf == '-') {
+                       is_prereq = 1;
+                       strbuf_remove(&buf, 0, 1);
                }
 
                /*
@@ -269,16 +295,16 @@ out:
 
 
 /* Write the pack data to bundle_fd */
-static int write_pack_data(int bundle_fd, struct rev_info *revs, struct argv_array *pack_options)
+static int write_pack_data(int bundle_fd, struct rev_info *revs, struct strvec *pack_options)
 {
        struct child_process pack_objects = CHILD_PROCESS_INIT;
        int i;
 
-       argv_array_pushl(&pack_objects.args,
-                        "pack-objects",
-                        "--stdout", "--thin", "--delta-base-offset",
-                        NULL);
-       argv_array_pushv(&pack_objects.args, pack_options->argv);
+       strvec_pushl(&pack_objects.args,
+                    "pack-objects",
+                    "--stdout", "--thin", "--delta-base-offset",
+                    NULL);
+       strvec_pushv(&pack_objects.args, pack_options->v);
        pack_objects.in = -1;
        pack_objects.out = bundle_fd;
        pack_objects.git_cmd = 1;
@@ -321,11 +347,11 @@ static int compute_and_write_prerequisites(int bundle_fd,
        FILE *rls_fout;
        int i;
 
-       argv_array_pushl(&rls.args,
-                        "rev-list", "--boundary", "--pretty=oneline",
-                        NULL);
+       strvec_pushl(&rls.args,
+                    "rev-list", "--boundary", "--pretty=oneline",
+                    NULL);
        for (i = 1; i < argc; i++)
-               argv_array_push(&rls.args, argv[i]);
+               strvec_push(&rls.args, argv[i]);
        rls.out = -1;
        rls.git_cmd = 1;
        if (start_command(&rls))
@@ -449,13 +475,14 @@ static int write_bundle_refs(int bundle_fd, struct rev_info *revs)
 }
 
 int create_bundle(struct repository *r, const char *path,
-                 int argc, const char **argv, struct argv_array *pack_options)
+                 int argc, const char **argv, struct strvec *pack_options, int version)
 {
        struct lock_file lock = LOCK_INIT;
        int bundle_fd = -1;
        int bundle_to_stdout;
        int ref_count = 0;
        struct rev_info revs;
+       int min_version = the_hash_algo == &hash_algos[GIT_HASH_SHA1] ? 2 : 3;
 
        bundle_to_stdout = !strcmp(path, "-");
        if (bundle_to_stdout)
@@ -464,8 +491,22 @@ int create_bundle(struct repository *r, const char *path,
                bundle_fd = hold_lock_file_for_update(&lock, path,
                                                      LOCK_DIE_ON_ERROR);
 
-       /* write signature */
-       write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature));
+       if (version == -1)
+               version = min_version;
+
+       if (version < 2 || version > 3) {
+               die(_("unsupported bundle version %d"), version);
+       } else if (version < min_version) {
+               die(_("cannot write bundle version %d with algorithm %s"), version, the_hash_algo->name);
+       } else if (version == 2) {
+               write_or_die(bundle_fd, v2_bundle_signature, strlen(v2_bundle_signature));
+       } else {
+               const char *capability = "@object-format=";
+               write_or_die(bundle_fd, v3_bundle_signature, strlen(v3_bundle_signature));
+               write_or_die(bundle_fd, capability, strlen(capability));
+               write_or_die(bundle_fd, the_hash_algo->name, strlen(the_hash_algo->name));
+               write_or_die(bundle_fd, "\n", 1);
+       }
 
        /* init revs to list objects for pack-objects later */
        save_commit_buffer = 0;
index 2dc9442024fa27f775e25bbfa9dc8ba04ca1967c..f9e2d1c8ef544d39e440656aa59d21c62e919777 100644 (file)
--- a/bundle.h
+++ b/bundle.h
@@ -1,7 +1,7 @@
 #ifndef BUNDLE_H
 #define BUNDLE_H
 
-#include "argv-array.h"
+#include "strvec.h"
 #include "cache.h"
 
 struct ref_list {
@@ -13,6 +13,7 @@ struct ref_list {
 };
 
 struct bundle_header {
+       unsigned version;
        struct ref_list prerequisites;
        struct ref_list references;
        const struct git_hash_algo *hash_algo;
@@ -21,7 +22,8 @@ struct bundle_header {
 int is_bundle(const char *path, int quiet);
 int read_bundle_header(const char *path, struct bundle_header *header);
 int create_bundle(struct repository *r, const char *path,
-                 int argc, const char **argv, struct argv_array *pack_options);
+                 int argc, const char **argv, struct strvec *pack_options,
+                 int version);
 int verify_bundle(struct repository *r, struct bundle_header *header, int verbose);
 #define BUNDLE_VERBOSE 1
 int unbundle(struct repository *r, struct bundle_header *header,
diff --git a/cache.h b/cache.h
index 654426460cc06ca093fad53ea3b72622d2b7bfd0..4cad61ffa4eecf4e793971a4009d199f7c2f3a50 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -921,8 +921,8 @@ extern int assume_unchanged;
 extern int prefer_symlink_refs;
 extern int warn_ambiguous_refs;
 extern int warn_on_object_refname_ambiguity;
-extern const char *apply_default_whitespace;
-extern const char *apply_default_ignorewhitespace;
+extern char *apply_default_whitespace;
+extern char *apply_default_ignorewhitespace;
 extern const char *git_attributes_file;
 extern const char *git_hooks_path;
 extern int zlib_compression_level;
@@ -1044,6 +1044,7 @@ struct repository_format {
        int hash_algo;
        char *work_tree;
        struct string_list unknown_extensions;
+       struct string_list v1_only_extensions;
 };
 
 /*
@@ -1057,6 +1058,7 @@ struct repository_format {
        .is_bare = -1, \
        .hash_algo = GIT_HASH_SHA1, \
        .unknown_extensions = STRING_LIST_INIT_DUP, \
+       .v1_only_extensions = STRING_LIST_INIT_DUP, \
 }
 
 /*
index c72e9f9773e173c0dbcb5de88bde54d5434cf808..6586e30ca5a64fe61ec982f3d5dbe188d9194258 100644 (file)
@@ -47,7 +47,7 @@ const char *unique_tracking_name(const char *name, struct object_id *oid,
 {
        struct tracking_name_data cb_data = TRACKING_NAME_DATA_INIT;
        const char *default_remote = NULL;
-       if (!git_config_get_string_const("checkout.defaultremote", &default_remote))
+       if (!git_config_get_string_tmp("checkout.defaultremote", &default_remote))
                cb_data.default_remote = default_remote;
        cb_data.src_ref = xstrfmt("refs/heads/%s", name);
        cb_data.dst_oid = oid;
@@ -55,7 +55,6 @@ const char *unique_tracking_name(const char *name, struct object_id *oid,
        if (dwim_remotes_matched)
                *dwim_remotes_matched = cb_data.num_matches;
        free(cb_data.src_ref);
-       free((char *)default_remote);
        if (cb_data.num_matches == 1) {
                free(cb_data.default_dst_ref);
                free(cb_data.default_dst_oid);
index ff24c547c8bb56a244eb5b1b3ca11e4bd32ea31a..3eefec500d88336fdb2d1fc3f4e05a611fc7e009 100755 (executable)
--- a/ci/lib.sh
+++ b/ci/lib.sh
@@ -184,9 +184,9 @@ linux-clang|linux-gcc)
        if [ "$jobname" = linux-gcc ]
        then
                export CC=gcc-8
-               MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=$(which python3)"
+               MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/python3"
        else
-               MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=$(which python2)"
+               MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/python2"
        fi
 
        export GIT_TEST_HTTPD=true
index 17e25aade96f46ecfcdf1b5658d788f23b99f587..6c27b886b8f0cfb8d16a82318d884725a1ed607c 100755 (executable)
@@ -24,6 +24,12 @@ linux-gcc)
        export GIT_TEST_ADD_I_USE_BUILTIN=1
        make test
        ;;
+linux-clang)
+       export GIT_TEST_DEFAULT_HASH=sha1
+       make test
+       export GIT_TEST_DEFAULT_HASH=sha256
+       make test
+       ;;
 linux-gcc-4.8)
        # Don't run the tests; we only care about whether Git can be
        # built with GCC 4.8, as it errors out on some undesired (C99)
index 4a38eed3226043764922e327cfda0e79b6f79dbf..1261e18a72e9727e6d4e530e7068ffb319f59548 100644 (file)
--- a/column.c
+++ b/column.c
@@ -107,7 +107,7 @@ static void display_plain(const struct string_list *list,
                printf("%s%s%s", indent, list->items[i].string, nl);
 }
 
-/* Print a cell to stdout with all necessary leading/traling space */
+/* Print a cell to stdout with all necessary leading/trailing space */
 static int display_cell(struct column_data *data, int initial_width,
                        const char *empty_cell, int x, int y)
 {
@@ -358,7 +358,7 @@ static struct child_process column_process = CHILD_PROCESS_INIT;
 
 int run_column_filter(int colopts, const struct column_options *opts)
 {
-       struct argv_array *argv;
+       struct strvec *argv;
 
        if (fd_out != -1)
                return -1;
@@ -366,14 +366,14 @@ int run_column_filter(int colopts, const struct column_options *opts)
        child_process_init(&column_process);
        argv = &column_process.args;
 
-       argv_array_push(argv, "column");
-       argv_array_pushf(argv, "--raw-mode=%d", colopts);
+       strvec_push(argv, "column");
+       strvec_pushf(argv, "--raw-mode=%d", colopts);
        if (opts && opts->width)
-               argv_array_pushf(argv, "--width=%d", opts->width);
+               strvec_pushf(argv, "--width=%d", opts->width);
        if (opts && opts->indent)
-               argv_array_pushf(argv, "--indent=%s", opts->indent);
+               strvec_pushf(argv, "--indent=%s", opts->indent);
        if (opts && opts->padding)
-               argv_array_pushf(argv, "--padding=%d", opts->padding);
+               strvec_pushf(argv, "--padding=%d", opts->padding);
 
        fflush(stdout);
        column_process.in = -1;
index 89aa60cde7e0659e955fdcfb963a8859bf69a567..e5901f2213319e065bf6e92b8b559b9c8bd8bf7e 100644 (file)
@@ -195,6 +195,7 @@ git-write-tree                          plumbingmanipulators
 gitattributes                           guide
 gitcli                                  guide
 gitcore-tutorial                        guide
+gitcredentials                          guide
 gitcvs-migration                        guide
 gitdiffcore                             guide
 giteveryday                             guide
@@ -204,6 +205,7 @@ githooks                                guide
 gitignore                               guide
 gitmodules                              guide
 gitnamespaces                           guide
+gitremote-helpers                       guide
 gitrepository-layout                    guide
 gitrevisions                            guide
 gitsubmodules                           guide
index 1af68c297d2e267b45fc5a1e820b11936dff906f..0ed003e218fb9bb2c024fb913a2af4fca9441039 100644 (file)
@@ -1,7 +1,5 @@
-#include "cache.h"
-#include "config.h"
-#include "dir.h"
 #include "git-compat-util.h"
+#include "config.h"
 #include "lockfile.h"
 #include "pack.h"
 #include "packfile.h"
@@ -19,6 +17,8 @@
 #include "bloom.h"
 #include "commit-slab.h"
 #include "shallow.h"
+#include "json-writer.h"
+#include "trace2.h"
 
 void git_test_write_commit_graph_or_die(void)
 {
@@ -179,7 +179,14 @@ static char *get_chain_filename(struct object_directory *odb)
 
 static uint8_t oid_version(void)
 {
-       return 1;
+       switch (hash_algo_by_ptr(the_hash_algo)) {
+       case GIT_HASH_SHA1:
+               return 1;
+       case GIT_HASH_SHA256:
+               return 2;
+       default:
+               die(_("invalid hash version"));
+       }
 }
 
 static struct commit_graph *alloc_commit_graph(void)
@@ -285,8 +292,7 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
        const unsigned char *data, *chunk_lookup;
        uint32_t i;
        struct commit_graph *graph;
-       uint64_t last_chunk_offset;
-       uint32_t last_chunk_id;
+       uint64_t next_chunk_offset;
        uint32_t graph_signature;
        unsigned char graph_version, hash_version;
 
@@ -326,24 +332,26 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
        graph->data = graph_map;
        graph->data_len = graph_size;
 
-       last_chunk_id = 0;
-       last_chunk_offset = 8;
+       if (graph_size < GRAPH_HEADER_SIZE +
+                        (graph->num_chunks + 1) * GRAPH_CHUNKLOOKUP_WIDTH +
+                        GRAPH_FANOUT_SIZE + the_hash_algo->rawsz) {
+               error(_("commit-graph file is too small to hold %u chunks"),
+                     graph->num_chunks);
+               free(graph);
+               return NULL;
+       }
+
        chunk_lookup = data + 8;
+       next_chunk_offset = get_be64(chunk_lookup + 4);
        for (i = 0; i < graph->num_chunks; i++) {
                uint32_t chunk_id;
-               uint64_t chunk_offset;
+               uint64_t chunk_offset = next_chunk_offset;
                int chunk_repeated = 0;
 
-               if (data + graph_size - chunk_lookup <
-                   GRAPH_CHUNKLOOKUP_WIDTH) {
-                       error(_("commit-graph chunk lookup table entry missing; file may be incomplete"));
-                       goto free_and_return;
-               }
-
                chunk_id = get_be32(chunk_lookup + 0);
-               chunk_offset = get_be64(chunk_lookup + 4);
 
                chunk_lookup += GRAPH_CHUNKLOOKUP_WIDTH;
+               next_chunk_offset = get_be64(chunk_lookup + 4);
 
                if (chunk_offset > graph_size - the_hash_algo->rawsz) {
                        error(_("commit-graph improper chunk offset %08x%08x"), (uint32_t)(chunk_offset >> 32),
@@ -362,8 +370,11 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
                case GRAPH_CHUNKID_OIDLOOKUP:
                        if (graph->chunk_oid_lookup)
                                chunk_repeated = 1;
-                       else
+                       else {
                                graph->chunk_oid_lookup = data + chunk_offset;
+                               graph->num_commits = (next_chunk_offset - chunk_offset)
+                                                    / graph->hash_len;
+                       }
                        break;
 
                case GRAPH_CHUNKID_DATA:
@@ -417,15 +428,6 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
                        error(_("commit-graph chunk id %08x appears multiple times"), chunk_id);
                        goto free_and_return;
                }
-
-               if (last_chunk_id == GRAPH_CHUNKID_OIDLOOKUP)
-               {
-                       graph->num_commits = (chunk_offset - last_chunk_offset)
-                                            / graph->hash_len;
-               }
-
-               last_chunk_id = chunk_id;
-               last_chunk_offset = chunk_offset;
        }
 
        if (graph->chunk_bloom_indexes && graph->chunk_bloom_data) {
@@ -624,10 +626,6 @@ static int prepare_commit_graph(struct repository *r)
                return !!r->objects->commit_graph;
        r->objects->commit_graph_attempted = 1;
 
-       if (git_env_bool(GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD, 0))
-               die("dying as requested by the '%s' variable on commit-graph load!",
-                   GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD);
-
        prepare_repo_settings(r);
 
        if (!git_env_bool(GIT_TEST_COMMIT_GRAPH, 0) &&
@@ -856,6 +854,14 @@ static int parse_commit_in_graph_one(struct repository *r,
 
 int parse_commit_in_graph(struct repository *r, struct commit *item)
 {
+       static int checked_env = 0;
+
+       if (!checked_env &&
+           git_env_bool(GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE, 0))
+               die("dying as requested by the '%s' variable on commit-graph parse!",
+                   GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE);
+       checked_env = 1;
+
        if (!prepare_commit_graph(r))
                return 0;
        return parse_commit_in_graph_one(r, r->objects->commit_graph, item);
@@ -948,10 +954,11 @@ struct write_commit_graph_context {
 
        const struct split_commit_graph_opts *split_opts;
        size_t total_bloom_filter_data_size;
+       const struct bloom_filter_settings *bloom_settings;
 };
 
-static void write_graph_chunk_fanout(struct hashfile *f,
-                                    struct write_commit_graph_context *ctx)
+static int write_graph_chunk_fanout(struct hashfile *f,
+                                   struct write_commit_graph_context *ctx)
 {
        int i, count = 0;
        struct commit **list = ctx->commits.list;
@@ -972,17 +979,21 @@ static void write_graph_chunk_fanout(struct hashfile *f,
 
                hashwrite_be32(f, count);
        }
+
+       return 0;
 }
 
-static void write_graph_chunk_oids(struct hashfile *f, int hash_len,
-                                  struct write_commit_graph_context *ctx)
+static int write_graph_chunk_oids(struct hashfile *f,
+                                 struct write_commit_graph_context *ctx)
 {
        struct commit **list = ctx->commits.list;
        int count;
        for (count = 0; count < ctx->commits.nr; count++, list++) {
                display_progress(ctx->progress, ++ctx->progress_cnt);
-               hashwrite(f, (*list)->object.oid.hash, (int)hash_len);
+               hashwrite(f, (*list)->object.oid.hash, the_hash_algo->rawsz);
        }
+
+       return 0;
 }
 
 static const unsigned char *commit_to_sha1(size_t index, void *table)
@@ -991,8 +1002,8 @@ static const unsigned char *commit_to_sha1(size_t index, void *table)
        return commits[index]->object.oid.hash;
 }
 
-static void write_graph_chunk_data(struct hashfile *f, int hash_len,
-                                  struct write_commit_graph_context *ctx)
+static int write_graph_chunk_data(struct hashfile *f,
+                                 struct write_commit_graph_context *ctx)
 {
        struct commit **list = ctx->commits.list;
        struct commit **last = ctx->commits.list + ctx->commits.nr;
@@ -1009,7 +1020,7 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len,
                        die(_("unable to parse commit %s"),
                                oid_to_hex(&(*list)->object.oid));
                tree = get_commit_tree_oid(*list);
-               hashwrite(f, tree->hash, hash_len);
+               hashwrite(f, tree->hash, the_hash_algo->rawsz);
 
                parent = (*list)->parents;
 
@@ -1089,10 +1100,12 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len,
 
                list++;
        }
+
+       return 0;
 }
 
-static void write_graph_chunk_extra_edges(struct hashfile *f,
-                                         struct write_commit_graph_context *ctx)
+static int write_graph_chunk_extra_edges(struct hashfile *f,
+                                        struct write_commit_graph_context *ctx)
 {
        struct commit **list = ctx->commits.list;
        struct commit **last = ctx->commits.list + ctx->commits.nr;
@@ -1141,10 +1154,12 @@ static void write_graph_chunk_extra_edges(struct hashfile *f,
 
                list++;
        }
+
+       return 0;
 }
 
-static void write_graph_chunk_bloom_indexes(struct hashfile *f,
-                                           struct write_commit_graph_context *ctx)
+static int write_graph_chunk_bloom_indexes(struct hashfile *f,
+                                          struct write_commit_graph_context *ctx)
 {
        struct commit **list = ctx->commits.list;
        struct commit **last = ctx->commits.list + ctx->commits.nr;
@@ -1152,30 +1167,54 @@ static void write_graph_chunk_bloom_indexes(struct hashfile *f,
 
        while (list < last) {
                struct bloom_filter *filter = get_bloom_filter(ctx->r, *list, 0);
-               cur_pos += filter->len;
+               size_t len = filter ? filter->len : 0;
+               cur_pos += len;
                display_progress(ctx->progress, ++ctx->progress_cnt);
                hashwrite_be32(f, cur_pos);
                list++;
        }
+
+       return 0;
 }
 
-static void write_graph_chunk_bloom_data(struct hashfile *f,
-                                        struct write_commit_graph_context *ctx,
-                                        const struct bloom_filter_settings *settings)
+static void trace2_bloom_filter_settings(struct write_commit_graph_context *ctx)
+{
+       struct json_writer jw = JSON_WRITER_INIT;
+
+       jw_object_begin(&jw, 0);
+       jw_object_intmax(&jw, "hash_version", ctx->bloom_settings->hash_version);
+       jw_object_intmax(&jw, "num_hashes", ctx->bloom_settings->num_hashes);
+       jw_object_intmax(&jw, "bits_per_entry", ctx->bloom_settings->bits_per_entry);
+       jw_end(&jw);
+
+       trace2_data_json("bloom", ctx->r, "settings", &jw);
+
+       jw_release(&jw);
+}
+
+static int write_graph_chunk_bloom_data(struct hashfile *f,
+                                       struct write_commit_graph_context *ctx)
 {
        struct commit **list = ctx->commits.list;
        struct commit **last = ctx->commits.list + ctx->commits.nr;
 
-       hashwrite_be32(f, settings->hash_version);
-       hashwrite_be32(f, settings->num_hashes);
-       hashwrite_be32(f, settings->bits_per_entry);
+       trace2_bloom_filter_settings(ctx);
+
+       hashwrite_be32(f, ctx->bloom_settings->hash_version);
+       hashwrite_be32(f, ctx->bloom_settings->num_hashes);
+       hashwrite_be32(f, ctx->bloom_settings->bits_per_entry);
 
        while (list < last) {
                struct bloom_filter *filter = get_bloom_filter(ctx->r, *list, 0);
+               size_t len = filter ? filter->len : 0;
+
                display_progress(ctx->progress, ++ctx->progress_cnt);
-               hashwrite(f, filter->data, filter->len * sizeof(unsigned char));
+               if (len)
+                       hashwrite(f, filter->data, len * sizeof(unsigned char));
                list++;
        }
+
+       return 0;
 }
 
 static int oid_compare(const void *_a, const void *_b)
@@ -1586,19 +1625,36 @@ static int write_graph_chunk_base(struct hashfile *f,
        return 0;
 }
 
+typedef int (*chunk_write_fn)(struct hashfile *f,
+                             struct write_commit_graph_context *ctx);
+
+struct chunk_info {
+       uint32_t id;
+       uint64_t size;
+       chunk_write_fn write_fn;
+};
+
 static int write_commit_graph_file(struct write_commit_graph_context *ctx)
 {
        uint32_t i;
        int fd;
        struct hashfile *f;
        struct lock_file lk = LOCK_INIT;
-       uint32_t chunk_ids[MAX_NUM_CHUNKS + 1];
-       uint64_t chunk_offsets[MAX_NUM_CHUNKS + 1];
+       struct chunk_info chunks[MAX_NUM_CHUNKS + 1];
        const unsigned hashsz = the_hash_algo->rawsz;
        struct strbuf progress_title = STRBUF_INIT;
        int num_chunks = 3;
+       uint64_t chunk_offset;
        struct object_id file_hash;
-       const struct bloom_filter_settings bloom_settings = DEFAULT_BLOOM_FILTER_SETTINGS;
+       struct bloom_filter_settings bloom_settings = DEFAULT_BLOOM_FILTER_SETTINGS;
+
+       if (!ctx->bloom_settings) {
+               bloom_settings.bits_per_entry = git_env_ulong("GIT_TEST_BLOOM_SETTINGS_BITS_PER_ENTRY",
+                                                             bloom_settings.bits_per_entry);
+               bloom_settings.num_hashes = git_env_ulong("GIT_TEST_BLOOM_SETTINGS_NUM_HASHES",
+                                                         bloom_settings.num_hashes);
+               ctx->bloom_settings = &bloom_settings;
+       }
 
        if (ctx->split) {
                struct strbuf tmp_file = STRBUF_INIT;
@@ -1644,51 +1700,41 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
                f = hashfd(lk.tempfile->fd, lk.tempfile->filename.buf);
        }
 
-       chunk_ids[0] = GRAPH_CHUNKID_OIDFANOUT;
-       chunk_ids[1] = GRAPH_CHUNKID_OIDLOOKUP;
-       chunk_ids[2] = GRAPH_CHUNKID_DATA;
+       chunks[0].id = GRAPH_CHUNKID_OIDFANOUT;
+       chunks[0].size = GRAPH_FANOUT_SIZE;
+       chunks[0].write_fn = write_graph_chunk_fanout;
+       chunks[1].id = GRAPH_CHUNKID_OIDLOOKUP;
+       chunks[1].size = hashsz * ctx->commits.nr;
+       chunks[1].write_fn = write_graph_chunk_oids;
+       chunks[2].id = GRAPH_CHUNKID_DATA;
+       chunks[2].size = (hashsz + 16) * ctx->commits.nr;
+       chunks[2].write_fn = write_graph_chunk_data;
        if (ctx->num_extra_edges) {
-               chunk_ids[num_chunks] = GRAPH_CHUNKID_EXTRAEDGES;
+               chunks[num_chunks].id = GRAPH_CHUNKID_EXTRAEDGES;
+               chunks[num_chunks].size = 4 * ctx->num_extra_edges;
+               chunks[num_chunks].write_fn = write_graph_chunk_extra_edges;
                num_chunks++;
        }
        if (ctx->changed_paths) {
-               chunk_ids[num_chunks] = GRAPH_CHUNKID_BLOOMINDEXES;
+               chunks[num_chunks].id = GRAPH_CHUNKID_BLOOMINDEXES;
+               chunks[num_chunks].size = sizeof(uint32_t) * ctx->commits.nr;
+               chunks[num_chunks].write_fn = write_graph_chunk_bloom_indexes;
                num_chunks++;
-               chunk_ids[num_chunks] = GRAPH_CHUNKID_BLOOMDATA;
+               chunks[num_chunks].id = GRAPH_CHUNKID_BLOOMDATA;
+               chunks[num_chunks].size = sizeof(uint32_t) * 3
+                                         + ctx->total_bloom_filter_data_size;
+               chunks[num_chunks].write_fn = write_graph_chunk_bloom_data;
                num_chunks++;
        }
        if (ctx->num_commit_graphs_after > 1) {
-               chunk_ids[num_chunks] = GRAPH_CHUNKID_BASE;
+               chunks[num_chunks].id = GRAPH_CHUNKID_BASE;
+               chunks[num_chunks].size = hashsz * (ctx->num_commit_graphs_after - 1);
+               chunks[num_chunks].write_fn = write_graph_chunk_base;
                num_chunks++;
        }
 
-       chunk_ids[num_chunks] = 0;
-
-       chunk_offsets[0] = 8 + (num_chunks + 1) * GRAPH_CHUNKLOOKUP_WIDTH;
-       chunk_offsets[1] = chunk_offsets[0] + GRAPH_FANOUT_SIZE;
-       chunk_offsets[2] = chunk_offsets[1] + hashsz * ctx->commits.nr;
-       chunk_offsets[3] = chunk_offsets[2] + (hashsz + 16) * ctx->commits.nr;
-
-       num_chunks = 3;
-       if (ctx->num_extra_edges) {
-               chunk_offsets[num_chunks + 1] = chunk_offsets[num_chunks] +
-                                               4 * ctx->num_extra_edges;
-               num_chunks++;
-       }
-       if (ctx->changed_paths) {
-               chunk_offsets[num_chunks + 1] = chunk_offsets[num_chunks] +
-                                               sizeof(uint32_t) * ctx->commits.nr;
-               num_chunks++;
-
-               chunk_offsets[num_chunks + 1] = chunk_offsets[num_chunks] +
-                                               sizeof(uint32_t) * 3 + ctx->total_bloom_filter_data_size;
-               num_chunks++;
-       }
-       if (ctx->num_commit_graphs_after > 1) {
-               chunk_offsets[num_chunks + 1] = chunk_offsets[num_chunks] +
-                                               hashsz * (ctx->num_commit_graphs_after - 1);
-               num_chunks++;
-       }
+       chunks[num_chunks].id = 0;
+       chunks[num_chunks].size = 0;
 
        hashwrite_be32(f, GRAPH_SIGNATURE);
 
@@ -1697,13 +1743,16 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
        hashwrite_u8(f, num_chunks);
        hashwrite_u8(f, ctx->num_commit_graphs_after - 1);
 
+       chunk_offset = 8 + (num_chunks + 1) * GRAPH_CHUNKLOOKUP_WIDTH;
        for (i = 0; i <= num_chunks; i++) {
                uint32_t chunk_write[3];
 
-               chunk_write[0] = htonl(chunk_ids[i]);
-               chunk_write[1] = htonl(chunk_offsets[i] >> 32);
-               chunk_write[2] = htonl(chunk_offsets[i] & 0xffffffff);
+               chunk_write[0] = htonl(chunks[i].id);
+               chunk_write[1] = htonl(chunk_offset >> 32);
+               chunk_write[2] = htonl(chunk_offset & 0xffffffff);
                hashwrite(f, chunk_write, 12);
+
+               chunk_offset += chunks[i].size;
        }
 
        if (ctx->report_progress) {
@@ -1716,19 +1765,19 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
                        progress_title.buf,
                        num_chunks * ctx->commits.nr);
        }
-       write_graph_chunk_fanout(f, ctx);
-       write_graph_chunk_oids(f, hashsz, ctx);
-       write_graph_chunk_data(f, hashsz, ctx);
-       if (ctx->num_extra_edges)
-               write_graph_chunk_extra_edges(f, ctx);
-       if (ctx->changed_paths) {
-               write_graph_chunk_bloom_indexes(f, ctx);
-               write_graph_chunk_bloom_data(f, ctx, &bloom_settings);
-       }
-       if (ctx->num_commit_graphs_after > 1 &&
-           write_graph_chunk_base(f, ctx)) {
-               return -1;
+
+       for (i = 0; i < num_chunks; i++) {
+               uint64_t start_offset = f->total + f->offset;
+
+               if (chunks[i].write_fn(f, ctx))
+                       return -1;
+
+               if (f->total + f->offset != start_offset + chunks[i].size)
+                       BUG("expected to write %"PRId64" bytes to chunk %"PRIx32", but wrote %"PRId64" instead",
+                           chunks[i].size, chunks[i].id,
+                           f->total + f->offset - start_offset);
        }
+
        stop_progress(&ctx->progress);
        strbuf_release(&progress_title);
 
@@ -2062,9 +2111,23 @@ int write_commit_graph(struct object_directory *odb,
        ctx->report_progress = flags & COMMIT_GRAPH_WRITE_PROGRESS ? 1 : 0;
        ctx->split = flags & COMMIT_GRAPH_WRITE_SPLIT ? 1 : 0;
        ctx->split_opts = split_opts;
-       ctx->changed_paths = flags & COMMIT_GRAPH_WRITE_BLOOM_FILTERS ? 1 : 0;
        ctx->total_bloom_filter_data_size = 0;
 
+       if (flags & COMMIT_GRAPH_WRITE_BLOOM_FILTERS)
+               ctx->changed_paths = 1;
+       if (!(flags & COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS)) {
+               struct commit_graph *g;
+               prepare_commit_graph_one(ctx->r, ctx->odb);
+
+               g = ctx->r->objects->commit_graph;
+
+               /* We have changed-paths already. Keep them in the next graph */
+               if (g && g->chunk_bloom_data) {
+                       ctx->changed_paths = 1;
+                       ctx->bloom_settings = g->bloom_filter_settings;
+               }
+       }
+
        if (ctx->split) {
                struct commit_graph *g;
                prepare_commit_graph(ctx->r);
index 28f89cdf3e577582261c2261698bdd051b530edb..09a97030dcd8a2ea570da097d6f27a5d0cbaf934 100644 (file)
@@ -2,14 +2,11 @@
 #define COMMIT_GRAPH_H
 
 #include "git-compat-util.h"
-#include "repository.h"
-#include "string-list.h"
-#include "cache.h"
 #include "object-store.h"
 #include "oidset.h"
 
 #define GIT_TEST_COMMIT_GRAPH "GIT_TEST_COMMIT_GRAPH"
-#define GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD "GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD"
+#define GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE "GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE"
 #define GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS "GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS"
 
 /*
@@ -23,6 +20,9 @@ void git_test_write_commit_graph_or_die(void);
 
 struct commit;
 struct bloom_filter_settings;
+struct repository;
+struct raw_object_store;
+struct string_list;
 
 char *get_commit_graph_filename(struct object_directory *odb);
 int open_commit_graph(const char *graph_file, int *fd, struct stat *st);
@@ -92,6 +92,7 @@ enum commit_graph_write_flags {
        COMMIT_GRAPH_WRITE_PROGRESS   = (1 << 1),
        COMMIT_GRAPH_WRITE_SPLIT      = (1 << 2),
        COMMIT_GRAPH_WRITE_BLOOM_FILTERS = (1 << 3),
+       COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS = (1 << 4),
 };
 
 enum commit_graph_split_flags {
index bfbed1516a455f2270940c88a6bfcdab51033363..98de2c970c014badd30a3f8a6bbbcf6d1273cda7 100644 (file)
@@ -32,6 +32,7 @@ struct slabname {                                                     \
 void init_ ##slabname## _with_stride(struct slabname *s, unsigned stride); \
 void init_ ##slabname(struct slabname *s);                             \
 void clear_ ##slabname(struct slabname *s);                            \
+void deep_clear_ ##slabname(struct slabname *s, void (*free_fn)(elemtype *ptr)); \
 elemtype *slabname## _at_peek(struct slabname *s, const struct commit *c, int add_if_missing); \
 elemtype *slabname## _at(struct slabname *s, const struct commit *c);  \
 elemtype *slabname## _peek(struct slabname *s, const struct commit *c)
index 5c0eb91a5d175ddb079459a0ba13b9be1f74b1ab..557738df271c7dd78c5ddcc65d6fe6e47c665758 100644 (file)
@@ -38,6 +38,19 @@ scope void clear_ ##slabname(struct slabname *s)                     \
        FREE_AND_NULL(s->slab);                                         \
 }                                                                      \
                                                                        \
+scope void deep_clear_ ##slabname(struct slabname *s, void (*free_fn)(elemtype *)) \
+{                                                                      \
+       unsigned int i;                                                 \
+       for (i = 0; i < s->slab_count; i++) {                           \
+               unsigned int j;                                         \
+               if (!s->slab[i])                                        \
+                       continue;                                       \
+               for (j = 0; j < s->slab_size; j++)                      \
+                       free_fn(&s->slab[i][j * s->stride]);            \
+       }                                                               \
+       clear_ ##slabname(s);                                           \
+}                                                                      \
+                                                                       \
 scope elemtype *slabname## _at_peek(struct slabname *s,                        \
                                                  const struct commit *c, \
                                                  int add_if_missing)   \
index 05b3f2804e74d5bb6bbcc0c735d7471d32566d88..8e72a30536541cc1064b8bd8d3cf727af03fa23c 100644 (file)
  *
  *   Call this function before the slab falls out of scope to avoid
  *   leaking memory.
+ *
+ * - void deep_clear_indegree(struct indegree *, void (*free_fn)(int*))
+ *
+ *   Empties the slab, similar to clear_indegree(), but in addition it
+ *   calls the given 'free_fn' for each slab entry to release any
+ *   additional memory that might be owned by the entry (but not the
+ *   entry itself!).
+ *   Note that 'free_fn' might be called even for entries for which no
+ *   indegree_at() call has been made; in this case 'free_fn' is invoked
+ *   with a pointer to a zero-initialized location.
  */
 
 #define define_commit_slab(slabname, elemtype) \
index 7128895c3ad86c261b2260d7faba0f79f263b1ca..4ce8cb38d5efe01a51648b4187acc291f588c012 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -1630,22 +1630,22 @@ size_t ignore_non_trailer(const char *buf, size_t len)
 int run_commit_hook(int editor_is_used, const char *index_file,
                    const char *name, ...)
 {
-       struct argv_array hook_env = ARGV_ARRAY_INIT;
+       struct strvec hook_env = STRVEC_INIT;
        va_list args;
        int ret;
 
-       argv_array_pushf(&hook_env, "GIT_INDEX_FILE=%s", index_file);
+       strvec_pushf(&hook_env, "GIT_INDEX_FILE=%s", index_file);
 
        /*
         * Let the hook know that no editor will be launched.
         */
        if (!editor_is_used)
-               argv_array_push(&hook_env, "GIT_EDITOR=:");
+               strvec_push(&hook_env, "GIT_EDITOR=:");
 
        va_start(args, name);
-       ret = run_hook_ve(hook_env.argv,name, args);
+       ret = run_hook_ve(hook_env.v, name, args);
        va_end(args);
-       argv_array_clear(&hook_env);
+       strvec_clear(&hook_env);
 
        return ret;
 }
index 8ee0b6408e945b369b30d9052c91aa7e1f31553a..a00f3312300ac36773bf42aec80b4514f31b1293 100644 (file)
@@ -18,8 +18,8 @@ void open_in_gdb(void)
        static struct child_process cp = CHILD_PROCESS_INIT;
        extern char *_pgmptr;
 
-       argv_array_pushl(&cp.args, "mintty", "gdb", NULL);
-       argv_array_pushf(&cp.args, "--pid=%d", getpid());
+       strvec_pushl(&cp.args, "mintty", "gdb", NULL);
+       strvec_pushf(&cp.args, "--pid=%d", getpid());
        cp.clean_on_exit = 1;
        if (start_command(&cp) < 0)
                die_errno("Could not start gdb");
@@ -290,6 +290,9 @@ int mingw_unlink(const char *pathname)
        if (xutftowcs_path(wpathname, pathname) < 0)
                return -1;
 
+       if (DeleteFileW(wpathname))
+               return 0;
+
        /* read-only files cannot be removed */
        _wchmod(wpathname, 0666);
        while ((ret = _wunlink(wpathname)) == -1 && tries < ARRAY_SIZE(delay)) {
index 35bca03d1470601568d17ed3cf71c5c622d43d87..43b73ddc75891a090d81b5e4ef34864f83c653a8 100644 (file)
@@ -86,9 +86,9 @@ static void restore_term(void)
                if (stty_restore.nr == 0)
                        return;
 
-               argv_array_push(&cp.args, "stty");
+               strvec_push(&cp.args, "stty");
                for (i = 0; i < stty_restore.nr; i++)
-                       argv_array_push(&cp.args, stty_restore.items[i].string);
+                       strvec_push(&cp.args, stty_restore.items[i].string);
                run_command(&cp);
                string_list_clear(&stty_restore, 0);
                return;
@@ -107,25 +107,25 @@ static int disable_bits(DWORD bits)
        if (use_stty) {
                struct child_process cp = CHILD_PROCESS_INIT;
 
-               argv_array_push(&cp.args, "stty");
+               strvec_push(&cp.args, "stty");
 
                if (bits & ENABLE_LINE_INPUT) {
                        string_list_append(&stty_restore, "icanon");
-                       argv_array_push(&cp.args, "-icanon");
+                       strvec_push(&cp.args, "-icanon");
                }
 
                if (bits & ENABLE_ECHO_INPUT) {
                        string_list_append(&stty_restore, "echo");
-                       argv_array_push(&cp.args, "-echo");
+                       strvec_push(&cp.args, "-echo");
                }
 
                if (bits & ENABLE_PROCESSED_INPUT) {
                        string_list_append(&stty_restore, "-ignbrk");
                        string_list_append(&stty_restore, "intr");
                        string_list_append(&stty_restore, "^c");
-                       argv_array_push(&cp.args, "ignbrk");
-                       argv_array_push(&cp.args, "intr");
-                       argv_array_push(&cp.args, "");
+                       strvec_push(&cp.args, "ignbrk");
+                       strvec_push(&cp.args, "intr");
+                       strvec_push(&cp.args, "");
                }
 
                if (run_command(&cp) == 0)
@@ -273,7 +273,7 @@ static int is_known_escape_sequence(const char *sequence)
                hashmap_init(&sequences, (hashmap_cmp_fn)sequence_entry_cmp,
                             NULL, 0);
 
-               argv_array_pushl(&cp.args, "infocmp", "-L", "-1", NULL);
+               strvec_pushl(&cp.args, "infocmp", "-L", "-1", NULL);
                if (pipe_command(&cp, NULL, 0, &buf, 0, NULL, 0))
                        strbuf_setlen(&buf, 0);
 
index 8db9c77098f01bec5178751c8b4e64880d473619..2bdff4457be7d5b1e1fd5f6acb558ac41b946a8c 100644 (file)
--- a/config.c
+++ b/config.c
@@ -2006,18 +2006,27 @@ const struct string_list *git_configset_get_value_multi(struct config_set *cs, c
        return e ? &e->value_list : NULL;
 }
 
-int git_configset_get_string_const(struct config_set *cs, const char *key, const char **dest)
+int git_configset_get_string(struct config_set *cs, const char *key, char **dest)
 {
        const char *value;
        if (!git_configset_get_value(cs, key, &value))
-               return git_config_string(dest, key, value);
+               return git_config_string((const char **)dest, key, value);
        else
                return 1;
 }
 
-int git_configset_get_string(struct config_set *cs, const char *key, char **dest)
+int git_configset_get_string_tmp(struct config_set *cs, const char *key,
+                                const char **dest)
 {
-       return git_configset_get_string_const(cs, key, (const char **)dest);
+       const char *value;
+       if (!git_configset_get_value(cs, key, &value)) {
+               if (!value)
+                       return config_error_nonbool(key);
+               *dest = value;
+               return 0;
+       } else {
+               return 1;
+       }
 }
 
 int git_configset_get_int(struct config_set *cs, const char *key, int *dest)
@@ -2147,22 +2156,26 @@ const struct string_list *repo_config_get_value_multi(struct repository *repo,
        return git_configset_get_value_multi(repo->config, key);
 }
 
-int repo_config_get_string_const(struct repository *repo,
-                                const char *key, const char **dest)
+int repo_config_get_string(struct repository *repo,
+                          const char *key, char **dest)
 {
        int ret;
        git_config_check_init(repo);
-       ret = git_configset_get_string_const(repo->config, key, dest);
+       ret = git_configset_get_string(repo->config, key, dest);
        if (ret < 0)
                git_die_config(key, NULL);
        return ret;
 }
 
-int repo_config_get_string(struct repository *repo,
-                          const char *key, char **dest)
+int repo_config_get_string_tmp(struct repository *repo,
+                              const char *key, const char **dest)
 {
+       int ret;
        git_config_check_init(repo);
-       return repo_config_get_string_const(repo, key, (const char **)dest);
+       ret = git_configset_get_string_tmp(repo->config, key, dest);
+       if (ret < 0)
+               git_die_config(key, NULL);
+       return ret;
 }
 
 int repo_config_get_int(struct repository *repo,
@@ -2232,14 +2245,14 @@ const struct string_list *git_config_get_value_multi(const char *key)
        return repo_config_get_value_multi(the_repository, key);
 }
 
-int git_config_get_string_const(const char *key, const char **dest)
+int git_config_get_string(const char *key, char **dest)
 {
-       return repo_config_get_string_const(the_repository, key, dest);
+       return repo_config_get_string(the_repository, key, dest);
 }
 
-int git_config_get_string(const char *key, char **dest)
+int git_config_get_string_tmp(const char *key, const char **dest)
 {
-       return repo_config_get_string(the_repository, key, dest);
+       return repo_config_get_string_tmp(the_repository, key, dest);
 }
 
 int git_config_get_int(const char *key, int *dest)
@@ -2274,7 +2287,7 @@ int git_config_get_pathname(const char *key, const char **dest)
 
 int git_config_get_expiry(const char *key, const char **output)
 {
-       int ret = git_config_get_string_const(key, output);
+       int ret = git_config_get_string(key, (char **)output);
        if (ret)
                return ret;
        if (strcmp(*output, "now")) {
@@ -2287,11 +2300,11 @@ int git_config_get_expiry(const char *key, const char **output)
 
 int git_config_get_expiry_in_days(const char *key, timestamp_t *expiry, timestamp_t now)
 {
-       char *expiry_string;
+       const char *expiry_string;
        intmax_t days;
        timestamp_t when;
 
-       if (git_config_get_string(key, &expiry_string))
+       if (git_config_get_string_tmp(key, &expiry_string))
                return 1; /* no such thing */
 
        if (git_parse_signed(expiry_string, &days, maximum_signed_value_of_type(int))) {
@@ -3115,7 +3128,7 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
        }
 
        while (fgets(buf, sizeof(buf), config_file)) {
-               int i;
+               unsigned i;
                int length;
                int is_section = 0;
                char *output = buf;
index 060874488f413cd6453e1633cd69c971d6e5d613..91cdfbfb414fdcc7835a3a467ea680b5780a74c8 100644 (file)
--- a/config.h
+++ b/config.h
@@ -458,8 +458,8 @@ void git_configset_clear(struct config_set *cs);
  */
 int git_configset_get_value(struct config_set *cs, const char *key, const char **dest);
 
-int git_configset_get_string_const(struct config_set *cs, const char *key, const char **dest);
 int git_configset_get_string(struct config_set *cs, const char *key, char **dest);
+int git_configset_get_string_tmp(struct config_set *cs, const char *key, const char **dest);
 int git_configset_get_int(struct config_set *cs, const char *key, int *dest);
 int git_configset_get_ulong(struct config_set *cs, const char *key, unsigned long *dest);
 int git_configset_get_bool(struct config_set *cs, const char *key, int *dest);
@@ -474,10 +474,10 @@ int repo_config_get_value(struct repository *repo,
                          const char *key, const char **value);
 const struct string_list *repo_config_get_value_multi(struct repository *repo,
                                                      const char *key);
-int repo_config_get_string_const(struct repository *repo,
-                                const char *key, const char **dest);
 int repo_config_get_string(struct repository *repo,
                           const char *key, char **dest);
+int repo_config_get_string_tmp(struct repository *repo,
+                              const char *key, const char **dest);
 int repo_config_get_int(struct repository *repo,
                        const char *key, int *dest);
 int repo_config_get_ulong(struct repository *repo,
@@ -529,13 +529,14 @@ void git_config_clear(void);
  * error message and returns -1. When the configuration variable `key` is
  * not found, returns 1 without touching `dest`.
  */
-int git_config_get_string_const(const char *key, const char **dest);
+int git_config_get_string(const char *key, char **dest);
 
 /**
- * Similar to `git_config_get_string_const`, except that retrieved value
- * copied into the `dest` parameter is a mutable string.
+ * Similar to `git_config_get_string`, but does not allocate any new
+ * memory; on success `dest` will point to memory owned by the config
+ * machinery, which could be invalidated if it is discarded and reloaded.
  */
-int git_config_get_string(const char *key, char **dest);
+int git_config_get_string_tmp(const char *key, const char **dest);
 
 /**
  * Finds and parses the value to an integer for the configuration variable
index cd4a82a9eb4a2b0a4a1d45f0186cd7f858a0ff57..89b218d11a5313f327492795964793bec8670160 100644 (file)
@@ -16,8 +16,6 @@ DEVELOPER_CFLAGS += -Wstrict-prototypes
 DEVELOPER_CFLAGS += -Wunused
 DEVELOPER_CFLAGS += -Wvla
 
-DEVELOPER_CFLAGS += -DENABLE_SHA256
-
 ifndef COMPILER_FEATURES
 COMPILER_FEATURES := $(shell ./detect-compiler $(CC))
 endif
index e0d5b9fee05fc5db4c329d4825600020dce8910a..8b8f56cf6d230b23c46bb980755cb6d1fc3684ef 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -17,7 +17,7 @@
 #include "alias.h"
 
 static char *server_capabilities_v1;
-static struct argv_array server_capabilities_v2 = ARGV_ARRAY_INIT;
+static struct strvec server_capabilities_v2 = STRVEC_INIT;
 static const char *next_server_feature_value(const char *feature, int *len, int *offset);
 
 static int check_ref(const char *name, unsigned int flags)
@@ -70,9 +70,9 @@ int server_supports_v2(const char *c, int die_on_error)
 {
        int i;
 
-       for (i = 0; i < server_capabilities_v2.argc; i++) {
+       for (i = 0; i < server_capabilities_v2.nr; i++) {
                const char *out;
-               if (skip_prefix(server_capabilities_v2.argv[i], c, &out) &&
+               if (skip_prefix(server_capabilities_v2.v[i], c, &out) &&
                    (!*out || *out == '='))
                        return 1;
        }
@@ -87,9 +87,9 @@ int server_feature_v2(const char *c, const char **v)
 {
        int i;
 
-       for (i = 0; i < server_capabilities_v2.argc; i++) {
+       for (i = 0; i < server_capabilities_v2.nr; i++) {
                const char *out;
-               if (skip_prefix(server_capabilities_v2.argv[i], c, &out) &&
+               if (skip_prefix(server_capabilities_v2.v[i], c, &out) &&
                    (*out == '=')) {
                        *v = out + 1;
                        return 1;
@@ -103,9 +103,9 @@ int server_supports_feature(const char *c, const char *feature,
 {
        int i;
 
-       for (i = 0; i < server_capabilities_v2.argc; i++) {
+       for (i = 0; i < server_capabilities_v2.nr; i++) {
                const char *out;
-               if (skip_prefix(server_capabilities_v2.argv[i], c, &out) &&
+               if (skip_prefix(server_capabilities_v2.v[i], c, &out) &&
                    (!*out || *(out++) == '=')) {
                        if (parse_feature_request(out, feature))
                                return 1;
@@ -123,7 +123,7 @@ int server_supports_feature(const char *c, const char *feature,
 static void process_capabilities_v2(struct packet_reader *reader)
 {
        while (packet_reader_read(reader) == PACKET_READ_NORMAL)
-               argv_array_push(&server_capabilities_v2, reader->line);
+               strvec_push(&server_capabilities_v2, reader->line);
 
        if (reader->status != PACKET_READ_FLUSH)
                die(_("expected flush after capabilities"));
@@ -453,7 +453,7 @@ void check_stateless_delimiter(int stateless_rpc,
 
 struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
                             struct ref **list, int for_push,
-                            const struct argv_array *ref_prefixes,
+                            const struct strvec *ref_prefixes,
                             const struct string_list *server_options,
                             int stateless_rpc)
 {
@@ -488,9 +488,9 @@ struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
        if (!for_push)
                packet_write_fmt(fd_out, "peel\n");
        packet_write_fmt(fd_out, "symrefs\n");
-       for (i = 0; ref_prefixes && i < ref_prefixes->argc; i++) {
+       for (i = 0; ref_prefixes && i < ref_prefixes->nr; i++) {
                packet_write_fmt(fd_out, "ref-prefix %s\n",
-                                ref_prefixes->argv[i]);
+                                ref_prefixes->v[i]);
        }
        packet_flush(fd_out);
 
@@ -944,9 +944,9 @@ static struct child_process *git_proxy_connect(int fd[2], char *host)
 
        proxy = xmalloc(sizeof(*proxy));
        child_process_init(proxy);
-       argv_array_push(&proxy->args, git_proxy_command);
-       argv_array_push(&proxy->args, host);
-       argv_array_push(&proxy->args, port);
+       strvec_push(&proxy->args, git_proxy_command);
+       strvec_push(&proxy->args, host);
+       strvec_push(&proxy->args, port);
        proxy->in = -1;
        proxy->out = -1;
        if (start_command(proxy))
@@ -1052,7 +1052,7 @@ static const char *get_ssh_command(void)
        if ((ssh = getenv("GIT_SSH_COMMAND")))
                return ssh;
 
-       if (!git_config_get_string_const("core.sshcommand", &ssh))
+       if (!git_config_get_string_tmp("core.sshcommand", &ssh))
                return ssh;
 
        return NULL;
@@ -1071,7 +1071,7 @@ static void override_ssh_variant(enum ssh_variant *ssh_variant)
 {
        const char *variant = getenv("GIT_SSH_VARIANT");
 
-       if (!variant && git_config_get_string_const("ssh.variant", &variant))
+       if (!variant && git_config_get_string_tmp("ssh.variant", &variant))
                return;
 
        if (!strcmp(variant, "auto"))
@@ -1199,16 +1199,16 @@ static struct child_process *git_connect_git(int fd[2], char *hostandport,
  * Append the appropriate environment variables to `env` and options to
  * `args` for running ssh in Git's SSH-tunneled transport.
  */
-static void push_ssh_options(struct argv_array *args, struct argv_array *env,
+static void push_ssh_options(struct strvec *args, struct strvec *env,
                             enum ssh_variant variant, const char *port,
                             enum protocol_version version, int flags)
 {
        if (variant == VARIANT_SSH &&
            version > 0) {
-               argv_array_push(args, "-o");
-               argv_array_push(args, "SendEnv=" GIT_PROTOCOL_ENVIRONMENT);
-               argv_array_pushf(env, GIT_PROTOCOL_ENVIRONMENT "=version=%d",
-                                version);
+               strvec_push(args, "-o");
+               strvec_push(args, "SendEnv=" GIT_PROTOCOL_ENVIRONMENT);
+               strvec_pushf(env, GIT_PROTOCOL_ENVIRONMENT "=version=%d",
+                            version);
        }
 
        if (flags & CONNECT_IPV4) {
@@ -1221,7 +1221,7 @@ static void push_ssh_options(struct argv_array *args, struct argv_array *env,
                case VARIANT_PLINK:
                case VARIANT_PUTTY:
                case VARIANT_TORTOISEPLINK:
-                       argv_array_push(args, "-4");
+                       strvec_push(args, "-4");
                }
        } else if (flags & CONNECT_IPV6) {
                switch (variant) {
@@ -1233,12 +1233,12 @@ static void push_ssh_options(struct argv_array *args, struct argv_array *env,
                case VARIANT_PLINK:
                case VARIANT_PUTTY:
                case VARIANT_TORTOISEPLINK:
-                       argv_array_push(args, "-6");
+                       strvec_push(args, "-6");
                }
        }
 
        if (variant == VARIANT_TORTOISEPLINK)
-               argv_array_push(args, "-batch");
+               strvec_push(args, "-batch");
 
        if (port) {
                switch (variant) {
@@ -1247,15 +1247,15 @@ static void push_ssh_options(struct argv_array *args, struct argv_array *env,
                case VARIANT_SIMPLE:
                        die(_("ssh variant 'simple' does not support setting port"));
                case VARIANT_SSH:
-                       argv_array_push(args, "-p");
+                       strvec_push(args, "-p");
                        break;
                case VARIANT_PLINK:
                case VARIANT_PUTTY:
                case VARIANT_TORTOISEPLINK:
-                       argv_array_push(args, "-P");
+                       strvec_push(args, "-P");
                }
 
-               argv_array_push(args, port);
+               strvec_push(args, port);
        }
 }
 
@@ -1293,18 +1293,18 @@ static void fill_ssh_args(struct child_process *conn, const char *ssh_host,
                detect.use_shell = conn->use_shell;
                detect.no_stdin = detect.no_stdout = detect.no_stderr = 1;
 
-               argv_array_push(&detect.args, ssh);
-               argv_array_push(&detect.args, "-G");
+               strvec_push(&detect.args, ssh);
+               strvec_push(&detect.args, "-G");
                push_ssh_options(&detect.args, &detect.env_array,
                                 VARIANT_SSH, port, version, flags);
-               argv_array_push(&detect.args, ssh_host);
+               strvec_push(&detect.args, ssh_host);
 
                variant = run_command(&detect) ? VARIANT_SIMPLE : VARIANT_SSH;
        }
 
-       argv_array_push(&conn->args, ssh);
+       strvec_push(&conn->args, ssh);
        push_ssh_options(&conn->args, &conn->env_array, variant, port, version, flags);
-       argv_array_push(&conn->args, ssh_host);
+       strvec_push(&conn->args, ssh_host);
 }
 
 /*
@@ -1365,7 +1365,7 @@ struct child_process *git_connect(int fd[2], const char *url,
 
                /* remove repo-local variables from the environment */
                for (var = local_repo_env; *var; var++)
-                       argv_array_push(&conn->env_array, *var);
+                       strvec_push(&conn->env_array, *var);
 
                conn->use_shell = 1;
                conn->in = conn->out = -1;
@@ -1397,11 +1397,12 @@ struct child_process *git_connect(int fd[2], const char *url,
                        transport_check_allowed("file");
                        conn->trace2_child_class = "transport/file";
                        if (version > 0) {
-                               argv_array_pushf(&conn->env_array, GIT_PROTOCOL_ENVIRONMENT "=version=%d",
-                                                version);
+                               strvec_pushf(&conn->env_array,
+                                            GIT_PROTOCOL_ENVIRONMENT "=version=%d",
+                                            version);
                        }
                }
-               argv_array_push(&conn->args, cmd.buf);
+               strvec_push(&conn->args, cmd.buf);
 
                if (start_command(conn))
                        die(_("unable to fork"));
index 937b4bae387a5757123ebb374fe98102be80921a..b18299fdf0e5224924915810d66196a1d38cbe56 100644 (file)
@@ -22,14 +22,13 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
                    struct check_connected_options *opt)
 {
        struct child_process rev_list = CHILD_PROCESS_INIT;
+       FILE *rev_list_in;
        struct check_connected_options defaults = CHECK_CONNECTED_INIT;
-       char commit[GIT_MAX_HEXSZ + 1];
        struct object_id oid;
        int err = 0;
        struct packed_git *new_pack = NULL;
        struct transport *transport;
        size_t base_len;
-       const unsigned hexsz = the_hash_algo->hexsz;
 
        if (!opt)
                opt = &defaults;
@@ -90,23 +89,23 @@ promisor_pack_found:
 
 no_promisor_pack_found:
        if (opt->shallow_file) {
-               argv_array_push(&rev_list.args, "--shallow-file");
-               argv_array_push(&rev_list.args, opt->shallow_file);
+               strvec_push(&rev_list.args, "--shallow-file");
+               strvec_push(&rev_list.args, opt->shallow_file);
        }
-       argv_array_push(&rev_list.args,"rev-list");
-       argv_array_push(&rev_list.args, "--objects");
-       argv_array_push(&rev_list.args, "--stdin");
+       strvec_push(&rev_list.args,"rev-list");
+       strvec_push(&rev_list.args, "--objects");
+       strvec_push(&rev_list.args, "--stdin");
        if (has_promisor_remote())
-               argv_array_push(&rev_list.args, "--exclude-promisor-objects");
+               strvec_push(&rev_list.args, "--exclude-promisor-objects");
        if (!opt->is_deepening_fetch) {
-               argv_array_push(&rev_list.args, "--not");
-               argv_array_push(&rev_list.args, "--all");
+               strvec_push(&rev_list.args, "--not");
+               strvec_push(&rev_list.args, "--all");
        }
-       argv_array_push(&rev_list.args, "--quiet");
-       argv_array_push(&rev_list.args, "--alternate-refs");
+       strvec_push(&rev_list.args, "--quiet");
+       strvec_push(&rev_list.args, "--alternate-refs");
        if (opt->progress)
-               argv_array_pushf(&rev_list.args, "--progress=%s",
-                                _("Checking connectivity"));
+               strvec_pushf(&rev_list.args, "--progress=%s",
+                            _("Checking connectivity"));
 
        rev_list.git_cmd = 1;
        rev_list.env = opt->env;
@@ -122,7 +121,8 @@ no_promisor_pack_found:
 
        sigchain_push(SIGPIPE, SIG_IGN);
 
-       commit[hexsz] = '\n';
+       rev_list_in = xfdopen(rev_list.in, "w");
+
        do {
                /*
                 * If index-pack already checked that:
@@ -135,16 +135,17 @@ no_promisor_pack_found:
                if (new_pack && find_pack_entry_one(oid.hash, new_pack))
                        continue;
 
-               memcpy(commit, oid_to_hex(&oid), hexsz);
-               if (write_in_full(rev_list.in, commit, hexsz + 1) < 0) {
-                       if (errno != EPIPE && errno != EINVAL)
-                               error_errno(_("failed write to rev-list"));
-                       err = -1;
+               if (fprintf(rev_list_in, "%s\n", oid_to_hex(&oid)) < 0)
                        break;
-               }
        } while (!fn(cb_data, &oid));
 
-       if (close(rev_list.in))
+       if (ferror(rev_list_in) || fflush(rev_list_in)) {
+               if (errno != EPIPE && errno != EINVAL)
+                       error_errno(_("failed write to rev-list"));
+               err = -1;
+       }
+
+       if (fclose(rev_list_in))
                err = error_errno(_("failed to close rev-list's stdin"));
 
        sigchain_pop(SIGPIPE);
diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
new file mode 100644 (file)
index 0000000..47215df
--- /dev/null
@@ -0,0 +1,1000 @@
+#
+#      Copyright (c) 2020 Sibi Siddharthan
+#
+
+#[[
+
+Instructions to run CMake:
+
+cmake `relative-path-to-CMakeLists.txt` -DCMAKE_BUILD_TYPE=Release
+Eg.
+From the root of git source tree
+       `cmake contrib/buildsystems/ `
+This will build the git binaries at the root
+
+For out of source builds, say build in 'git/git-build/'
+       `mkdir git-build;cd git-build; cmake ../contrib/buildsystems/`
+This will build the git binaries in git-build directory
+
+Possible build configurations(-DCMAKE_BUILD_TYPE) with corresponding
+compiler flags
+Debug : -g
+Release: -O3
+RelWithDebInfo : -O2 -g
+MinSizeRel : -Os
+empty(default) :
+
+NOTE: -DCMAKE_BUILD_TYPE is optional. For multi-config generators like Visual Studio
+this option is ignored
+
+This process generates a Makefile(Linux/*BSD/MacOS) , Visual Studio solution(Windows) by default.
+Run `make` to build Git on Linux/*BSD/MacOS.
+Open git.sln on Windows and build Git.
+
+NOTE: By default CMake uses Makefile as the build tool on Linux and Visual Studio in Windows,
+to use another tool say `ninja` add this to the command line when configuring.
+`-G Ninja`
+
+]]
+cmake_minimum_required(VERSION 3.14)
+
+#set the source directory to root of git
+set(CMAKE_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
+
+find_program(SH_EXE sh)
+if(NOT SH_EXE)
+       message(FATAL_ERROR "sh: shell interpreter was not found in your path, please install one."
+                       "On Windows, you can get it as part of 'Git for Windows' install at https://gitforwindows.org/")
+endif()
+
+#Create GIT-VERSION-FILE using GIT-VERSION-GEN
+if(NOT EXISTS ${CMAKE_SOURCE_DIR}/GIT-VERSION-FILE)
+       message("Generating GIT-VERSION-FILE")
+       execute_process(COMMAND ${SH_EXE} ${CMAKE_SOURCE_DIR}/GIT-VERSION-GEN
+               WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
+endif()
+
+#Parse GIT-VERSION-FILE to get the version
+file(STRINGS ${CMAKE_SOURCE_DIR}/GIT-VERSION-FILE git_version REGEX "GIT_VERSION = (.*)")
+string(REPLACE "GIT_VERSION = " "" git_version ${git_version})
+string(FIND ${git_version} "GIT" location)
+if(location EQUAL -1)
+       string(REGEX MATCH "[0-9]*\\.[0-9]*\\.[0-9]*" git_version ${git_version})
+else()
+       string(REGEX MATCH "[0-9]*\\.[0-9]*" git_version ${git_version})
+       string(APPEND git_version ".0") #for building from a snapshot
+endif()
+
+project(git
+       VERSION ${git_version}
+       LANGUAGES C)
+
+
+#TODO gitk git-gui gitweb
+#TODO Enable NLS on windows natively
+#TODO Add pcre support
+
+#macros for parsing the Makefile for sources and scripts
+macro(parse_makefile_for_sources list_var regex)
+       file(STRINGS ${CMAKE_SOURCE_DIR}/Makefile ${list_var} REGEX "^${regex} \\+=(.*)")
+       string(REPLACE "${regex} +=" "" ${list_var} ${${list_var}})
+       string(REPLACE "$(COMPAT_OBJS)" "" ${list_var} ${${list_var}}) #remove "$(COMPAT_OBJS)" This is only for libgit.
+       string(STRIP ${${list_var}} ${list_var}) #remove trailing/leading whitespaces
+       string(REPLACE ".o" ".c;" ${list_var} ${${list_var}}) #change .o to .c, ; is for converting the string into a list
+       list(TRANSFORM ${list_var} STRIP) #remove trailing/leading whitespaces for each element in list
+       list(REMOVE_ITEM ${list_var} "") #remove empty list elements
+endmacro()
+
+macro(parse_makefile_for_scripts list_var regex lang)
+       file(STRINGS ${CMAKE_SOURCE_DIR}/Makefile ${list_var} REGEX "^${regex} \\+=(.*)")
+       string(REPLACE "${regex} +=" "" ${list_var} ${${list_var}})
+       string(STRIP ${${list_var}} ${list_var}) #remove trailing/leading whitespaces
+       string(REPLACE " " ";" ${list_var} ${${list_var}}) #convert string to a list
+       if(NOT ${lang}) #exclude for SCRIPT_LIB
+               list(TRANSFORM ${list_var} REPLACE "${lang}" "") #do the replacement
+       endif()
+endmacro()
+
+include(CheckTypeSize)
+include(CheckCSourceRuns)
+include(CheckCSourceCompiles)
+include(CheckIncludeFile)
+include(CheckFunctionExists)
+include(CheckSymbolExists)
+include(CheckStructHasMember)
+include(CTest)
+
+find_package(ZLIB REQUIRED)
+find_package(CURL)
+find_package(EXPAT)
+find_package(Iconv)
+
+#Don't use libintl on Windows Visual Studio and Clang builds
+if(NOT (WIN32 AND (CMAKE_C_COMPILER_ID STREQUAL "MSVC" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")))
+       find_package(Intl)
+endif()
+
+if(NOT Intl_FOUND)
+       add_compile_definitions(NO_GETTEXT)
+       if(NOT Iconv_FOUND)
+               add_compile_definitions(NO_ICONV)
+       endif()
+endif()
+
+include_directories(SYSTEM ${ZLIB_INCLUDE_DIRS})
+if(CURL_FOUND)
+       include_directories(SYSTEM ${CURL_INCLUDE_DIRS})
+endif()
+if(EXPAT_FOUND)
+       include_directories(SYSTEM ${EXPAT_INCLUDE_DIRS})
+endif()
+if(Iconv_FOUND)
+       include_directories(SYSTEM ${Iconv_INCLUDE_DIRS})
+endif()
+if(Intl_FOUND)
+       include_directories(SYSTEM ${Intl_INCLUDE_DIRS})
+endif()
+
+
+if(WIN32 AND NOT MSVC)#not required for visual studio builds
+       find_program(WINDRES_EXE windres)
+       if(NOT WINDRES_EXE)
+               message(FATAL_ERROR "Install windres on Windows for resource files")
+       endif()
+endif()
+
+find_program(MSGFMT_EXE msgfmt)
+if(NOT MSGFMT_EXE)
+       message(WARNING "Text Translations won't be build")
+endif()
+
+#Force all visual studio outputs to CMAKE_BINARY_DIR
+if(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
+       set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR})
+       set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR})
+       add_compile_options(/MP)
+endif()
+
+#default behaviour
+include_directories(${CMAKE_SOURCE_DIR})
+add_compile_definitions(GIT_HOST_CPU="${CMAKE_SYSTEM_PROCESSOR}")
+add_compile_definitions(SHA256_BLK INTERNAL_QSORT RUNTIME_PREFIX)
+add_compile_definitions(NO_OPENSSL SHA1_DC SHA1DC_NO_STANDARD_INCLUDES
+                       SHA1DC_INIT_SAFE_HASH_DEFAULT=0
+                       SHA1DC_CUSTOM_INCLUDE_SHA1_C="cache.h"
+                       SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C="git-compat-util.h" )
+list(APPEND compat_SOURCES sha1dc_git.c sha1dc/sha1.c sha1dc/ubc_check.c block-sha1/sha1.c sha256/block/sha256.c compat/qsort_s.c)
+
+
+add_compile_definitions(PAGER_ENV="LESS=FRX LV=-c"
+                       ETC_GITATTRIBUTES="etc/gitattributes"
+                       ETC_GITCONFIG="etc/gitconfig"
+                       GIT_EXEC_PATH="libexec/git-core"
+                       GIT_LOCALE_PATH="share/locale"
+                       GIT_MAN_PATH="share/man"
+                       GIT_INFO_PATH="share/info"
+                       GIT_HTML_PATH="share/doc/git-doc"
+                       DEFAULT_HELP_FORMAT="html"
+                       DEFAULT_GIT_TEMPLATE_DIR="share/git-core/templates"
+                       GIT_VERSION="${PROJECT_VERSION}.GIT"
+                       GIT_USER_AGENT="git/${PROJECT_VERSION}.GIT"
+                       BINDIR="bin"
+                       GIT_BUILT_FROM_COMMIT="")
+
+if(WIN32)
+       set(FALLBACK_RUNTIME_PREFIX /mingw64)
+       add_compile_definitions(FALLBACK_RUNTIME_PREFIX="${FALLBACK_RUNTIME_PREFIX}")
+else()
+       set(FALLBACK_RUNTIME_PREFIX /home/$ENV{USER})
+       add_compile_definitions(FALLBACK_RUNTIME_PREFIX="${FALLBACK_RUNTIME_PREFIX}")
+endif()
+
+
+#Platform Specific
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+       if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
+               include_directories(${CMAKE_SOURCE_DIR}/compat/vcbuild/include)
+               add_compile_definitions(_CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE)
+       endif()
+       include_directories(${CMAKE_SOURCE_DIR}/compat/win32)
+       add_compile_definitions(HAVE_ALLOCA_H NO_POSIX_GOODIES NATIVE_CRLF NO_UNIX_SOCKETS WIN32
+                               _CONSOLE DETECT_MSYS_TTY STRIP_EXTENSION=".exe"  NO_SYMLINK_HEAD UNRELIABLE_FSTAT
+                               NOGDI OBJECT_CREATION_MODE=1 __USE_MINGW_ANSI_STDIO=0
+                               USE_NED_ALLOCATOR OVERRIDE_STRDUP MMAP_PREVENTS_DELETE USE_WIN32_MMAP
+                               UNICODE _UNICODE HAVE_WPGMPTR ENSURE_MSYSTEM_IS_SET)
+       list(APPEND compat_SOURCES compat/mingw.c compat/winansi.c compat/win32/path-utils.c
+               compat/win32/pthread.c compat/win32mmap.c compat/win32/syslog.c
+               compat/win32/trace2_win32_process_info.c compat/win32/dirent.c
+               compat/nedmalloc/nedmalloc.c compat/strdup.c)
+       set(NO_UNIX_SOCKETS 1)
+
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+       add_compile_definitions(PROCFS_EXECUTABLE_PATH="/proc/self/exe" HAVE_DEV_TTY )
+       list(APPEND compat_SOURCES unix-socket.c)
+endif()
+
+set(EXE_EXTENSION ${CMAKE_EXECUTABLE_SUFFIX})
+
+#header checks
+check_include_file(libgen.h HAVE_LIBGEN_H)
+if(NOT HAVE_LIBGEN_H)
+       add_compile_definitions(NO_LIBGEN_H)
+       list(APPEND compat_SOURCES compat/basename.c)
+endif()
+
+check_include_file(sys/sysinfo.h HAVE_SYSINFO)
+if(HAVE_SYSINFO)
+       add_compile_definitions(HAVE_SYSINFO)
+endif()
+
+check_c_source_compiles("
+#include <alloca.h>
+
+int main(void)
+{
+       char *p = (char *) alloca(2 * sizeof(int));
+
+       if (p)
+               return 0;
+       return 0;
+}"
+HAVE_ALLOCA_H)
+if(HAVE_ALLOCA_H)
+       add_compile_definitions(HAVE_ALLOCA_H)
+endif()
+
+check_include_file(strings.h HAVE_STRINGS_H)
+if(HAVE_STRINGS_H)
+       add_compile_definitions(HAVE_STRINGS_H)
+endif()
+
+check_include_file(sys/select.h HAVE_SYS_SELECT_H)
+if(NOT HAVE_SYS_SELECT_H)
+       add_compile_definitions(NO_SYS_SELECT_H)
+endif()
+
+check_include_file(sys/poll.h HAVE_SYS_POLL_H)
+if(NOT HAVE_SYS_POLL_H)
+       add_compile_definitions(NO_SYS_POLL_H)
+endif()
+
+check_include_file(poll.h HAVE_POLL_H)
+if(NOT HAVE_POLL_H)
+       add_compile_definitions(NO_POLL_H)
+endif()
+
+check_include_file(inttypes.h HAVE_INTTYPES_H)
+if(NOT HAVE_INTTYPES_H)
+       add_compile_definitions(NO_INTTYPES_H)
+endif()
+
+check_include_file(paths.h HAVE_PATHS_H)
+if(HAVE_PATHS_H)
+       add_compile_definitions(HAVE_PATHS_H)
+endif()
+
+#function checks
+set(function_checks
+       strcasestr memmem strlcpy strtoimax strtoumax strtoull
+       setenv mkdtemp poll pread memmem)
+
+#unsetenv,hstrerror are incompatible with windows build
+if(NOT WIN32)
+       list(APPEND function_checks unsetenv hstrerror)
+endif()
+
+foreach(f ${function_checks})
+       string(TOUPPER ${f} uf)
+       check_function_exists(${f} HAVE_${uf})
+       if(NOT HAVE_${uf})
+               add_compile_definitions(NO_${uf})
+       endif()
+endforeach()
+
+if(NOT HAVE_POLL_H OR NOT HAVE_SYS_POLL_H OR NOT HAVE_POLL)
+       include_directories(${CMAKE_SOURCE_DIR}/compat/poll)
+       add_compile_definitions(NO_POLL)
+       list(APPEND compat_SOURCES compat/poll/poll.c)
+endif()
+
+if(NOT HAVE_STRCASESTR)
+       list(APPEND compat_SOURCES compat/strcasestr.c)
+endif()
+
+if(NOT HAVE_STRLCPY)
+       list(APPEND compat_SOURCES compat/strlcpy.c)
+endif()
+
+if(NOT HAVE_STRTOUMAX)
+       list(APPEND compat_SOURCES compat/strtoumax.c compat/strtoimax.c)
+endif()
+
+if(NOT HAVE_SETENV)
+       list(APPEND compat_SOURCES compat/setenv.c)
+endif()
+
+if(NOT HAVE_MKDTEMP)
+       list(APPEND compat_SOURCES compat/mkdtemp.c)
+endif()
+
+if(NOT HAVE_PREAD)
+       list(APPEND compat_SOURCES compat/pread.c)
+endif()
+
+if(NOT HAVE_MEMMEM)
+       list(APPEND compat_SOURCES compat/memmem.c)
+endif()
+
+if(NOT WIN32)
+       if(NOT HAVE_UNSETENV)
+               list(APPEND compat_SOURCES compat/unsetenv.c)
+       endif()
+
+       if(NOT HAVE_HSTRERROR)
+               list(APPEND compat_SOURCES compat/hstrerror.c)
+       endif()
+endif()
+
+check_function_exists(getdelim HAVE_GETDELIM)
+if(HAVE_GETDELIM)
+       add_compile_definitions(HAVE_GETDELIM)
+endif()
+
+check_function_exists(clock_gettime HAVE_CLOCK_GETTIME)
+check_symbol_exists(CLOCK_MONOTONIC "time.h" HAVE_CLOCK_MONOTONIC)
+if(HAVE_CLOCK_GETTIME)
+       add_compile_definitions(HAVE_CLOCK_GETTIME)
+endif()
+if(HAVE_CLOCK_MONOTONIC)
+       add_compile_definitions(HAVE_CLOCK_MONOTONIC)
+endif()
+
+#check for st_blocks in struct stat
+check_struct_has_member("struct stat" st_blocks "sys/stat.h" STRUCT_STAT_HAS_ST_BLOCKS)
+if(NOT STRUCT_STAT_HAS_ST_BLOCKS)
+       add_compile_definitions(NO_ST_BLOCKS_IN_STRUCT_STAT)
+endif()
+
+#compile checks
+check_c_source_runs("
+#include<stdio.h>
+#include<stdarg.h>
+#include<string.h>
+#include<stdlib.h>
+
+int test_vsnprintf(char *str, size_t maxsize, const char *format, ...)
+{
+       int ret;
+       va_list ap;
+
+       va_start(ap, format);
+       ret = vsnprintf(str, maxsize, format, ap);
+       va_end(ap);
+       return ret;
+}
+
+int main(void)
+{
+       char buf[6];
+
+       if (test_vsnprintf(buf, 3, \"%s\", \"12345\") != 5
+               || strcmp(buf, \"12\"))
+                       return 1;
+       if (snprintf(buf, 3, \"%s\", \"12345\") != 5
+               || strcmp(buf, \"12\"))
+                       return 1;
+       return 0;
+}"
+SNPRINTF_OK)
+if(NOT SNPRINTF_OK)
+       add_compile_definitions(SNPRINTF_RETURNS_BOGUS)
+       list(APPEND compat_SOURCES compat/snprintf.c)
+endif()
+
+check_c_source_runs("
+#include<stdio.h>
+
+int main(void)
+{
+       FILE *f = fopen(\".\", \"r\");
+
+       return f != NULL;
+}"
+FREAD_READS_DIRECTORIES_NO)
+if(NOT FREAD_READS_DIRECTORIES_NO)
+       add_compile_definitions(FREAD_READS_DIRECTORIES)
+       list(APPEND compat_SOURCES compat/fopen.c)
+endif()
+
+check_c_source_compiles("
+#include <regex.h>
+#ifndef REG_STARTEND
+#error oops we dont have it
+#endif
+
+int main(void)
+{
+       return 0;
+}"
+HAVE_REGEX)
+if(NOT HAVE_REGEX)
+       include_directories(${CMAKE_SOURCE_DIR}/compat/regex)
+       list(APPEND compat_SOURCES compat/regex/regex.c )
+       add_compile_definitions(NO_REGEX NO_MBSUPPORT GAWK)
+endif()
+
+
+check_c_source_compiles("
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+int main(void)
+{
+       int val, mib[2];
+       size_t len;
+
+       mib[0] = CTL_HW;
+       mib[1] = 1;
+       len = sizeof(val);
+       return sysctl(mib, 2, &val, &len, NULL, 0) ? 1 : 0;
+}"
+HAVE_BSD_SYSCTL)
+if(HAVE_BSD_SYSCTL)
+       add_compile_definitions(HAVE_BSD_SYSCTL)
+endif()
+
+set(CMAKE_REQUIRED_LIBRARIES ${Iconv_LIBRARIES})
+set(CMAKE_REQUIRED_INCLUDES ${Iconv_INCLUDE_DIRS})
+
+check_c_source_compiles("
+#include <iconv.h>
+
+extern size_t iconv(iconv_t cd,
+               char **inbuf, size_t *inbytesleft,
+               char **outbuf, size_t *outbytesleft);
+
+int main(void)
+{
+       return 0;
+}"
+HAVE_NEW_ICONV)
+if(HAVE_NEW_ICONV)
+       set(HAVE_OLD_ICONV 0)
+else()
+       set(HAVE_OLD_ICONV 1)
+endif()
+
+check_c_source_runs("
+#include <iconv.h>
+#if ${HAVE_OLD_ICONV}
+typedef const char *iconv_ibp;
+#else
+typedef char *iconv_ibp;
+#endif
+
+int main(void)
+{
+       int v;
+       iconv_t conv;
+       char in[] = \"a\";
+       iconv_ibp pin = in;
+       char out[20] = \"\";
+       char *pout = out;
+       size_t isz = sizeof(in);
+       size_t osz = sizeof(out);
+
+       conv = iconv_open(\"UTF-16\", \"UTF-8\");
+       iconv(conv, &pin, &isz, &pout, &osz);
+       iconv_close(conv);
+       v = (unsigned char)(out[0]) + (unsigned char)(out[1]);
+       return v != 0xfe + 0xff;
+}"
+ICONV_DOESNOT_OMIT_BOM)
+if(NOT ICONV_DOESNOT_OMIT_BOM)
+       add_compile_definitions(ICONV_OMITS_BOM)
+endif()
+
+unset(CMAKE_REQUIRED_LIBRARIES)
+unset(CMAKE_REQUIRED_INCLUDES)
+
+
+#programs
+set(PROGRAMS_BUILT
+       git git-bugreport git-credential-store git-daemon git-fast-import git-http-backend git-sh-i18n--envsubst
+       git-shell git-remote-testsvn)
+
+if(NO_UNIX_SOCKETS)
+       list(APPEND excluded_progs git-credential-cache git-credential-cache--daemon)
+else()
+       list(APPEND PROGRAMS_BUILT git-credential-cache git-credential-cache--daemon)
+endif()
+
+if(NOT CURL_FOUND)
+       list(APPEND excluded_progs git-http-fetch git-http-push)
+       add_compile_definitions(NO_CURL)
+       message(WARNING "git-http-push and git-http-fetch will not be built")
+else()
+       list(APPEND PROGRAMS_BUILT git-http-fetch git-http-push git-imap-send git-remote-http)
+       if(CURL_VERSION_STRING VERSION_GREATER_EQUAL 7.34.0)
+               add_compile_definitions(USE_CURL_FOR_IMAP_SEND)
+       endif()
+endif()
+
+if(NOT EXPAT_FOUND)
+       list(APPEND excluded_progs git-http-push)
+       add_compile_definitions(NO_EXPAT)
+else()
+       list(APPEND PROGRAMS_BUILT git-http-push)
+       if(EXPAT_VERSION_STRING VERSION_LESS_EQUAL 1.2)
+               add_compile_definitions(EXPAT_NEEDS_XMLPARSE_H)
+       endif()
+endif()
+
+list(REMOVE_DUPLICATES excluded_progs)
+list(REMOVE_DUPLICATES PROGRAMS_BUILT)
+
+
+foreach(p ${excluded_progs})
+       list(APPEND EXCLUSION_PROGS --exclude-program ${p} )
+endforeach()
+
+#for comparing null values
+list(APPEND EXCLUSION_PROGS empty)
+set(EXCLUSION_PROGS_CACHE ${EXCLUSION_PROGS} CACHE STRING "Programs not built" FORCE)
+
+if(NOT EXISTS ${CMAKE_BINARY_DIR}/command-list.h OR NOT EXCLUSION_PROGS_CACHE STREQUAL EXCLUSION_PROGS)
+       list(REMOVE_ITEM EXCLUSION_PROGS empty)
+       message("Generating command-list.h")
+       execute_process(COMMAND ${SH_EXE} ${CMAKE_SOURCE_DIR}/generate-cmdlist.sh ${EXCLUSION_PROGS} command-list.txt
+                       WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+                       OUTPUT_FILE ${CMAKE_BINARY_DIR}/command-list.h)
+endif()
+
+if(NOT EXISTS ${CMAKE_BINARY_DIR}/config-list.h)
+       message("Generating config-list.h")
+       execute_process(COMMAND ${SH_EXE} ${CMAKE_SOURCE_DIR}/generate-configlist.sh
+                       WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+                       OUTPUT_FILE ${CMAKE_BINARY_DIR}/config-list.h)
+endif()
+
+include_directories(${CMAKE_BINARY_DIR})
+
+#build
+#libgit
+parse_makefile_for_sources(libgit_SOURCES "LIB_OBJS")
+
+list(TRANSFORM libgit_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/")
+list(TRANSFORM compat_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/")
+add_library(libgit ${libgit_SOURCES} ${compat_SOURCES})
+
+#libxdiff
+parse_makefile_for_sources(libxdiff_SOURCES "XDIFF_OBJS")
+
+list(TRANSFORM libxdiff_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/")
+add_library(xdiff STATIC ${libxdiff_SOURCES})
+
+#libvcs-svn
+parse_makefile_for_sources(libvcs-svn_SOURCES "VCSSVN_OBJS")
+
+list(TRANSFORM libvcs-svn_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/")
+add_library(vcs-svn STATIC ${libvcs-svn_SOURCES})
+
+if(WIN32)
+       if(NOT MSVC)#use windres when compiling with gcc and clang
+               add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/git.res
+                               COMMAND ${WINDRES_EXE} -O coff -DMAJOR=${PROJECT_VERSION_MAJOR} -DMINOR=${PROJECT_VERSION_MINOR}
+                                       -DMICRO=${PROJECT_VERSION_PATCH} -DPATCHLEVEL=0 -DGIT_VERSION="\\\"${PROJECT_VERSION}.GIT\\\""
+                                       -i ${CMAKE_SOURCE_DIR}/git.rc -o ${CMAKE_BINARY_DIR}/git.res
+                               WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+                               VERBATIM)
+       else()#MSVC use rc
+               add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/git.res
+                               COMMAND ${CMAKE_RC_COMPILER} /d MAJOR=${PROJECT_VERSION_MAJOR} /d MINOR=${PROJECT_VERSION_MINOR}
+                                       /d MICRO=${PROJECT_VERSION_PATCH} /d PATCHLEVEL=0 /d GIT_VERSION="${PROJECT_VERSION}.GIT"
+                                       /fo ${CMAKE_BINARY_DIR}/git.res ${CMAKE_SOURCE_DIR}/git.rc
+                               WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+                               VERBATIM)
+       endif()
+       add_custom_target(git-rc DEPENDS ${CMAKE_BINARY_DIR}/git.res)
+endif()
+
+#link all required libraries to common-main
+add_library(common-main OBJECT ${CMAKE_SOURCE_DIR}/common-main.c)
+
+target_link_libraries(common-main libgit xdiff ${ZLIB_LIBRARIES})
+if(Intl_FOUND)
+       target_link_libraries(common-main ${Intl_LIBRARIES})
+endif()
+if(Iconv_FOUND)
+       target_link_libraries(common-main ${Iconv_LIBRARIES})
+endif()
+if(WIN32)
+       target_link_libraries(common-main ws2_32 ntdll ${CMAKE_BINARY_DIR}/git.res)
+       add_dependencies(common-main git-rc)
+       if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
+               target_link_options(common-main PUBLIC -municode -Wl,--nxcompat -Wl,--dynamicbase -Wl,--pic-executable,-e,mainCRTStartup)
+       elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+               target_link_options(common-main PUBLIC -municode -Wl,-nxcompat -Wl,-dynamicbase -Wl,-entry:wmainCRTStartup -Wl,invalidcontinue.obj)
+       elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
+               target_link_options(common-main PUBLIC /IGNORE:4217 /IGNORE:4049 /NOLOGO /ENTRY:wmainCRTStartup /SUBSYSTEM:CONSOLE invalidcontinue.obj)
+       endif()
+elseif(UNIX)
+       target_link_libraries(common-main pthread rt)
+endif()
+
+#git
+parse_makefile_for_sources(git_SOURCES "BUILTIN_OBJS")
+
+list(TRANSFORM git_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/")
+add_executable(git ${CMAKE_SOURCE_DIR}/git.c ${git_SOURCES})
+target_link_libraries(git common-main)
+
+add_executable(git-bugreport ${CMAKE_SOURCE_DIR}/bugreport.c)
+target_link_libraries(git-bugreport common-main)
+
+add_executable(git-credential-store ${CMAKE_SOURCE_DIR}/credential-store.c)
+target_link_libraries(git-credential-store common-main)
+
+add_executable(git-daemon ${CMAKE_SOURCE_DIR}/daemon.c)
+target_link_libraries(git-daemon common-main)
+
+add_executable(git-fast-import ${CMAKE_SOURCE_DIR}/fast-import.c)
+target_link_libraries(git-fast-import common-main)
+
+add_executable(git-http-backend ${CMAKE_SOURCE_DIR}/http-backend.c)
+target_link_libraries(git-http-backend common-main)
+
+add_executable(git-sh-i18n--envsubst ${CMAKE_SOURCE_DIR}/sh-i18n--envsubst.c)
+target_link_libraries(git-sh-i18n--envsubst common-main)
+
+add_executable(git-shell ${CMAKE_SOURCE_DIR}/shell.c)
+target_link_libraries(git-shell common-main)
+
+if(CURL_FOUND)
+       add_library(http_obj OBJECT ${CMAKE_SOURCE_DIR}/http.c)
+
+       add_executable(git-imap-send ${CMAKE_SOURCE_DIR}/imap-send.c)
+       target_link_libraries(git-imap-send http_obj common-main ${CURL_LIBRARIES})
+
+       add_executable(git-http-fetch ${CMAKE_SOURCE_DIR}/http-walker.c ${CMAKE_SOURCE_DIR}/http-fetch.c)
+       target_link_libraries(git-http-fetch http_obj common-main ${CURL_LIBRARIES})
+
+       add_executable(git-remote-http ${CMAKE_SOURCE_DIR}/http-walker.c ${CMAKE_SOURCE_DIR}/remote-curl.c)
+       target_link_libraries(git-remote-http http_obj common-main ${CURL_LIBRARIES} )
+
+       if(EXPAT_FOUND)
+               add_executable(git-http-push ${CMAKE_SOURCE_DIR}/http-push.c)
+               target_link_libraries(git-http-push http_obj common-main ${CURL_LIBRARIES} ${EXPAT_LIBRARIES})
+       endif()
+endif()
+
+add_executable(git-remote-testsvn ${CMAKE_SOURCE_DIR}/remote-testsvn.c)
+target_link_libraries(git-remote-testsvn common-main vcs-svn)
+
+if(NOT NO_UNIX_SOCKETS)
+       add_executable(git-credential-cache ${CMAKE_SOURCE_DIR}/credential-cache.c)
+       target_link_libraries(git-credential-cache common-main)
+
+       add_executable(git-credential-cache--daemon ${CMAKE_SOURCE_DIR}/credential-cache--daemon.c)
+       target_link_libraries(git-credential-cache--daemon common-main)
+endif()
+
+
+set(git_builtin_extra
+       cherry cherry-pick format-patch fsck-objects
+       init merge-subtree restore show
+       stage status switch whatchanged)
+
+#Creating hardlinks
+foreach(s ${git_SOURCES} ${git_builtin_extra})
+       string(REPLACE "${CMAKE_SOURCE_DIR}/builtin/" "" s ${s})
+       string(REPLACE ".c" "" s ${s})
+       file(APPEND ${CMAKE_BINARY_DIR}/CreateLinks.cmake "file(CREATE_LINK git${EXE_EXTENSION} git-${s}${EXE_EXTENSION})\n")
+       list(APPEND git_links ${CMAKE_BINARY_DIR}/git-${s}${EXE_EXTENSION})
+endforeach()
+
+if(CURL_FOUND)
+       set(remote_exes
+               git-remote-https git-remote-ftp git-remote-ftps)
+       foreach(s ${remote_exes})
+               file(APPEND ${CMAKE_BINARY_DIR}/CreateLinks.cmake "file(CREATE_LINK git-remote-http${EXE_EXTENSION} ${s}${EXE_EXTENSION})\n")
+               list(APPEND git_http_links ${CMAKE_BINARY_DIR}/${s}${EXE_EXTENSION})
+       endforeach()
+endif()
+
+add_custom_command(OUTPUT ${git_links} ${git_http_links}
+               COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/CreateLinks.cmake
+               DEPENDS git git-remote-http)
+add_custom_target(git-links ALL DEPENDS ${git_links} ${git_http_links})
+
+
+#creating required scripts
+set(SHELL_PATH /bin/sh)
+set(PERL_PATH /usr/bin/perl)
+set(LOCALEDIR ${FALLBACK_RUNTIME_PREFIX}/share/locale)
+set(GITWEBDIR ${FALLBACK_RUNTIME_PREFIX}/share/locale)
+set(INSTLIBDIR ${FALLBACK_RUNTIME_PREFIX}/share/perl5)
+
+#shell scripts
+parse_makefile_for_scripts(git_sh_scripts "SCRIPT_SH" ".sh")
+parse_makefile_for_scripts(git_shlib_scripts "SCRIPT_LIB" "")
+set(git_shell_scripts
+       ${git_sh_scripts} ${git_shlib_scripts} git-instaweb)
+
+foreach(script ${git_shell_scripts})
+       file(STRINGS ${CMAKE_SOURCE_DIR}/${script}.sh content NEWLINE_CONSUME)
+       string(REPLACE "@SHELL_PATH@" "${SHELL_PATH}" content "${content}")
+       string(REPLACE "@@DIFF@@" "diff" content "${content}")
+       string(REPLACE "@LOCALEDIR@" "${LOCALEDIR}" content "${content}")
+       string(REPLACE "@GITWEBDIR@" "${GITWEBDIR}" content "${content}")
+       string(REPLACE "@@NO_CURL@@" "" content "${content}")
+       string(REPLACE "@@USE_GETTEXT_SCHEME@@" "" content "${content}")
+       string(REPLACE "# @@BROKEN_PATH_FIX@@" "" content "${content}")
+       string(REPLACE "@@PERL@@" "${PERL_PATH}" content "${content}")
+       string(REPLACE "@@SANE_TEXT_GREP@@" "-a" content "${content}")
+       string(REPLACE "@@PAGER_ENV@@" "LESS=FRX LV=-c" content "${content}")
+       file(WRITE ${CMAKE_BINARY_DIR}/${script} ${content})
+endforeach()
+
+#perl scripts
+parse_makefile_for_scripts(git_perl_scripts "SCRIPT_PERL" ".perl")
+
+#create perl header
+file(STRINGS ${CMAKE_SOURCE_DIR}/perl/header_templates/fixed_prefix.template.pl perl_header )
+string(REPLACE "@@PATHSEP@@" ":" perl_header "${perl_header}")
+string(REPLACE "@@INSTLIBDIR@@" "${INSTLIBDIR}" perl_header "${perl_header}")
+
+foreach(script ${git_perl_scripts})
+       file(STRINGS ${CMAKE_SOURCE_DIR}/${script}.perl content NEWLINE_CONSUME)
+       string(REPLACE "#!/usr/bin/perl" "#!/usr/bin/perl\n${perl_header}\n" content "${content}")
+       string(REPLACE "@@GIT_VERSION@@" "${PROJECT_VERSION}" content "${content}")
+       file(WRITE ${CMAKE_BINARY_DIR}/${script} ${content})
+endforeach()
+
+#python script
+file(STRINGS ${CMAKE_SOURCE_DIR}/git-p4.py content NEWLINE_CONSUME)
+string(REPLACE "#!/usr/bin/env python" "#!/usr/bin/python" content "${content}")
+file(WRITE ${CMAKE_BINARY_DIR}/git-p4 ${content})
+
+#perl modules
+file(GLOB_RECURSE perl_modules "${CMAKE_SOURCE_DIR}/perl/*.pm")
+
+foreach(pm ${perl_modules})
+       string(REPLACE "${CMAKE_SOURCE_DIR}/perl/" "" file_path ${pm})
+       file(STRINGS ${pm} content NEWLINE_CONSUME)
+       string(REPLACE "@@LOCALEDIR@@" "${LOCALEDIR}" content "${content}")
+       string(REPLACE "@@NO_PERL_CPAN_FALLBACKS@@" "" content "${content}")
+       file(WRITE ${CMAKE_BINARY_DIR}/perl/build/lib/${file_path} ${content})
+#test-lib.sh requires perl/build/lib to be the build directory of perl modules
+endforeach()
+
+
+#templates
+file(GLOB templates "${CMAKE_SOURCE_DIR}/templates/*")
+list(TRANSFORM templates REPLACE "${CMAKE_SOURCE_DIR}/templates/" "")
+list(REMOVE_ITEM templates ".gitignore")
+list(REMOVE_ITEM templates "Makefile")
+list(REMOVE_ITEM templates "blt")# Prevents an error when reconfiguring for in source builds
+
+list(REMOVE_ITEM templates "branches--")
+file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/templates/blt/branches) #create branches
+
+#templates have @.*@ replacement so use configure_file instead
+foreach(tm ${templates})
+       string(REPLACE "--" "/" blt_tm ${tm})
+       string(REPLACE "this" "" blt_tm ${blt_tm})# for this--
+       configure_file(${CMAKE_SOURCE_DIR}/templates/${tm} ${CMAKE_BINARY_DIR}/templates/blt/${blt_tm} @ONLY)
+endforeach()
+
+
+#translations
+if(MSGFMT_EXE)
+       file(GLOB po_files "${CMAKE_SOURCE_DIR}/po/*.po")
+       list(TRANSFORM po_files REPLACE "${CMAKE_SOURCE_DIR}/po/" "")
+       list(TRANSFORM po_files REPLACE ".po" "")
+       foreach(po ${po_files})
+               file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/po/build/locale/${po}/LC_MESSAGES)
+               add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/po/build/locale/${po}/LC_MESSAGES/git.mo
+                               COMMAND ${MSGFMT_EXE} --check --statistics -o ${CMAKE_BINARY_DIR}/po/build/locale/${po}/LC_MESSAGES/git.mo ${CMAKE_SOURCE_DIR}/po/${po}.po)
+               list(APPEND po_gen ${CMAKE_BINARY_DIR}/po/build/locale/${po}/LC_MESSAGES/git.mo)
+       endforeach()
+       add_custom_target(po-gen ALL DEPENDS ${po_gen})
+endif()
+
+
+#to help with the install
+list(TRANSFORM git_shell_scripts PREPEND "${CMAKE_BINARY_DIR}/")
+list(TRANSFORM git_perl_scripts PREPEND "${CMAKE_BINARY_DIR}/")
+
+#install
+install(TARGETS git git-shell
+       RUNTIME DESTINATION bin)
+install(PROGRAMS ${CMAKE_BINARY_DIR}/git-cvsserver
+       DESTINATION bin)
+
+list(REMOVE_ITEM PROGRAMS_BUILT git git-shell)
+install(TARGETS ${PROGRAMS_BUILT}
+       RUNTIME DESTINATION libexec/git-core)
+
+set(bin_links
+       git-receive-pack git-upload-archive git-upload-pack)
+
+foreach(b ${bin_links})
+install(CODE "file(CREATE_LINK ${CMAKE_INSTALL_PREFIX}/bin/git${EXE_EXTENSION} ${CMAKE_INSTALL_PREFIX}/bin/${b}${EXE_EXTENSION})")
+endforeach()
+
+install(CODE "file(CREATE_LINK ${CMAKE_INSTALL_PREFIX}/bin/git${EXE_EXTENSION} ${CMAKE_INSTALL_PREFIX}/libexec/git-core/git${EXE_EXTENSION})")
+install(CODE "file(CREATE_LINK ${CMAKE_INSTALL_PREFIX}/bin/git-shell${EXE_EXTENSION} ${CMAKE_INSTALL_PREFIX}/libexec/git-core/git-shell${EXE_EXTENSION})")
+
+foreach(b ${git_links})
+       string(REPLACE "${CMAKE_BINARY_DIR}" "" b ${b})
+       install(CODE "file(CREATE_LINK ${CMAKE_INSTALL_PREFIX}/bin/git${EXE_EXTENSION} ${CMAKE_INSTALL_PREFIX}/libexec/git-core/${b}${EXE_EXTENSION})")
+endforeach()
+
+foreach(b ${git_http_links})
+       string(REPLACE "${CMAKE_BINARY_DIR}" "" b ${b})
+       install(CODE "file(CREATE_LINK  ${CMAKE_INSTALL_PREFIX}/libexec/git-core/git-remote-http${EXE_EXTENSION} ${CMAKE_INSTALL_PREFIX}/libexec/git-core/${b}${EXE_EXTENSION})")
+endforeach()
+
+install(PROGRAMS ${git_shell_scripts} ${git_perl_scripts} ${CMAKE_BINARY_DIR}/git-p4
+       DESTINATION libexec/git-core)
+
+install(DIRECTORY ${CMAKE_SOURCE_DIR}/mergetools DESTINATION libexec/git-core)
+install(DIRECTORY ${CMAKE_BINARY_DIR}/perl/build/lib/ DESTINATION share/perl5
+       FILES_MATCHING PATTERN "*.pm")
+install(DIRECTORY ${CMAKE_BINARY_DIR}/templates/blt/ DESTINATION share/git-core/templates)
+
+if(MSGFMT_EXE)
+       install(DIRECTORY ${CMAKE_BINARY_DIR}/po/build/locale DESTINATION share)
+endif()
+
+
+if(BUILD_TESTING)
+
+#tests-helpers
+add_executable(test-fake-ssh ${CMAKE_SOURCE_DIR}/t/helper/test-fake-ssh.c)
+target_link_libraries(test-fake-ssh common-main)
+
+add_executable(test-line-buffer ${CMAKE_SOURCE_DIR}/t/helper/test-line-buffer.c)
+target_link_libraries(test-line-buffer common-main vcs-svn)
+
+add_executable(test-svn-fe ${CMAKE_SOURCE_DIR}/t/helper/test-svn-fe.c)
+target_link_libraries(test-svn-fe common-main vcs-svn)
+
+#test-tool
+parse_makefile_for_sources(test-tool_SOURCES "TEST_BUILTINS_OBJS")
+
+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})
+target_link_libraries(test-tool common-main)
+
+set_target_properties(test-fake-ssh test-line-buffer test-svn-fe test-tool
+                       PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/t/helper)
+
+if(MSVC)
+       set_target_properties(test-fake-ssh test-line-buffer test-svn-fe test-tool
+                               PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/t/helper)
+       set_target_properties(test-fake-ssh test-line-buffer test-svn-fe test-tool
+                               PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/t/helper)
+endif()
+
+#wrapper scripts
+set(wrapper_scripts
+       git git-upload-pack git-receive-pack git-upload-archive git-shell git-remote-ext)
+
+set(wrapper_test_scripts
+       test-fake-ssh test-line-buffer test-svn-fe test-tool)
+
+
+foreach(script ${wrapper_scripts})
+       file(STRINGS ${CMAKE_SOURCE_DIR}/wrap-for-bin.sh content NEWLINE_CONSUME)
+       string(REPLACE "@@BUILD_DIR@@" "${CMAKE_BINARY_DIR}" content "${content}")
+       string(REPLACE "@@PROG@@" "${script}${EXE_EXTENSION}" content "${content}")
+       file(WRITE ${CMAKE_BINARY_DIR}/bin-wrappers/${script} ${content})
+endforeach()
+
+foreach(script ${wrapper_test_scripts})
+       file(STRINGS ${CMAKE_SOURCE_DIR}/wrap-for-bin.sh content NEWLINE_CONSUME)
+       string(REPLACE "@@BUILD_DIR@@" "${CMAKE_BINARY_DIR}" content "${content}")
+       string(REPLACE "@@PROG@@" "t/helper/${script}${EXE_EXTENSION}" content "${content}")
+       file(WRITE ${CMAKE_BINARY_DIR}/bin-wrappers/${script} ${content})
+endforeach()
+
+file(STRINGS ${CMAKE_SOURCE_DIR}/wrap-for-bin.sh content NEWLINE_CONSUME)
+string(REPLACE "@@BUILD_DIR@@" "${CMAKE_BINARY_DIR}" content "${content}")
+string(REPLACE "@@PROG@@" "git-cvsserver" content "${content}")
+file(WRITE ${CMAKE_BINARY_DIR}/bin-wrappers/git-cvsserver ${content})
+
+#options for configuring test options
+option(PERL_TESTS "Perform tests that use perl" ON)
+option(PYTHON_TESTS "Perform tests that use python" ON)
+
+#GIT-BUILD-OPTIONS
+set(TEST_SHELL_PATH ${SHELL_PATH})
+set(DIFF diff)
+set(PYTHON_PATH /usr/bin/python)
+set(TAR tar)
+set(NO_CURL )
+set(NO_EXPAT )
+set(USE_LIBPCRE1 )
+set(USE_LIBPCRE2 )
+set(NO_LIBPCRE1_JIT )
+set(NO_PERL )
+set(NO_PTHREADS )
+set(NO_PYTHON )
+set(PAGER_ENV "LESS=FRX LV=-c")
+set(DC_SHA1 YesPlease)
+set(RUNTIME_PREFIX true)
+set(NO_GETTEXT )
+
+if(NOT CURL_FOUND)
+       set(NO_CURL 1)
+endif()
+
+if(NOT EXPAT_FOUND)
+       set(NO_EXPAT 1)
+endif()
+
+if(NOT Intl_FOUND)
+       set(NO_GETTEXT 1)
+endif()
+
+if(NOT PERL_TESTS)
+       set(NO_PERL 1)
+endif()
+
+if(NOT PYTHON_TESTS)
+       set(NO_PYTHON 1)
+endif()
+
+file(WRITE ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "SHELL_PATH='${SHELL_PATH}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "TEST_SHELL_PATH='${TEST_SHELL_PATH}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "PERL_PATH='${PERL_PATH}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "DIFF='${DIFF}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "PYTHON_PATH='${PYTHON_PATH}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "TAR='${TAR}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_CURL='${NO_CURL}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_EXPAT='${NO_EXPAT}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "USE_LIBPCRE1='${USE_LIBPCRE1}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_LIBPCRE1_JIT='${NO_LIBPCRE1_JIT}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_PERL='${NO_PERL}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_PTHREADS='${NO_PTHREADS}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_UNIX_SOCKETS='${NO_UNIX_SOCKETS}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "PAGER_ENV='${PAGER_ENV}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "DC_SHA1='${DC_SHA1}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "X='${EXE_EXTENSION}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_GETTEXT='${NO_GETTEXT}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "RUNTIME_PREFIX='${RUNTIME_PREFIX}'\n")
+file(APPEND ${CMAKE_BINARY_DIR}/GIT-BUILD-OPTIONS "NO_PYTHON='${NO_PYTHON}'\n")
+
+#Make the tests work when building out of the source tree
+get_filename_component(CACHE_PATH ${CMAKE_CURRENT_LIST_DIR}/../../CMakeCache.txt ABSOLUTE)
+if(NOT ${CMAKE_BINARY_DIR}/CMakeCache.txt STREQUAL ${CACHE_PATH})
+       file(RELATIVE_PATH BUILD_DIR_RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}/CMakeCache.txt)
+       string(REPLACE "/CMakeCache.txt" "" BUILD_DIR_RELATIVE ${BUILD_DIR_RELATIVE})
+       #Setting the build directory in test-lib.sh before running tests
+       file(WRITE ${CMAKE_BINARY_DIR}/CTestCustom.cmake
+               "file(STRINGS ${CMAKE_SOURCE_DIR}/t/test-lib.sh GIT_BUILD_DIR_REPL REGEX \"GIT_BUILD_DIR=(.*)\")\n"
+               "file(STRINGS ${CMAKE_SOURCE_DIR}/t/test-lib.sh content NEWLINE_CONSUME)\n"
+               "string(REPLACE \"\${GIT_BUILD_DIR_REPL}\" \"GIT_BUILD_DIR=\\\"$TEST_DIRECTORY\\\"/../${BUILD_DIR_RELATIVE}\" content \"\${content}\")\n"
+               "file(WRITE ${CMAKE_SOURCE_DIR}/t/test-lib.sh \${content})")
+       #misc copies
+       file(COPY ${CMAKE_SOURCE_DIR}/t/chainlint.sed DESTINATION ${CMAKE_BINARY_DIR}/t/)
+       file(COPY ${CMAKE_SOURCE_DIR}/po/is.po DESTINATION ${CMAKE_BINARY_DIR}/po/)
+       file(COPY ${CMAKE_SOURCE_DIR}/mergetools/tkdiff DESTINATION ${CMAKE_BINARY_DIR}/mergetools/)
+       file(COPY ${CMAKE_SOURCE_DIR}/contrib/completion/git-prompt.sh DESTINATION ${CMAKE_BINARY_DIR}/contrib/completion/)
+       file(COPY ${CMAKE_SOURCE_DIR}/contrib/completion/git-completion.bash DESTINATION ${CMAKE_BINARY_DIR}/contrib/completion/)
+       file(COPY ${CMAKE_SOURCE_DIR}/contrib/svn-fe/svnrdump_sim.py DESTINATION ${CMAKE_BINARY_DIR}/contrib/svn-fe/)
+endif()
+
+file(GLOB test_scipts "${CMAKE_SOURCE_DIR}/t/t[0-9]*.sh")
+
+#test
+foreach(tsh ${test_scipts})
+       add_test(NAME ${tsh}
+               COMMAND ${SH_EXE} ${tsh}
+               WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/t)
+endforeach()
+
+endif()#BUILD_TESTING
index ee468ea3b041ca573eb412739443230211cc6043..9147fba3d5c34e617f94129b02459d4579595da8 100644 (file)
 #     When set to "1", do not include "DWIM" suggestions in git-checkout
 #     and git-switch completion (e.g., completing "foo" when "origin/foo"
 #     exists).
+#
+#   GIT_COMPLETION_SHOW_ALL
+#
+#     When set to "1" suggest all options, including options which are
+#     typically hidden (e.g. '--allow-empty' for 'git commit').
 
 case "$COMP_WORDBREAKS" in
 *:*) : great ;;
@@ -411,10 +416,17 @@ __gitcomp_builtin ()
        local options
        eval "options=\${$var-}"
 
+       local completion_helper
+       if [ "$GIT_COMPLETION_SHOW_ALL" = "1" ]; then
+               completion_helper="--git-completion-helper-all"
+       else
+               completion_helper="--git-completion-helper"
+       fi
+
        if [ -z "$options" ]; then
                # leading and trailing spaces are significant to make
                # option removal work correctly.
-               options=" $incl $(__git ${cmd/_/ } --git-completion-helper) " || return
+               options=" $incl $(__git ${cmd/_/ } $completion_helper) " || return
 
                for i in $excl; do
                        options="${options/ $i / }"
@@ -1712,8 +1724,8 @@ _git_diff ()
 }
 
 __git_mergetools_common="diffuse diffmerge ecmerge emerge kdiff3 meld opendiff
-                       tkdiff vimdiff gvimdiff xxdiff araxis p4merge bc
-                       codecompare smerge
+                       tkdiff vimdiff nvimdiff gvimdiff xxdiff araxis p4merge
+                       bc codecompare smerge
 "
 
 _git_difftool ()
@@ -2907,6 +2919,14 @@ _git_show ()
                __gitcomp "$__git_diff_submodule_formats" "" "${cur##--submodule=}"
                return
                ;;
+       --color-moved=*)
+               __gitcomp "$__git_color_moved_opts" "" "${cur##--color-moved=}"
+               return
+               ;;
+       --color-moved-ws=*)
+               __gitcomp "$__git_color_moved_ws_opts" "" "${cur##--color-moved-ws=}"
+               return
+               ;;
        --*)
                __gitcomp "--pretty= --format= --abbrev-commit --no-abbrev-commit
                        --oneline --show-signature --patch
index 352deda69dcfd009ff025615dff07dd0a5d015d1..0db02fe3c09528cdb2b26982b4b9cf60e7e94429 100644 (file)
@@ -139,12 +139,12 @@ OPTIONS
 
 -m <message>::
 --message=<message>::
-       This option is only valid for add, merge and pull (unsure).
+       This option is only valid for add, merge, pull, and split --rejoin.
        Specify <message> as the commit message for the merge commit.
 
 
-OPTIONS FOR add, merge, push, pull
-----------------------------------
+OPTIONS FOR add, merge, and pull
+--------------------------------
 --squash::
        This option is only valid for add, merge, and pull
        commands.
index 53d7accf949fef1882f051805570a4797e46de3f..57ff4b25c17e5479e9dc058fd723d44faa23877b 100755 (executable)
@@ -196,8 +196,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix' '
                cd "$subtree_test_count" &&
                git fetch ./"sub proj" master &&
                git subtree merge --prefix="sub dir" FETCH_HEAD &&
-               check_equal "$(last_commit_message)" \
-                       "Merge commit '\''$(git rev-parse FETCH_HEAD)'\'' into master"
+               check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
        )
 '
 
@@ -274,8 +273,7 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende
                cd "$test_count" &&
                git fetch ./subproj master &&
                git subtree merge --prefix=subdir/ FETCH_HEAD &&
-               check_equal "$(last_commit_message)" \
-                       "Merge commit '\''$(git rev-parse FETCH_HEAD)'\'' into master"
+               check_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
        )
 '
 
index fd669ed3b4278e9f999ed1ed33747a3e96f817e6..2ab7ea82eb0b4f7c62c553e1e65c16644983f7de 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -296,7 +296,7 @@ static const char *path_ok(const char *directory, struct hostinfo *hi)
        return NULL;            /* Fallthrough. Deny by default */
 }
 
-typedef int (*daemon_service_fn)(const struct argv_array *env);
+typedef int (*daemon_service_fn)(const struct strvec *env);
 struct daemon_service {
        const char *name;
        const char *config_name;
@@ -377,7 +377,7 @@ error_return:
 }
 
 static int run_service(const char *dir, struct daemon_service *service,
-                      struct hostinfo *hi, const struct argv_array *env)
+                      struct hostinfo *hi, const struct strvec *env)
 {
        const char *path;
        int enabled = service->enabled;
@@ -462,7 +462,7 @@ static void copy_to_log(int fd)
 
 static int run_service_command(struct child_process *cld)
 {
-       argv_array_push(&cld->args, ".");
+       strvec_push(&cld->args, ".");
        cld->git_cmd = 1;
        cld->err = -1;
        if (start_command(cld))
@@ -476,33 +476,33 @@ static int run_service_command(struct child_process *cld)
        return finish_command(cld);
 }
 
-static int upload_pack(const struct argv_array *env)
+static int upload_pack(const struct strvec *env)
 {
        struct child_process cld = CHILD_PROCESS_INIT;
-       argv_array_pushl(&cld.args, "upload-pack", "--strict", NULL);
-       argv_array_pushf(&cld.args, "--timeout=%u", timeout);
+       strvec_pushl(&cld.args, "upload-pack", "--strict", NULL);
+       strvec_pushf(&cld.args, "--timeout=%u", timeout);
 
-       argv_array_pushv(&cld.env_array, env->argv);
+       strvec_pushv(&cld.env_array, env->v);
 
        return run_service_command(&cld);
 }
 
-static int upload_archive(const struct argv_array *env)
+static int upload_archive(const struct strvec *env)
 {
        struct child_process cld = CHILD_PROCESS_INIT;
-       argv_array_push(&cld.args, "upload-archive");
+       strvec_push(&cld.args, "upload-archive");
 
-       argv_array_pushv(&cld.env_array, env->argv);
+       strvec_pushv(&cld.env_array, env->v);
 
        return run_service_command(&cld);
 }
 
-static int receive_pack(const struct argv_array *env)
+static int receive_pack(const struct strvec *env)
 {
        struct child_process cld = CHILD_PROCESS_INIT;
-       argv_array_push(&cld.args, "receive-pack");
+       strvec_push(&cld.args, "receive-pack");
 
-       argv_array_pushv(&cld.env_array, env->argv);
+       strvec_pushv(&cld.env_array, env->v);
 
        return run_service_command(&cld);
 }
@@ -633,7 +633,7 @@ static char *parse_host_arg(struct hostinfo *hi, char *extra_args, int buflen)
        return extra_args;
 }
 
-static void parse_extra_args(struct hostinfo *hi, struct argv_array *env,
+static void parse_extra_args(struct hostinfo *hi, struct strvec *env,
                             char *extra_args, int buflen)
 {
        const char *end = extra_args + buflen;
@@ -664,8 +664,8 @@ static void parse_extra_args(struct hostinfo *hi, struct argv_array *env,
 
        if (git_protocol.len > 0) {
                loginfo("Extended attribute \"protocol\": %s", git_protocol.buf);
-               argv_array_pushf(env, GIT_PROTOCOL_ENVIRONMENT "=%s",
-                                git_protocol.buf);
+               strvec_pushf(env, GIT_PROTOCOL_ENVIRONMENT "=%s",
+                            git_protocol.buf);
        }
        strbuf_release(&git_protocol);
 }
@@ -761,7 +761,7 @@ static int execute(void)
        int pktlen, len, i;
        char *addr = getenv("REMOTE_ADDR"), *port = getenv("REMOTE_PORT");
        struct hostinfo hi;
-       struct argv_array env = ARGV_ARRAY_INIT;
+       struct strvec env = STRVEC_INIT;
 
        hostinfo_init(&hi);
 
@@ -794,13 +794,13 @@ static int execute(void)
                         */
                        int rc = run_service(arg, s, &hi, &env);
                        hostinfo_clear(&hi);
-                       argv_array_clear(&env);
+                       strvec_clear(&env);
                        return rc;
                }
        }
 
        hostinfo_clear(&hi);
-       argv_array_clear(&env);
+       strvec_clear(&env);
        logerror("Protocol error: '%s'", line);
        return -1;
 }
@@ -893,7 +893,7 @@ static void check_dead_children(void)
                        cradle = &blanket->next;
 }
 
-static struct argv_array cld_argv = ARGV_ARRAY_INIT;
+static struct strvec cld_argv = STRVEC_INIT;
 static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)
 {
        struct child_process cld = CHILD_PROCESS_INIT;
@@ -913,21 +913,21 @@ static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)
                char buf[128] = "";
                struct sockaddr_in *sin_addr = (void *) addr;
                inet_ntop(addr->sa_family, &sin_addr->sin_addr, buf, sizeof(buf));
-               argv_array_pushf(&cld.env_array, "REMOTE_ADDR=%s", buf);
-               argv_array_pushf(&cld.env_array, "REMOTE_PORT=%d",
-                                ntohs(sin_addr->sin_port));
+               strvec_pushf(&cld.env_array, "REMOTE_ADDR=%s", buf);
+               strvec_pushf(&cld.env_array, "REMOTE_PORT=%d",
+                            ntohs(sin_addr->sin_port));
 #ifndef NO_IPV6
        } else if (addr->sa_family == AF_INET6) {
                char buf[128] = "";
                struct sockaddr_in6 *sin6_addr = (void *) addr;
                inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(buf));
-               argv_array_pushf(&cld.env_array, "REMOTE_ADDR=[%s]", buf);
-               argv_array_pushf(&cld.env_array, "REMOTE_PORT=%d",
-                                ntohs(sin6_addr->sin6_port));
+               strvec_pushf(&cld.env_array, "REMOTE_ADDR=[%s]", buf);
+               strvec_pushf(&cld.env_array, "REMOTE_PORT=%d",
+                            ntohs(sin6_addr->sin6_port));
 #endif
        }
 
-       cld.argv = cld_argv.argv;
+       cld.argv = cld_argv.v;
        cld.in = incoming;
        cld.out = dup(incoming);
 
@@ -1476,10 +1476,10 @@ int cmd_main(int argc, const char **argv)
                write_file(pid_file, "%"PRIuMAX, (uintmax_t) getpid());
 
        /* prepare argv for serving-processes */
-       argv_array_push(&cld_argv, argv[0]); /* git-daemon */
-       argv_array_push(&cld_argv, "--serve");
+       strvec_push(&cld_argv, argv[0]); /* git-daemon */
+       strvec_push(&cld_argv, "--serve");
        for (i = 1; i < argc; ++i)
-               argv_array_push(&cld_argv, argv[i]);
+               strvec_push(&cld_argv, argv[i]);
 
        return serve(&listen_addr, listen_port, cred);
 }
index 25fd2dee19c4a8f6408d768d44d8dc92aeaf0ed3..50521e2093fc581ce3cedc76b3036a61f31bef35 100644 (file)
@@ -219,7 +219,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
                                continue;
                        } else if (revs->diffopt.ita_invisible_in_index &&
                                   ce_intent_to_add(ce)) {
-                               diff_addremove(&revs->diffopt, '+', ce->ce_mode,
+                               newmode = ce_mode_from_stat(ce, st.st_mode);
+                               diff_addremove(&revs->diffopt, '+', newmode,
                                               &null_oid, 0, ce->name, 0);
                                continue;
                        }
diff --git a/diff.c b/diff.c
index d24aaa304780b7105618434d80a76627e588d280..e3a5ee3bee8c93f1480747891cadaa824f259262 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -20,7 +20,7 @@
 #include "hashmap.h"
 #include "ll-merge.h"
 #include "string-list.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "graph.h"
 #include "packfile.h"
 #include "parse-options.h"
@@ -4192,14 +4192,14 @@ static struct diff_tempfile *prepare_temp_file(struct repository *r,
 }
 
 static void add_external_diff_name(struct repository *r,
-                                  struct argv_array *argv,
+                                  struct strvec *argv,
                                   const char *name,
                                   struct diff_filespec *df)
 {
        struct diff_tempfile *temp = prepare_temp_file(r, name, df);
-       argv_array_push(argv, temp->name);
-       argv_array_push(argv, temp->hex);
-       argv_array_push(argv, temp->mode);
+       strvec_push(argv, temp->name);
+       strvec_push(argv, temp->hex);
+       strvec_push(argv, temp->mode);
 }
 
 /* An external diff command takes:
@@ -4216,12 +4216,12 @@ static void run_external_diff(const char *pgm,
                              const char *xfrm_msg,
                              struct diff_options *o)
 {
-       struct argv_array argv = ARGV_ARRAY_INIT;
-       struct argv_array env = ARGV_ARRAY_INIT;
+       struct strvec argv = STRVEC_INIT;
+       struct strvec env = STRVEC_INIT;
        struct diff_queue_struct *q = &diff_queued_diff;
 
-       argv_array_push(&argv, pgm);
-       argv_array_push(&argv, name);
+       strvec_push(&argv, pgm);
+       strvec_push(&argv, name);
 
        if (one && two) {
                add_external_diff_name(o->repo, &argv, name, one);
@@ -4229,22 +4229,22 @@ static void run_external_diff(const char *pgm,
                        add_external_diff_name(o->repo, &argv, name, two);
                else {
                        add_external_diff_name(o->repo, &argv, other, two);
-                       argv_array_push(&argv, other);
-                       argv_array_push(&argv, xfrm_msg);
+                       strvec_push(&argv, other);
+                       strvec_push(&argv, xfrm_msg);
                }
        }
 
-       argv_array_pushf(&env, "GIT_DIFF_PATH_COUNTER=%d", ++o->diff_path_counter);
-       argv_array_pushf(&env, "GIT_DIFF_PATH_TOTAL=%d", q->nr);
+       strvec_pushf(&env, "GIT_DIFF_PATH_COUNTER=%d", ++o->diff_path_counter);
+       strvec_pushf(&env, "GIT_DIFF_PATH_TOTAL=%d", q->nr);
 
        diff_free_filespec_data(one);
        diff_free_filespec_data(two);
-       if (run_command_v_opt_cd_env(argv.argv, RUN_USING_SHELL, NULL, env.argv))
+       if (run_command_v_opt_cd_env(argv.v, RUN_USING_SHELL, NULL, env.v))
                die(_("external diff died, stopping at %s"), name);
 
        remove_tempfile();
-       argv_array_clear(&argv);
-       argv_array_clear(&env);
+       strvec_clear(&argv);
+       strvec_clear(&env);
 }
 
 static int similarity_index(struct diff_filepair *p)
@@ -4319,7 +4319,10 @@ static void fill_metainfo(struct strbuf *msg,
        }
        if (one && two && !oideq(&one->oid, &two->oid)) {
                const unsigned hexsz = the_hash_algo->hexsz;
-               int abbrev = o->flags.full_index ? hexsz : DEFAULT_ABBREV;
+               int abbrev = o->abbrev ? o->abbrev : DEFAULT_ABBREV;
+
+               if (o->flags.full_index)
+                       abbrev = hexsz;
 
                if (o->flags.binary) {
                        mmfile_t mf;
@@ -6044,6 +6047,8 @@ static void patch_id_consume(void *priv, char *line, unsigned long len)
        struct patch_id_t *data = priv;
        int new_len;
 
+       if (len > 12 && starts_with(line, "\\ "))
+               return;
        new_len = remove_space(line, len);
 
        the_hash_algo->update_fn(data->ctx, line, new_len);
diff --git a/diff.h b/diff.h
index 9443dc1b0039026ba6c32efd3e445fa61a0860f5..e0c0af6286bbab24fde5174282c66a122737c392 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -431,11 +431,11 @@ struct combine_diff_path *diff_tree_paths(
        struct combine_diff_path *p, const struct object_id *oid,
        const struct object_id **parents_oid, int nparent,
        struct strbuf *base, struct diff_options *opt);
-int diff_tree_oid(const struct object_id *old_oid,
-                 const struct object_id *new_oid,
-                 const char *base, struct diff_options *opt);
-int diff_root_tree_oid(const struct object_id *new_oid, const char *base,
-                      struct diff_options *opt);
+void diff_tree_oid(const struct object_id *old_oid,
+                  const struct object_id *new_oid,
+                  const char *base, struct diff_options *opt);
+void diff_root_tree_oid(const struct object_id *new_oid, const char *base,
+                       struct diff_options *opt);
 
 struct combine_diff_path {
        struct combine_diff_path *next;
diff --git a/dir.c b/dir.c
index 1045cc9c6f58702aba6e9036a8bce91a431c108a..3018a657b059868c5a3a739d0a039311eedda5b9 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -54,6 +54,11 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
 static int resolve_dtype(int dtype, struct index_state *istate,
                         const char *path, int len);
 
+void dir_init(struct dir_struct *dir)
+{
+       memset(dir, 0, sizeof(*dir));
+}
+
 int count_slashes(const char *s)
 {
        int cnt = 0;
@@ -916,6 +921,8 @@ void clear_pattern_list(struct pattern_list *pl)
                free(pl->patterns[i]);
        free(pl->patterns);
        free(pl->filebuf);
+       hashmap_free_entries(&pl->recursive_hashmap, struct pattern_entry, ent);
+       hashmap_free_entries(&pl->parent_hashmap, struct pattern_entry, ent);
 
        memset(pl, 0, sizeof(*pl));
 }
@@ -1792,9 +1799,12 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
                nested_repo = is_nonbare_repository_dir(&sb);
                strbuf_release(&sb);
        }
-       if (nested_repo)
-               return ((dir->flags & DIR_SKIP_NESTED_GIT) ? path_none :
-                       (excluded ? path_excluded : path_untracked));
+       if (nested_repo) {
+               if ((dir->flags & DIR_SKIP_NESTED_GIT) ||
+                   (matches_how == MATCHED_RECURSIVELY_LEADING_PATHSPEC))
+                       return path_none;
+               return excluded ? path_excluded : path_untracked;
+       }
 
        if (!(dir->flags & DIR_SHOW_OTHER_DIRECTORIES)) {
                if (excluded &&
@@ -2209,13 +2219,13 @@ static enum path_treatment treat_path(struct dir_struct *dir,
                                       baselen, excluded, pathspec);
        case DT_REG:
        case DT_LNK:
-               if (excluded)
-                       return path_excluded;
                if (pathspec &&
                    !match_pathspec(istate, pathspec, path->buf, path->len,
                                    0 /* prefix */, NULL /* seen */,
                                    0 /* is_dir */))
                        return path_none;
+               if (excluded)
+                       return path_excluded;
                return path_untracked;
        }
 }
@@ -3009,10 +3019,10 @@ int remove_path(const char *name)
 }
 
 /*
- * Frees memory within dir which was allocated for exclude lists and
- * the exclude_stack.  Does not free dir itself.
+ * Frees memory within dir which was allocated, and resets fields for further
+ * use.  Does not free dir itself.
  */
-void clear_directory(struct dir_struct *dir)
+void dir_clear(struct dir_struct *dir)
 {
        int i, j;
        struct exclude_list_group *group;
@@ -3030,6 +3040,13 @@ void clear_directory(struct dir_struct *dir)
                free(group->pl);
        }
 
+       for (i = 0; i < dir->ignored_nr; i++)
+               free(dir->ignored[i]);
+       for (i = 0; i < dir->nr; i++)
+               free(dir->entries[i]);
+       free(dir->ignored);
+       free(dir->entries);
+
        stk = dir->exclude_stack;
        while (stk) {
                struct exclude_stack *prev = stk->prev;
@@ -3037,6 +3054,8 @@ void clear_directory(struct dir_struct *dir)
                stk = prev;
        }
        strbuf_release(&dir->basebuf);
+
+       dir_init(dir);
 }
 
 struct ondisk_untracked_cache {
diff --git a/dir.h b/dir.h
index 5855c065a610b794b3777405bba6f343230b7ea2..a3c40dec5165425ec00181a152b1ddac37dba43d 100644 (file)
--- a/dir.h
+++ b/dir.h
  * CE_SKIP_WORKTREE marked. If you want to exclude files, make sure you have
  * loaded the index first.
  *
- * - Prepare `struct dir_struct dir` and clear it with `memset(&dir, 0,
- * sizeof(dir))`.
+ * - Prepare `struct dir_struct dir` using `dir_init()` function.
  *
  * - To add single exclude pattern, call `add_pattern_list()` and then
  *   `add_pattern()`.
  *
  * - To add patterns from a file (e.g. `.git/info/exclude`), call
- *   `add_patterns_from_file()` , and/or set `dir.exclude_per_dir`.  A
- *   short-hand function `setup_standard_excludes()` can be used to set
- *   up the standard set of exclude settings.
+ *   `add_patterns_from_file()` , and/or set `dir.exclude_per_dir`.
  *
- * - Set options described in the Data Structure section above.
+ * - A short-hand function `setup_standard_excludes()` can be used to set
+ *   up the standard set of exclude settings, instead of manually calling
+ *   the add_pattern*() family of functions.
  *
- * - Call `read_directory()`.
+ * - Call `fill_directory()`.
  *
- * - Use `dir.entries[]`.
+ * - Use `dir.entries[]` and `dir.ignored[]`.
  *
- * - Call `clear_directory()` when none of the contained elements are no longer in use.
+ * - Call `dir_clear()` when the contained elements are no longer in use.
  *
  */
 
@@ -362,6 +361,8 @@ int match_pathspec(const struct index_state *istate,
 int report_path_error(const char *ps_matched, const struct pathspec *pathspec);
 int within_depth(const char *name, int namelen, int depth, int max_depth);
 
+void dir_init(struct dir_struct *dir);
+
 int fill_directory(struct dir_struct *dir,
                   struct index_state *istate,
                   const struct pathspec *pathspec);
@@ -428,7 +429,7 @@ void parse_path_pattern(const char **string, int *patternlen, unsigned *flags, i
 void add_pattern(const char *string, const char *base,
                 int baselen, struct pattern_list *pl, int srcpos);
 void clear_pattern_list(struct pattern_list *pl);
-void clear_directory(struct dir_struct *dir);
+void dir_clear(struct dir_struct *dir);
 
 int repo_file_exists(struct repository *repo, const char *path);
 int file_exists(const char *);
index 91989ee8a116aa44502a2c60dfbd02ba4528a34f..6303ae0ab0d52b7b54a00bd9bf687a91aac998fd 100644 (file)
--- a/editor.c
+++ b/editor.c
@@ -40,7 +40,7 @@ const char *git_sequence_editor(void)
        const char *editor = getenv("GIT_SEQUENCE_EDITOR");
 
        if (!editor)
-               git_config_get_string_const("sequence.editor", &editor);
+               git_config_get_string_tmp("sequence.editor", &editor);
        if (!editor)
                editor = git_editor();
 
diff --git a/entry.c b/entry.c
index 449bd32dee555d9a52481e30226cd4450e80409e..a0532f1f00007be7c9b675a54a7e8c48c000d638 100644 (file)
--- a/entry.c
+++ b/entry.c
@@ -510,8 +510,6 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state,
                        /* If it is a gitlink, leave it alone! */
                        if (S_ISGITLINK(ce->ce_mode))
                                return 0;
-                       if (!state->force)
-                               return error("%s is a directory", path.buf);
                        remove_subtree(&path);
                } else if (unlink(path.buf))
                        return error_errno("unable to unlink old '%s'", path.buf);
index aaca0e91ac8f4a3043dfbe963b33a376e72020fd..bb518c61cd259caf74f65fc8a080096b54168e48 100644 (file)
@@ -14,7 +14,7 @@
 #include "refs.h"
 #include "fmt-merge-msg.h"
 #include "commit.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "object-store.h"
 #include "chdir-notify.h"
 #include "shallow.h"
@@ -35,8 +35,8 @@ int repository_format_precious_objects;
 int repository_format_worktree_config;
 const char *git_commit_encoding;
 const char *git_log_output_encoding;
-const char *apply_default_whitespace;
-const char *apply_default_ignorewhitespace;
+char *apply_default_whitespace;
+char *apply_default_ignorewhitespace;
 const char *git_attributes_file;
 const char *git_hooks_path;
 int zlib_compression_level = Z_BEST_SPEED;
@@ -156,15 +156,15 @@ static char *expand_namespace(const char *raw_namespace)
  * Wrapper of getenv() that returns a strdup value. This value is kept
  * in argv to be freed later.
  */
-static const char *getenv_safe(struct argv_array *argv, const char *name)
+static const char *getenv_safe(struct strvec *argv, const char *name)
 {
        const char *value = getenv(name);
 
        if (!value)
                return NULL;
 
-       argv_array_push(argv, value);
-       return argv->argv[argv->argc - 1];
+       strvec_push(argv, value);
+       return argv->v[argv->nr - 1];
 }
 
 void setup_git_env(const char *git_dir)
@@ -172,7 +172,7 @@ void setup_git_env(const char *git_dir)
        const char *shallow_file;
        const char *replace_ref_base;
        struct set_gitdir_args args = { NULL };
-       struct argv_array to_free = ARGV_ARRAY_INIT;
+       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);
@@ -180,7 +180,7 @@ void setup_git_env(const char *git_dir)
        args.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT);
        args.alternate_db = getenv_safe(&to_free, ALTERNATE_DB_ENVIRONMENT);
        repo_set_gitdir(the_repository, git_dir, &args);
-       argv_array_clear(&to_free);
+       strvec_clear(&to_free);
 
        if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
                read_replace_refs = 0;
index 7deeab30397cf2edbee622717acd94de87256c8e..eeb2ee52b83441fd51bd79cea8bf13682bcd522e 100644 (file)
@@ -1,7 +1,7 @@
 #include "cache.h"
 #include "exec-cmd.h"
 #include "quote.h"
-#include "argv-array.h"
+#include "strvec.h"
 
 #if defined(RUNTIME_PREFIX)
 
@@ -320,26 +320,26 @@ void setup_path(void)
        strbuf_release(&new_path);
 }
 
-const char **prepare_git_cmd(struct argv_array *out, const char **argv)
+const char **prepare_git_cmd(struct strvec *out, const char **argv)
 {
-       argv_array_push(out, "git");
-       argv_array_pushv(out, argv);
-       return out->argv;
+       strvec_push(out, "git");
+       strvec_pushv(out, argv);
+       return out->v;
 }
 
 int execv_git_cmd(const char **argv)
 {
-       struct argv_array nargv = ARGV_ARRAY_INIT;
+       struct strvec nargv = STRVEC_INIT;
 
        prepare_git_cmd(&nargv, argv);
-       trace_argv_printf(nargv.argv, "trace: exec:");
+       trace_argv_printf(nargv.v, "trace: exec:");
 
        /* execvp() can only ever return if it fails */
-       sane_execvp("git", (char **)nargv.argv);
+       sane_execvp("git", (char **)nargv.v);
 
        trace_printf("trace: exec failed: %s\n", strerror(errno));
 
-       argv_array_clear(&nargv);
+       strvec_clear(&nargv);
        return -1;
 }
 
index 8cd1df28d3f11d165bc91fc34c90fc94802c9f61..330b41d54dec525326a0b864887ed089753c81c3 100644 (file)
@@ -1,13 +1,13 @@
 #ifndef GIT_EXEC_CMD_H
 #define GIT_EXEC_CMD_H
 
-struct argv_array;
+struct strvec;
 
 void git_set_exec_path(const char *exec_path);
 void git_resolve_executable_dir(const char *path);
 const char *git_exec_path(void);
 void setup_path(void);
-const char **prepare_git_cmd(struct argv_array *out, const char **argv);
+const char **prepare_git_cmd(struct strvec *out, const char **argv);
 int execv_git_cmd(const char **argv); /* NULL terminated */
 LAST_ARG_MUST_BE_NULL
 int execl_git_cmd(const char *cmd, ...);
index 0dfa14dc8c3c07bfb8f19275d2366a5f63576212..c45fe7474c6b83f5591554e994fb30407cdc5c8a 100644 (file)
@@ -526,14 +526,6 @@ static unsigned int hc_str(const char *s, size_t len)
        return r;
 }
 
-static char *pool_strdup(const char *s)
-{
-       size_t len = strlen(s) + 1;
-       char *r = mem_pool_alloc(&fi_mem_pool, len);
-       memcpy(r, s, len);
-       return r;
-}
-
 static void insert_mark(struct mark_set *s, uintmax_t idnum, struct object_entry *oe)
 {
        while ((idnum >> s->shift) >= 1024) {
@@ -615,7 +607,7 @@ static struct branch *new_branch(const char *name)
                die("Branch name doesn't conform to GIT standards: %s", name);
 
        b = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct branch));
-       b->name = pool_strdup(name);
+       b->name = mem_pool_strdup(&fi_mem_pool, name);
        b->table_next_branch = branch_table[hc];
        b->branch_tree.versions[0].mode = S_IFDIR;
        b->branch_tree.versions[1].mode = S_IFDIR;
@@ -843,9 +835,9 @@ static int loosen_small_pack(const struct packed_git *p)
        unpack.in = p->pack_fd;
        unpack.git_cmd = 1;
        unpack.stdout_to_stderr = 1;
-       argv_array_push(&unpack.args, "unpack-objects");
+       strvec_push(&unpack.args, "unpack-objects");
        if (!show_stats)
-               argv_array_push(&unpack.args, "-q");
+               strvec_push(&unpack.args, "-q");
 
        return run_command(&unpack);
 }
@@ -2806,7 +2798,7 @@ static void parse_new_tag(const char *arg)
 
        t = mem_pool_alloc(&fi_mem_pool, sizeof(struct tag));
        memset(t, 0, sizeof(struct tag));
-       t->name = pool_strdup(arg);
+       t->name = mem_pool_strdup(&fi_mem_pool, arg);
        if (last_tag)
                last_tag->next_tag = t;
        else
index 80fb3bd89987671c1c696c72b84cb25e946882b9..d467edc24edeabd9f819003a8ddd3d1a6d497c47 100644 (file)
@@ -835,30 +835,30 @@ static int get_pack(struct fetch_pack_args *args,
        }
 
        if (alternate_shallow_file) {
-               argv_array_push(&cmd.args, "--shallow-file");
-               argv_array_push(&cmd.args, alternate_shallow_file);
+               strvec_push(&cmd.args, "--shallow-file");
+               strvec_push(&cmd.args, alternate_shallow_file);
        }
 
        if (do_keep || args->from_promisor) {
                if (pack_lockfiles)
                        cmd.out = -1;
                cmd_name = "index-pack";
-               argv_array_push(&cmd.args, cmd_name);
-               argv_array_push(&cmd.args, "--stdin");
+               strvec_push(&cmd.args, cmd_name);
+               strvec_push(&cmd.args, "--stdin");
                if (!args->quiet && !args->no_progress)
-                       argv_array_push(&cmd.args, "-v");
+                       strvec_push(&cmd.args, "-v");
                if (args->use_thin_pack)
-                       argv_array_push(&cmd.args, "--fix-thin");
+                       strvec_push(&cmd.args, "--fix-thin");
                if (do_keep && (args->lock_pack || unpack_limit)) {
                        char hostname[HOST_NAME_MAX + 1];
                        if (xgethostname(hostname, sizeof(hostname)))
                                xsnprintf(hostname, sizeof(hostname), "localhost");
-                       argv_array_pushf(&cmd.args,
-                                       "--keep=fetch-pack %"PRIuMAX " on %s",
-                                       (uintmax_t)getpid(), hostname);
+                       strvec_pushf(&cmd.args,
+                                    "--keep=fetch-pack %"PRIuMAX " on %s",
+                                    (uintmax_t)getpid(), hostname);
                }
                if (only_packfile && args->check_self_contained_and_connected)
-                       argv_array_push(&cmd.args, "--check-self-contained-and-connected");
+                       strvec_push(&cmd.args, "--check-self-contained-and-connected");
                else
                        /*
                         * We cannot perform any connectivity checks because
@@ -866,26 +866,29 @@ static int get_pack(struct fetch_pack_args *args,
                         * have this responsibility.
                         */
                        args->check_self_contained_and_connected = 0;
-               /*
-                * If we're obtaining the filename of a lockfile, we'll use
-                * that filename to write a .promisor file with more
-                * information below. If not, we need index-pack to do it for
-                * us.
-                */
-               if (!(do_keep && pack_lockfiles) && args->from_promisor)
-                       argv_array_push(&cmd.args, "--promisor");
+
+               if (args->from_promisor)
+                       /*
+                        * write_promisor_file() may be called afterwards but
+                        * we still need index-pack to know that this is a
+                        * promisor pack. For example, if transfer.fsckobjects
+                        * is true, index-pack needs to know that .gitmodules
+                        * is a promisor object (so that it won't complain if
+                        * it is missing).
+                        */
+                       strvec_push(&cmd.args, "--promisor");
        }
        else {
                cmd_name = "unpack-objects";
-               argv_array_push(&cmd.args, cmd_name);
+               strvec_push(&cmd.args, cmd_name);
                if (args->quiet || args->no_progress)
-                       argv_array_push(&cmd.args, "-q");
+                       strvec_push(&cmd.args, "-q");
                args->check_self_contained_and_connected = 0;
        }
 
        if (pass_header)
-               argv_array_pushf(&cmd.args, "--pack_header=%"PRIu32",%"PRIu32,
-                                ntohl(header.hdr_version),
+               strvec_pushf(&cmd.args, "--pack_header=%"PRIu32",%"PRIu32,
+                            ntohl(header.hdr_version),
                                 ntohl(header.hdr_entries));
        if (fetch_fsck_objects >= 0
            ? fetch_fsck_objects
@@ -898,10 +901,10 @@ static int get_pack(struct fetch_pack_args *args,
                         * checks both broken objects and links, but we only
                         * want to check for broken objects.
                         */
-                       argv_array_push(&cmd.args, "--fsck-objects");
+                       strvec_push(&cmd.args, "--fsck-objects");
                else
-                       argv_array_pushf(&cmd.args, "--strict%s",
-                                        fsck_msg_types.buf);
+                       strvec_pushf(&cmd.args, "--strict%s",
+                                    fsck_msg_types.buf);
        }
 
        cmd.in = demux.out;
@@ -1652,11 +1655,11 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
                const char *uri = packfile_uris.items[i].string +
                        the_hash_algo->hexsz + 1;
 
-               argv_array_push(&cmd.args, "http-fetch");
-               argv_array_pushf(&cmd.args, "--packfile=%.*s",
-                                (int) the_hash_algo->hexsz,
-                                packfile_uris.items[i].string);
-               argv_array_push(&cmd.args, uri);
+               strvec_push(&cmd.args, "http-fetch");
+               strvec_pushf(&cmd.args, "--packfile=%.*s",
+                            (int) the_hash_algo->hexsz,
+                            packfile_uris.items[i].string);
+               strvec_push(&cmd.args, uri);
                cmd.git_cmd = 1;
                cmd.no_stdin = 1;
                cmd.out = -1;
index cfb8ff2f33f9f325bfae1fba78bf9312b5ba9cbe..bd22e1ea8865c086dd5e0c7fa32229036c1d83f3 100644 (file)
@@ -10,6 +10,8 @@
 #include "commit-reach.h"
 
 static int use_branch_desc;
+static int suppress_dest_pattern_seen;
+static struct string_list suppress_dest_patterns = STRING_LIST_INIT_DUP;
 
 int fmt_merge_msg_config(const char *key, const char *value, void *cb)
 {
@@ -22,6 +24,14 @@ int fmt_merge_msg_config(const char *key, const char *value, void *cb)
                        merge_log_config = DEFAULT_MERGE_LOG_LEN;
        } else if (!strcmp(key, "merge.branchdesc")) {
                use_branch_desc = git_config_bool(key, value);
+       } else if (!strcmp(key, "merge.suppressdest")) {
+               if (!value)
+                       return config_error_nonbool(key);
+               if (!*value)
+                       string_list_clear(&suppress_dest_patterns, 0);
+               else
+                       string_list_append(&suppress_dest_patterns, value);
+               suppress_dest_pattern_seen = 1;
        } else {
                return git_default_config(key, value, cb);
        }
@@ -403,6 +413,24 @@ static void shortlog(const char *name,
        string_list_clear(&subjects, 0);
 }
 
+/*
+ * See if dest_branch matches with any glob pattern on the
+ * suppress_dest_patterns list.
+ *
+ * We may want to also allow negative matches e.g. ":!glob" like we do
+ * for pathspec, but for now, let's keep it simple and stupid.
+ */
+static int dest_suppressed(const char *dest_branch)
+{
+       struct string_list_item *item;
+
+       for_each_string_list_item(item, &suppress_dest_patterns) {
+               if (!wildmatch(item->string, dest_branch, WM_PATHNAME))
+                       return 1;
+       }
+       return 0;
+}
+
 static void fmt_merge_msg_title(struct strbuf *out,
                                const char *current_branch)
 {
@@ -451,7 +479,9 @@ static void fmt_merge_msg_title(struct strbuf *out,
                        strbuf_addf(out, " of %s", srcs.items[i].string);
        }
 
-       strbuf_addf(out, " into %s\n", current_branch);
+       if (!dest_suppressed(current_branch))
+               strbuf_addf(out, " into %s", current_branch);
+       strbuf_addch(out, '\n');
 }
 
 static void fmt_tag_signature(struct strbuf *tagbuf,
@@ -596,6 +626,9 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
        void *current_branch_to_free;
        struct merge_parents merge_parents;
 
+       if (!suppress_dest_pattern_seen)
+               string_list_append(&suppress_dest_patterns, "master");
+
        memset(&merge_parents, 0, sizeof(merge_parents));
 
        /* get current branch */
index 932bd9012daf9eb91dd445374f52a78ceade918b..ca031c3abb8bf5a4c392039615c7ed88a991aa5e 100644 (file)
@@ -146,9 +146,9 @@ static int query_fsmonitor(int version, const char *last_update, struct strbuf *
        if (!core_fsmonitor)
                return -1;
 
-       argv_array_push(&cp.args, core_fsmonitor);
-       argv_array_pushf(&cp.args, "%d", version);
-       argv_array_pushf(&cp.args, "%s", last_update);
+       strvec_push(&cp.args, core_fsmonitor);
+       strvec_pushf(&cp.args, "%d", version);
+       strvec_pushf(&cp.args, "%s", last_update);
        cp.use_shell = 1;
        cp.dir = get_git_work_tree();
 
@@ -217,7 +217,7 @@ void refresh_fsmonitor(struct index_state *istate)
                                 * Need to use a char * variable because static
                                 * analysis was suggesting to use strbuf_addbuf
                                 * but we don't want to copy the entire strbuf
-                                * only the the chars up to the first NUL
+                                * only the chars up to the first NUL
                                 */
                                buf = query_result.buf;
                                strbuf_addstr(&last_update_token, buf);
index 08a6ed57ddb115413013ce5cd4c9a786b1a2bef9..c28e35b0fa8039f9d9ccf0925c1e17ac79c70dbe 100755 (executable)
@@ -4,7 +4,7 @@ USAGE='[help|start|bad|good|new|old|terms|skip|next|reset|visualize|view|replay|
 LONG_USAGE='git bisect help
        print this long help message.
 git bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>]
-                [--no-checkout] [<bad> [<good>...]] [--] [<pathspec>...]
+                [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]
        reset bisect state and start bisection.
 git bisect (bad|new) [<rev>]
        mark <rev> a known-bad revision/
@@ -41,7 +41,7 @@ TERM_GOOD=good
 
 bisect_head()
 {
-       if test -f "$GIT_DIR/BISECT_HEAD"
+       if git rev-parse --verify -q BISECT_HEAD > /dev/null
        then
                echo BISECT_HEAD
        else
@@ -153,7 +153,7 @@ bisect_next() {
        git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD $TERM_GOOD|| exit
 
        # Perform all bisection computation, display and checkout
-       git bisect--helper --next-all $(test -f "$GIT_DIR/BISECT_HEAD" && echo --no-checkout)
+       git bisect--helper --next-all
        res=$?
 
        # Check if we should exit because bisection is finished
index 5637114b8dcf41a2ab09a8f1787de53fc5a3a443..7a0fb7a04597a4b6fa7ea48194aa334852104eb9 100644 (file)
@@ -252,8 +252,10 @@ typedef unsigned long uintptr_t;
 #ifdef PRECOMPOSE_UNICODE
 #include "compat/precompose_utf8.h"
 #else
-#define precompose_str(in,i_nfd2nfc)
-#define precompose_argv(c,v)
+static inline void precompose_argv(int argc, const char **argv)
+{
+       ; /* nothing */
+}
 #define probe_utf8_pathname_composition()
 #endif
 
@@ -270,7 +272,9 @@ struct itimerval {
 #endif
 
 #ifdef NO_SETITIMER
-#define setitimer(which,value,ovalue)
+static inline int setitimer(int which, const struct itimerval *value, struct itimerval *newvalue) {
+       ; /* nothing */
+}
 #endif
 
 #ifndef NO_LIBGEN_H
@@ -1231,8 +1235,14 @@ int warn_on_fopen_errors(const char *path);
 #endif
 
 #ifndef _POSIX_THREAD_SAFE_FUNCTIONS
-#define flockfile(fh)
-#define funlockfile(fh)
+static inline void flockfile(FILE *fh)
+{
+       ; /* nothing */
+}
+static inline void funlockfile(FILE *fh)
+{
+       ; /* nothing */
+}
 #define getc_unlocked(fh) getc(fh)
 #endif
 
index 6483d792d337f6c0c0aa1dc0074df230bff8f378..0ae8bce3fb0675ea206e962ef576d08d5d608ada 100755 (executable)
@@ -22,7 +22,7 @@ die "Need at least one commit identifier!" unless @ARGV;
 my $repo = Git->repository();
 $opt_w = $repo->config('cvsexportcommit.cvsdir') unless defined $opt_w;
 
-my $tmpdir = File::Temp->newdir;
+my $tmpdir = File::Temp::tempdir(CLEANUP => 1);
 my $hash_algo = $repo->config('extensions.objectformat') || 'sha1';
 my $hexsz = $hash_algo eq 'sha256' ? 64 : 40;
 
index 204a5acd66f5444412f0088b8df6cb0ae2fd6b41..2defef28cd931fc9dca041ee7ec0ea5d440c3dd7 100644 (file)
@@ -43,7 +43,14 @@ show_tool_names () {
 
        shown_any=
        ( cd "$MERGE_TOOLS_DIR" && ls ) | {
-               while read toolname
+               while read scriptname
+               do
+                       setup_tool "$scriptname" 2>/dev/null
+                       variants="$variants$(list_tool_variants)\n"
+               done
+               variants="$(echo "$variants" | sort | uniq)"
+
+               for toolname in $variants
                do
                        if setup_tool "$toolname" 2>/dev/null &&
                                (eval "$condition" "$toolname")
@@ -157,6 +164,10 @@ setup_tool () {
                echo "$1"
        }
 
+       list_tool_variants () {
+               echo "$tool"
+       }
+
        # Most tools' exit codes cannot be trusted, so By default we ignore
        # their exit code and check the merged file's modification time in
        # check_unchanged() to determine whether or not the merge was
@@ -178,19 +189,26 @@ setup_tool () {
                false
        }
 
-
-       if ! test -f "$MERGE_TOOLS_DIR/$tool"
+       if test -f "$MERGE_TOOLS_DIR/$tool"
+       then
+               . "$MERGE_TOOLS_DIR/$tool"
+       elif test -f "$MERGE_TOOLS_DIR/${tool%[0-9]}"
        then
+               . "$MERGE_TOOLS_DIR/${tool%[0-9]}"
+       else
                setup_user_tool
                return $?
        fi
 
-       # Load the redefined functions
-       . "$MERGE_TOOLS_DIR/$tool"
        # Now let the user override the default command for the tool.  If
        # they have not done so then this will return 1 which we ignore.
        setup_user_tool
 
+       if ! list_tool_variants | grep -q "^$tool$"
+       then
+               return 1
+       fi
+
        if merge_mode && ! can_merge
        then
                echo "error: '$tool' can not be used to resolve merges" >&2
@@ -286,11 +304,14 @@ list_merge_tool_candidates () {
                tools="$tools smerge"
        fi
        case "${VISUAL:-$EDITOR}" in
+       *nvim*)
+               tools="$tools nvimdiff vimdiff emerge"
+               ;;
        *vim*)
-               tools="$tools vimdiff emerge"
+               tools="$tools vimdiff nvimdiff emerge"
                ;;
        *)
-               tools="$tools emerge vimdiff"
+               tools="$tools emerge vimdiff nvimdiff"
                ;;
        esac
 }
index dec90e9af67785e23bbe7cc553a1c23a5f0a1fd3..b9c71d2a71bdd32ed595da0d217f1e6c854f5ffc 100644 (file)
@@ -193,16 +193,6 @@ mark_action_done () {
        fi
 }
 
-# Put the last action marked done at the beginning of the todo list
-# again. If there has not been an action marked done yet, leave the list of
-# items on the todo list unchanged.
-reschedule_last_action () {
-       tail -n 1 "$done" | cat - "$todo" >"$todo".new
-       sed -e \$d <"$done" >"$done".new
-       mv -f "$todo".new "$todo"
-       mv -f "$done".new "$done"
-}
-
 append_todo_help () {
        gettext "
 Commands:
index 36c47bae1d1f1a0d3558fe43dcdbd5eb49a3d27c..1f425c08091d400e1d2e94533411c1b778f561de 100755 (executable)
@@ -250,6 +250,7 @@ my $chain_reply_to = 0;
 my $use_xmailer = 1;
 my $validate = 1;
 my $target_xfer_encoding = 'auto';
+my $forbid_sendmail_variables = 1;
 
 my %config_bool_settings = (
     "thread" => \$thread,
@@ -263,6 +264,7 @@ my %config_bool_settings = (
     "multiedit" => \$multiedit,
     "annotate" => \$annotate,
     "xmailer" => \$use_xmailer,
+    "forbidsendmailvariables" => \$forbid_sendmail_variables,
 );
 
 my %config_settings = (
@@ -478,6 +480,12 @@ unless ($rc) {
     usage();
 }
 
+if ($forbid_sendmail_variables && (scalar Git::config_regexp("^sendmail[.]")) != 0) {
+       die __("fatal: found configuration options for 'sendmail'\n" .
+               "git-send-email is configured with the sendemail.* options - note the 'e'.\n" .
+               "Set sendemail.forbidSendmailVariables to false to disable this check.\n");
+}
+
 die __("Cannot run git format-patch from outside a repository\n")
        if $format_patch and not $repo;
 
diff --git a/git.c b/git.c
index 6cd887bb0cffce589a14afc0205aefa3764c9eff..8bd1d7551daa28dcde69935046a055243c4b4d99 100644 (file)
--- a/git.c
+++ b/git.c
@@ -349,10 +349,10 @@ static int handle_alias(int *argcp, const char ***argv)
                        child.clean_on_exit = 1;
                        child.wait_after_clean = 1;
                        child.trace2_child_class = "shell_alias";
-                       argv_array_push(&child.args, alias_string + 1);
-                       argv_array_pushv(&child.args, (*argv) + 1);
+                       strvec_push(&child.args, alias_string + 1);
+                       strvec_pushv(&child.args, (*argv) + 1);
 
-                       trace2_cmd_alias(alias_command, child.args.argv);
+                       trace2_cmd_alias(alias_command, child.args.v);
                        trace2_cmd_list_config();
                        trace2_cmd_list_env_vars();
                        trace2_cmd_name("_run_shell_alias_");
@@ -646,7 +646,7 @@ static void strip_extension(const char **argv)
 
 static void handle_builtin(int argc, const char **argv)
 {
-       struct argv_array args = ARGV_ARRAY_INIT;
+       struct strvec args = STRVEC_INIT;
        const char *cmd;
        struct cmd_struct *builtin;
 
@@ -661,19 +661,19 @@ static void handle_builtin(int argc, const char **argv)
                argv[0] = cmd = "help";
 
                for (i = 0; i < argc; i++) {
-                       argv_array_push(&args, argv[i]);
+                       strvec_push(&args, argv[i]);
                        if (!i)
-                               argv_array_push(&args, "--exclude-guides");
+                               strvec_push(&args, "--exclude-guides");
                }
 
                argc++;
-               argv = args.argv;
+               argv = args.v;
        }
 
        builtin = get_builtin(cmd);
        if (builtin)
                exit(run_builtin(builtin, argc, argv));
-       argv_array_clear(&args);
+       strvec_clear(&args);
 }
 
 static void execv_dashed_external(const char **argv)
@@ -688,8 +688,8 @@ static void execv_dashed_external(const char **argv)
                use_pager = check_pager_config(argv[0]);
        commit_pager_choice();
 
-       argv_array_pushf(&cmd.args, "git-%s", argv[0]);
-       argv_array_pushv(&cmd.args, argv + 1);
+       strvec_pushf(&cmd.args, "git-%s", argv[0]);
+       strvec_pushv(&cmd.args, argv + 1);
        cmd.clean_on_exit = 1;
        cmd.wait_after_clean = 1;
        cmd.silent_exec_failure = 1;
@@ -701,7 +701,7 @@ static void execv_dashed_external(const char **argv)
         * The code in run_command() logs trace2 child_start/child_exit
         * events, so we do not need to report exec/exec_result events here.
         */
-       trace_argv_printf(cmd.args.argv, "trace: exec:");
+       trace_argv_printf(cmd.args.v, "trace: exec:");
 
        /*
         * If we fail because the command is not found, it is
@@ -741,7 +741,7 @@ static int run_argv(int *argcp, const char ***argv)
                if (!done_alias)
                        handle_builtin(*argcp, *argv);
                else if (get_builtin(**argv)) {
-                       struct argv_array args = ARGV_ARRAY_INIT;
+                       struct strvec args = STRVEC_INIT;
                        int i;
 
                        /*
@@ -758,17 +758,17 @@ static int run_argv(int *argcp, const char ***argv)
 
                        commit_pager_choice();
 
-                       argv_array_push(&args, "git");
+                       strvec_push(&args, "git");
                        for (i = 0; i < *argcp; i++)
-                               argv_array_push(&args, (*argv)[i]);
+                               strvec_push(&args, (*argv)[i]);
 
-                       trace_argv_printf(args.argv, "trace: exec:");
+                       trace_argv_printf(args.v, "trace: exec:");
 
                        /*
                         * if we fail because the command is not found, it is
                         * OK to return. Otherwise, we just pass along the status code.
                         */
-                       i = run_command_v_opt_tr2(args.argv, RUN_SILENT_EXEC_FAILURE |
+                       i = run_command_v_opt_tr2(args.v, RUN_SILENT_EXEC_FAILURE |
                                                  RUN_CLEAN_ON_EXIT | RUN_WAIT_AFTER_CLEAN, "git_alias");
                        if (i >= 0 || errno != ENOENT)
                                exit(i);
index 2d538bcd6e30d1314f76d89764284f8735cd187f..b49927083661c8ca695112b8432691f17ed6d835 100644 (file)
@@ -282,12 +282,12 @@ static int verify_signed_buffer(const char *payload, size_t payload_size,
        if (!fmt)
                BUG("bad signature '%s'", signature);
 
-       argv_array_push(&gpg.args, fmt->program);
-       argv_array_pushv(&gpg.args, fmt->verify_args);
-       argv_array_pushl(&gpg.args,
-                        "--status-fd=1",
-                        "--verify", temp->filename.buf, "-",
-                        NULL);
+       strvec_push(&gpg.args, fmt->program);
+       strvec_pushv(&gpg.args, fmt->verify_args);
+       strvec_pushl(&gpg.args,
+                    "--status-fd=1",
+                    "--verify", temp->filename.buf, "-",
+                    NULL);
 
        if (!gpg_status)
                gpg_status = &buf;
@@ -434,11 +434,11 @@ int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *sig
        size_t i, j, bottom;
        struct strbuf gpg_status = STRBUF_INIT;
 
-       argv_array_pushl(&gpg.args,
-                        use_format->program,
-                        "--status-fd=2",
-                        "-bsau", signing_key,
-                        NULL);
+       strvec_pushl(&gpg.args,
+                    use_format->program,
+                    "--status-fd=2",
+                    "-bsau", signing_key,
+                    NULL);
 
        bottom = signature->len;
 
diff --git a/graph.c b/graph.c
index 4cd9915075ff23d8a5218609b06239b9d9f08435..c128ad0cce8f5954eef4730eb70eb0ffab363310 100644 (file)
--- a/graph.c
+++ b/graph.c
@@ -4,7 +4,7 @@
 #include "color.h"
 #include "graph.h"
 #include "revision.h"
-#include "argv-array.h"
+#include "strvec.h"
 
 /* Internal API */
 
@@ -82,7 +82,7 @@ static void graph_show_line_prefix(const struct diff_options *diffopt)
 static const char **column_colors;
 static unsigned short column_colors_max;
 
-static void parse_graph_colors_config(struct argv_array *colors, const char *string)
+static void parse_graph_colors_config(struct strvec *colors, const char *string)
 {
        const char *end, *start;
 
@@ -93,13 +93,13 @@ static void parse_graph_colors_config(struct argv_array *colors, const char *str
                char color[COLOR_MAXLEN];
 
                if (!color_parse_mem(start, comma - start, color))
-                       argv_array_push(colors, color);
+                       strvec_push(colors, color);
                else
                        warning(_("ignore invalid color '%.*s' in log.graphColors"),
                                (int)(comma - start), start);
                start = comma + 1;
        }
-       argv_array_push(colors, GIT_COLOR_RESET);
+       strvec_push(colors, GIT_COLOR_RESET);
 }
 
 void graph_set_column_colors(const char **colors, unsigned short colors_max)
@@ -350,13 +350,13 @@ struct git_graph *graph_init(struct rev_info *opt)
                        graph_set_column_colors(column_colors_ansi,
                                                column_colors_ansi_max);
                } else {
-                       static struct argv_array custom_colors = ARGV_ARRAY_INIT;
-                       argv_array_clear(&custom_colors);
+                       static struct strvec custom_colors = STRVEC_INIT;
+                       strvec_clear(&custom_colors);
                        parse_graph_colors_config(&custom_colors, string);
                        free(string);
                        /* graph_set_column_colors takes a max-index, not a count */
-                       graph_set_column_colors(custom_colors.argv,
-                                               custom_colors.argc - 1);
+                       graph_set_column_colors(custom_colors.v,
+                                               custom_colors.nr - 1);
                }
        }
 
diff --git a/grep.c b/grep.c
index 13232a904aca4906f28aae2e04165d1fda47b922..54af9f813e99043c723ba4f6e9fd32023d0be655 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -1817,7 +1817,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
                 * We might set up the shared textconv cache data here, which
                 * is not thread-safe. Also, get_oid_with_context() and
                 * parse_object() might be internally called. As they are not
-                * currenty thread-safe and might be racy with object reading,
+                * currently thread-safe and might be racy with object reading,
                 * obj_read_lock() must be called.
                 */
                grep_attr_lock();
index 79ae9f80de1c19d5798006c34bc88ee786a0357a..ef220de4c64dabceb01273147b04bf5ebe897879 100644 (file)
--- a/hashmap.h
+++ b/hashmap.h
@@ -168,7 +168,7 @@ struct hashmap_entry {
  * argument `keydata`, respectively. Otherwise, `keydata` is NULL.
  *
  * When it is too expensive to allocate a user entry (either because it is
- * large or varialbe sized, such that it is not on the stack), then the
+ * large or variable sized, such that it is not on the stack), then the
  * relevant data to check for equality should be passed via `keydata`.
  * In this case `key` can be a stripped down version of the user key data
  * or even just a hashmap_entry having the correct hash.
diff --git a/help.c b/help.c
index 44cee69c11c68381fbdc12a3fb6b7f5bae7f4dfe..4e2468a44dfe3154642299dbca0761ab114cb859 100644 (file)
--- a/help.c
+++ b/help.c
@@ -375,7 +375,7 @@ void list_cmds_by_config(struct string_list *list)
 {
        const char *cmd_list;
 
-       if (git_config_get_string_const("completion.commands", &cmd_list))
+       if (git_config_get_string_tmp("completion.commands", &cmd_list))
                return;
 
        string_list_sort(list);
@@ -397,10 +397,10 @@ void list_cmds_by_config(struct string_list *list)
        }
 }
 
-void list_common_guides_help(void)
+void list_guides_help(void)
 {
        struct category_description catdesc[] = {
-               { CAT_guide, N_("The common Git guides are:") },
+               { CAT_guide, N_("The Git concept guides are:") },
                { 0, NULL }
        };
        print_cmd_by_category(catdesc, NULL);
diff --git a/help.h b/help.h
index 500521b9081c3725cdfcc252ef30394af40a6943..dc02458855c09291e2caf4bac6cd5b3a7ba40cff 100644 (file)
--- a/help.h
+++ b/help.h
@@ -21,7 +21,7 @@ static inline void mput_char(char c, unsigned int num)
 
 void list_common_cmds_help(void);
 void list_all_cmds_help(void);
-void list_common_guides_help(void);
+void list_guides_help(void);
 
 void list_all_main_cmds(struct string_list *list);
 void list_all_other_cmds(struct string_list *list);
index ec3144b4447548cfd9cf23d22c1f7f5f8c7cde35..a03b4bae2221fc2cdb8fa5dad0f89c1ce33af281 100644 (file)
@@ -9,7 +9,7 @@
 #include "run-command.h"
 #include "string-list.h"
 #include "url.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "packfile.h"
 #include "object-store.h"
 #include "protocol.h"
@@ -477,10 +477,10 @@ static void run_service(const char **argv, int buffer_input)
                host = "(none)";
 
        if (!getenv("GIT_COMMITTER_NAME"))
-               argv_array_pushf(&cld.env_array, "GIT_COMMITTER_NAME=%s", user);
+               strvec_pushf(&cld.env_array, "GIT_COMMITTER_NAME=%s", user);
        if (!getenv("GIT_COMMITTER_EMAIL"))
-               argv_array_pushf(&cld.env_array,
-                                "GIT_COMMITTER_EMAIL=%s@http.%s", user, host);
+               strvec_pushf(&cld.env_array,
+                            "GIT_COMMITTER_EMAIL=%s@http.%s", user, host);
 
        cld.argv = argv;
        if (buffer_input || gzipped_request || req_len >= 0)
index 1df376e745ce69390bf8dda422882906a5f747ec..c4ccc5fea93cff445785bb101c8438b9374d1b74 100644 (file)
@@ -84,8 +84,11 @@ int cmd_main(int argc, const char **argv)
        int get_verbosely = 0;
        int get_recover = 0;
        int packfile = 0;
+       int nongit;
        struct object_id packfile_hash;
 
+       setup_git_directory_gently(&nongit);
+
        while (arg < argc && argv[arg][0] == '-') {
                const char *p;
 
@@ -115,7 +118,8 @@ int cmd_main(int argc, const char **argv)
        if (argc != arg + 2 - (commits_on_stdin || packfile))
                usage(http_fetch_usage);
 
-       setup_git_directory();
+       if (nongit)
+               die(_("not a git repository"));
 
        git_config(git_default_config, NULL);
 
index 1ff1883cdd9fdb537d52b1c2c25f780378de5e7c..6a4a43e07f2cd43ad3b34b409de69d1903fb6fd9 100644 (file)
@@ -11,7 +11,7 @@
 #include "remote.h"
 #include "list-objects.h"
 #include "sigchain.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "packfile.h"
 #include "object-store.h"
 #include "commit-reach.h"
@@ -1846,7 +1846,7 @@ int cmd_main(int argc, const char **argv)
 
        new_refs = 0;
        for (ref = remote_refs; ref; ref = ref->next) {
-               struct argv_array commit_argv = ARGV_ARRAY_INIT;
+               struct strvec commit_argv = STRVEC_INIT;
 
                if (!ref->peer_ref)
                        continue;
@@ -1924,14 +1924,14 @@ int cmd_main(int argc, const char **argv)
                }
 
                /* Set up revision info for this refspec */
-               argv_array_push(&commit_argv, ""); /* ignored */
-               argv_array_push(&commit_argv, "--objects");
-               argv_array_push(&commit_argv, oid_to_hex(&ref->new_oid));
+               strvec_push(&commit_argv, ""); /* ignored */
+               strvec_push(&commit_argv, "--objects");
+               strvec_push(&commit_argv, oid_to_hex(&ref->new_oid));
                if (!push_all && !is_null_oid(&ref->old_oid))
-                       argv_array_pushf(&commit_argv, "^%s",
-                                        oid_to_hex(&ref->old_oid));
+                       strvec_pushf(&commit_argv, "^%s",
+                                    oid_to_hex(&ref->old_oid));
                repo_init_revisions(the_repository, &revs, setup_git_directory());
-               setup_revisions(commit_argv.argc, commit_argv.argv, &revs, NULL);
+               setup_revisions(commit_argv.nr, commit_argv.v, &revs, NULL);
                revs.edge_hint = 0; /* just in case */
 
                /* Generate a list of objects that need to be pushed */
@@ -1961,7 +1961,7 @@ int cmd_main(int argc, const char **argv)
                        printf("%s %s\n", !rc ? "ok" : "error", ref->name);
                unlock_remote(ref_lock);
                check_locks();
-               argv_array_clear(&commit_argv);
+               strvec_clear(&commit_argv);
        }
 
        /* Update remote server info if appropriate */
diff --git a/http.c b/http.c
index 3b12843a5b2341615d341e5c1fd49d05dcb893a5..8b23a546afdf40dc9f15756f637a62286fe1bdd0 100644 (file)
--- a/http.c
+++ b/http.c
@@ -2270,13 +2270,13 @@ int finish_http_pack_request(struct http_pack_request *preq)
 
        tmpfile_fd = xopen(preq->tmpfile.buf, O_RDONLY);
 
-       argv_array_push(&ip.args, "index-pack");
-       argv_array_push(&ip.args, "--stdin");
+       strvec_push(&ip.args, "index-pack");
+       strvec_push(&ip.args, "--stdin");
        ip.git_cmd = 1;
        ip.in = tmpfile_fd;
        if (preq->generate_keep) {
-               argv_array_pushf(&ip.args, "--keep=git %"PRIuMAX,
-                                (uintmax_t)getpid());
+               strvec_pushf(&ip.args, "--keep=git %"PRIuMAX,
+                            (uintmax_t)getpid());
                ip.out = 0;
        } else {
                ip.no_stdout = 1;
index 52737546f38b65f1cba1043dbda349d6680b78b6..5764dd812ca768002aacd67b066f9af22ab8994e 100644 (file)
@@ -976,7 +976,7 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc, char *f
 
                imap_info("Starting tunnel '%s'... ", srvc->tunnel);
 
-               argv_array_push(&tunnel.args, srvc->tunnel);
+               strvec_push(&tunnel.args, srvc->tunnel);
                tunnel.use_shell = 1;
                tunnel.in = -1;
                tunnel.out = -1;
index c53692834d858cb602431f6a15c30203615e3b0a..bf73ea95acbcf2d9969850227756773592389d42 100644 (file)
@@ -14,7 +14,7 @@
 #include "graph.h"
 #include "userdiff.h"
 #include "line-log.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "bloom.h"
 
 static void range_set_grow(struct range_set *rs, size_t extra)
@@ -758,12 +758,12 @@ static void parse_pathspec_from_ranges(struct pathspec *pathspec,
                                       struct line_log_data *range)
 {
        struct line_log_data *r;
-       struct argv_array array = ARGV_ARRAY_INIT;
+       struct strvec array = STRVEC_INIT;
        const char **paths;
 
        for (r = range; r; r = r->next)
-               argv_array_push(&array, r->path);
-       paths = argv_array_detach(&array);
+               strvec_push(&array, r->path);
+       paths = strvec_detach(&array);
 
        parse_pathspec(pathspec, 0, PATHSPEC_PREFER_FULL, "", paths);
        /* strings are now owned by pathspec */
index 3553ad7b0a759e13258a267960caf2ee15b6f019..b66314560ac957d722985ad935ecb7fb49663b85 100644 (file)
@@ -2,7 +2,7 @@
 #include "commit.h"
 #include "config.h"
 #include "revision.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "list-objects.h"
 #include "list-objects-filter.h"
 #include "list-objects-filter-options.h"
@@ -15,6 +15,29 @@ static int parse_combine_filter(
        const char *arg,
        struct strbuf *errbuf);
 
+const char *list_object_filter_config_name(enum list_objects_filter_choice c)
+{
+       switch (c) {
+       case LOFC_DISABLED:
+               /* we have no name for "no filter at all" */
+               break;
+       case LOFC_BLOB_NONE:
+               return "blob:none";
+       case LOFC_BLOB_LIMIT:
+               return "blob:limit";
+       case LOFC_TREE_DEPTH:
+               return "tree";
+       case LOFC_SPARSE_OID:
+               return "sparse:oid";
+       case LOFC_COMBINE:
+               return "combine";
+       case LOFC__COUNT:
+               /* not a real filter type; just the count of all filters */
+               break;
+       }
+       BUG("list_object_filter_choice_name: invalid argument '%d'", c);
+}
+
 /*
  * Parse value of the argument to the "filter" keyword.
  * On the command line this looks like:
index 73fffa4ad746a31a4a798d05f38452f1916b365d..01767c3c968f33440aac3095a25d8cc08bec3659 100644 (file)
@@ -17,6 +17,12 @@ enum list_objects_filter_choice {
        LOFC__COUNT /* must be last */
 };
 
+/*
+ * Returns a configuration key suitable for describing the given object filter,
+ * e.g.: "blob:none", "combine", etc.
+ */
+const char *list_object_filter_config_name(enum list_objects_filter_choice c);
+
 struct list_objects_filter_options {
        /*
         * 'filter_spec' is the raw argument value given on the command line
index 50d86866c6eac5957951e5b685d7912fcf12eed7..a1e0b473e44720421a71adeaf6aebb4ceb782f6e 100644 (file)
--- a/ls-refs.c
+++ b/ls-refs.c
@@ -2,7 +2,7 @@
 #include "repository.h"
 #include "refs.h"
 #include "remote.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "ls-refs.h"
 #include "pkt-line.h"
 #include "config.h"
  * Check if one of the prefixes is a prefix of the ref.
  * If no prefixes were provided, all refs match.
  */
-static int ref_match(const struct argv_array *prefixes, const char *refname)
+static int ref_match(const struct strvec *prefixes, const char *refname)
 {
        int i;
 
-       if (!prefixes->argc)
+       if (!prefixes->nr)
                return 1; /* no restriction */
 
-       for (i = 0; i < prefixes->argc; i++) {
-               const char *prefix = prefixes->argv[i];
+       for (i = 0; i < prefixes->nr; i++) {
+               const char *prefix = prefixes->v[i];
 
                if (starts_with(refname, prefix))
                        return 1;
@@ -31,7 +31,7 @@ static int ref_match(const struct argv_array *prefixes, const char *refname)
 struct ls_refs_data {
        unsigned peel;
        unsigned symrefs;
-       struct argv_array prefixes;
+       struct strvec prefixes;
 };
 
 static int send_ref(const char *refname, const struct object_id *oid,
@@ -84,7 +84,7 @@ static int ls_refs_config(const char *var, const char *value, void *data)
        return parse_hide_refs_config(var, value, "uploadpack");
 }
 
-int ls_refs(struct repository *r, struct argv_array *keys,
+int ls_refs(struct repository *r, struct strvec *keys,
            struct packet_reader *request)
 {
        struct ls_refs_data data;
@@ -102,7 +102,7 @@ int ls_refs(struct repository *r, struct argv_array *keys,
                else if (!strcmp("symrefs", arg))
                        data.symrefs = 1;
                else if (skip_prefix(arg, "ref-prefix ", &out))
-                       argv_array_push(&data.prefixes, out);
+                       strvec_push(&data.prefixes, out);
        }
 
        if (request->status != PACKET_READ_FLUSH)
@@ -111,6 +111,6 @@ int ls_refs(struct repository *r, struct argv_array *keys,
        head_ref_namespaced(send_ref, &data);
        for_each_namespaced_ref(send_ref, &data);
        packet_flush(1);
-       argv_array_clear(&data.prefixes);
+       strvec_clear(&data.prefixes);
        return 0;
 }
index 7e5646f5f62b2c69e591cde485b58c5328b609bc..7b33a7c6b819c0d504ad6b447b61e003e9f590fb 100644 (file)
--- a/ls-refs.h
+++ b/ls-refs.h
@@ -2,9 +2,9 @@
 #define LS_REFS_H
 
 struct repository;
-struct argv_array;
+struct strvec;
 struct packet_reader;
-int ls_refs(struct repository *r, struct argv_array *keys,
+int ls_refs(struct repository *r, struct strvec *keys,
            struct packet_reader *request);
 
 #endif /* LS_REFS_H */
index a2841a4a9ad7e4871282031f1b18fd62f18e9638..8401761dda0a2a585f6593e2212ff41db7135170 100644 (file)
  * `insert_after`. If `insert_after` is NULL, then insert block at the
  * head of the linked list.
  */
-static struct mp_block *mem_pool_alloc_block(struct mem_pool *mem_pool, size_t block_alloc, struct mp_block *insert_after)
+static struct mp_block *mem_pool_alloc_block(struct mem_pool *pool,
+                                            size_t block_alloc,
+                                            struct mp_block *insert_after)
 {
        struct mp_block *p;
 
-       mem_pool->pool_alloc += sizeof(struct mp_block) + block_alloc;
+       pool->pool_alloc += sizeof(struct mp_block) + block_alloc;
        p = xmalloc(st_add(sizeof(struct mp_block), block_alloc));
 
        p->next_free = (char *)p->space;
@@ -26,35 +28,27 @@ static struct mp_block *mem_pool_alloc_block(struct mem_pool *mem_pool, size_t b
                p->next_block = insert_after->next_block;
                insert_after->next_block = p;
        } else {
-               p->next_block = mem_pool->mp_block;
-               mem_pool->mp_block = p;
+               p->next_block = pool->mp_block;
+               pool->mp_block = p;
        }
 
        return p;
 }
 
-void mem_pool_init(struct mem_pool **mem_pool, size_t initial_size)
+void mem_pool_init(struct mem_pool *pool, size_t initial_size)
 {
-       struct mem_pool *pool;
-
-       if (*mem_pool)
-               return;
-
-       pool = xcalloc(1, sizeof(*pool));
-
+       memset(pool, 0, sizeof(*pool));
        pool->block_alloc = BLOCK_GROWTH_SIZE;
 
        if (initial_size > 0)
                mem_pool_alloc_block(pool, initial_size, NULL);
-
-       *mem_pool = pool;
 }
 
-void mem_pool_discard(struct mem_pool *mem_pool, int invalidate_memory)
+void mem_pool_discard(struct mem_pool *pool, int invalidate_memory)
 {
        struct mp_block *block, *block_to_free;
 
-       block = mem_pool->mp_block;
+       block = pool->mp_block;
        while (block)
        {
                block_to_free = block;
@@ -66,10 +60,11 @@ void mem_pool_discard(struct mem_pool *mem_pool, int invalidate_memory)
                free(block_to_free);
        }
 
-       free(mem_pool);
+       pool->mp_block = NULL;
+       pool->pool_alloc = 0;
 }
 
-void *mem_pool_alloc(struct mem_pool *mem_pool, size_t len)
+void *mem_pool_alloc(struct mem_pool *pool, size_t len)
 {
        struct mp_block *p = NULL;
        void *r;
@@ -78,15 +73,15 @@ void *mem_pool_alloc(struct mem_pool *mem_pool, size_t len)
        if (len & (sizeof(uintmax_t) - 1))
                len += sizeof(uintmax_t) - (len & (sizeof(uintmax_t) - 1));
 
-       if (mem_pool->mp_block &&
-           mem_pool->mp_block->end - mem_pool->mp_block->next_free >= len)
-               p = mem_pool->mp_block;
+       if (pool->mp_block &&
+           pool->mp_block->end - pool->mp_block->next_free >= len)
+               p = pool->mp_block;
 
        if (!p) {
-               if (len >= (mem_pool->block_alloc / 2))
-                       return mem_pool_alloc_block(mem_pool, len, mem_pool->mp_block);
+               if (len >= (pool->block_alloc / 2))
+                       return mem_pool_alloc_block(pool, len, pool->mp_block);
 
-               p = mem_pool_alloc_block(mem_pool, mem_pool->block_alloc, NULL);
+               p = mem_pool_alloc_block(pool, pool->block_alloc, NULL);
        }
 
        r = p->next_free;
@@ -94,20 +89,38 @@ void *mem_pool_alloc(struct mem_pool *mem_pool, size_t len)
        return r;
 }
 
-void *mem_pool_calloc(struct mem_pool *mem_pool, size_t count, size_t size)
+void *mem_pool_calloc(struct mem_pool *pool, size_t count, size_t size)
 {
        size_t len = st_mult(count, size);
-       void *r = mem_pool_alloc(mem_pool, len);
+       void *r = mem_pool_alloc(pool, len);
        memset(r, 0, len);
        return r;
 }
 
-int mem_pool_contains(struct mem_pool *mem_pool, void *mem)
+char *mem_pool_strdup(struct mem_pool *pool, const char *str)
+{
+       size_t len = strlen(str) + 1;
+       char *ret = mem_pool_alloc(pool, len);
+
+       return memcpy(ret, str, len);
+}
+
+char *mem_pool_strndup(struct mem_pool *pool, const char *str, size_t len)
+{
+       char *p = memchr(str, '\0', len);
+       size_t actual_len = (p ? p - str : len);
+       char *ret = mem_pool_alloc(pool, actual_len+1);
+
+       ret[actual_len] = '\0';
+       return memcpy(ret, str, actual_len);
+}
+
+int mem_pool_contains(struct mem_pool *pool, void *mem)
 {
        struct mp_block *p;
 
        /* Check if memory is allocated in a block */
-       for (p = mem_pool->mp_block; p; p = p->next_block)
+       for (p = pool->mp_block; p; p = p->next_block)
                if ((mem >= ((void *)p->space)) &&
                    (mem < ((void *)p->end)))
                        return 1;
index 999d3c3a52cc49b6dec896fc1e6b31ea8ac078d5..fe7507f022bba40d74aab341e99269ead7171695 100644 (file)
@@ -24,12 +24,12 @@ struct mem_pool {
 /*
  * Initialize mem_pool with specified initial size.
  */
-void mem_pool_init(struct mem_pool **mem_pool, size_t initial_size);
+void mem_pool_init(struct mem_pool *pool, size_t initial_size);
 
 /*
- * Discard a memory pool and free all the memory it is responsible for.
+ * Discard all the memory the memory pool is responsible for.
  */
-void mem_pool_discard(struct mem_pool *mem_pool, int invalidate_memory);
+void mem_pool_discard(struct mem_pool *pool, int invalidate_memory);
 
 /*
  * Alloc memory from the mem_pool.
@@ -41,6 +41,12 @@ void *mem_pool_alloc(struct mem_pool *pool, size_t len);
  */
 void *mem_pool_calloc(struct mem_pool *pool, size_t count, size_t size);
 
+/*
+ * Allocate memory from the memory pool and copy str into it.
+ */
+char *mem_pool_strdup(struct mem_pool *pool, const char *str);
+char *mem_pool_strndup(struct mem_pool *pool, const char *str, size_t len);
+
 /*
  * Move the memory associated with the 'src' pool to the 'dst' pool. The 'src'
  * pool will be empty and not contain any memory. It still needs to be free'd
@@ -52,6 +58,6 @@ void mem_pool_combine(struct mem_pool *dst, struct mem_pool *src);
  * Check if a memory pointed at by 'mem' is part of the range of
  * memory managed by the specified mem_pool.
  */
-int mem_pool_contains(struct mem_pool *mem_pool, void *mem);
+int mem_pool_contains(struct mem_pool *pool, void *mem);
 
 #endif
index 36948eafb750284551a3748405135a685ddba2ff..d0214335a79ddef7202e0552b80111a05c36f14c 100644 (file)
@@ -3529,8 +3529,9 @@ static struct commit_list *reverse_commit_list(struct commit_list *list)
 }
 
 /*
- * Merge the commits h1 and h2, return the resulting virtual
- * commit object and a flag indicating the cleanness of the merge.
+ * Merge the commits h1 and h2, returning a flag (int) indicating the
+ * cleanness of the merge.  Also, if opt->priv->call_depth, create a
+ * virtual commit and write its location to *result.
  */
 static int merge_recursive_internal(struct merge_options *opt,
                                    struct commit *h1,
@@ -3791,9 +3792,12 @@ int merge_recursive_generic(struct merge_options *opt,
 static void merge_recursive_config(struct merge_options *opt)
 {
        char *value = NULL;
+       int renormalize = 0;
        git_config_get_int("merge.verbosity", &opt->verbosity);
        git_config_get_int("diff.renamelimit", &opt->rename_limit);
        git_config_get_int("merge.renamelimit", &opt->rename_limit);
+       git_config_get_bool("merge.renormalize", &renormalize);
+       opt->renormalize = renormalize;
        if (!git_config_get_string("diff.renames", &value)) {
                opt->detect_renames = git_config_rename("diff.renames", value);
                free(value);
index 978847e6724805ccab3fb85015f51677b045da62..0795a1d3ec1809ea42fd11c1e3ad35467050d286 100644 (file)
@@ -69,9 +69,8 @@ int parse_merge_opt(struct merge_options *opt, const char *s);
  *
  * Outputs:
  *   - See RETURN VALUES above
- *   - No commit is created
  *   - opt->repo->index has the new index
- *   - $GIT_INDEX_FILE is not updated
+ *   - new index NOT written to disk
  *   - The working tree is updated with results of the merge
  */
 int merge_trees(struct merge_options *opt,
@@ -81,7 +80,7 @@ int merge_trees(struct merge_options *opt,
 
 /*
  * merge_recursive is like merge_trees() but with recursive ancestor
- * consolidation and, if the commit is clean, creation of a commit.
+ * consolidation.
  *
  * NOTE: empirically, about a decade ago it was determined that with more
  *       than two merge bases, optimal behavior was found when the
@@ -91,9 +90,9 @@ int merge_trees(struct merge_options *opt,
  *
  * Outputs:
  *   - See RETURN VALUES above
- *   - If merge is clean, a commit is created and its address written to *result
+ *   - *result is treated as scratch space for temporary recursive merges
  *   - opt->repo->index has the new index
- *   - $GIT_INDEX_FILE is not updated
+ *   - new index NOT written to disk
  *   - The working tree is updated with results of the merge
  */
 int merge_recursive(struct merge_options *opt,
@@ -109,9 +108,9 @@ int merge_recursive(struct merge_options *opt,
  *
  * Outputs:
  *   - See RETURN VALUES above
- *   - If merge is clean, a commit is created and its address written to *result
+ *   - *result is treated as scratch space for temporary recursive merges
  *   - opt->repo->index has the new index
- *   - $GIT_INDEX_FILE is updated
+ *   - new index also written to $GIT_INDEX_FILE on disk
  *   - The working tree is updated with results of the merge
  */
 int merge_recursive_generic(struct merge_options *opt,
diff --git a/merge.c b/merge.c
index aa36de2f64a4e1195a274f5d50c471c6806d4db8..5fb88af10254a75557697345fd25cfcf19df9748 100644 (file)
--- a/merge.c
+++ b/merge.c
@@ -19,22 +19,22 @@ int try_merge_command(struct repository *r,
                      const char **xopts, struct commit_list *common,
                      const char *head_arg, struct commit_list *remotes)
 {
-       struct argv_array args = ARGV_ARRAY_INIT;
+       struct strvec args = STRVEC_INIT;
        int i, ret;
        struct commit_list *j;
 
-       argv_array_pushf(&args, "merge-%s", strategy);
+       strvec_pushf(&args, "merge-%s", strategy);
        for (i = 0; i < xopts_nr; i++)
-               argv_array_pushf(&args, "--%s", xopts[i]);
+               strvec_pushf(&args, "--%s", xopts[i]);
        for (j = common; j; j = j->next)
-               argv_array_push(&args, merge_argument(j->item));
-       argv_array_push(&args, "--");
-       argv_array_push(&args, head_arg);
+               strvec_push(&args, merge_argument(j->item));
+       strvec_push(&args, "--");
+       strvec_push(&args, head_arg);
        for (j = remotes; j; j = j->next)
-               argv_array_push(&args, merge_argument(j->item));
+               strvec_push(&args, merge_argument(j->item));
 
-       ret = run_command_v_opt(args.argv, RUN_GIT_CMD);
-       argv_array_clear(&args);
+       ret = run_command_v_opt(args.v, RUN_GIT_CMD);
+       strvec_clear(&args);
 
        discard_index(r->index);
        if (repo_read_index(r) < 0)
@@ -80,8 +80,8 @@ int checkout_fast_forward(struct repository *r,
        }
 
        memset(&opts, 0, sizeof(opts));
+       dir_init(&dir);
        if (overwrite_ignore) {
-               memset(&dir, 0, sizeof(dir));
                dir.flags |= DIR_SHOW_IGNORED;
                setup_standard_excludes(&dir);
                opts.dir = &dir;
@@ -102,6 +102,7 @@ int checkout_fast_forward(struct repository *r,
                clear_unpack_trees_porcelain(&opts);
                return -1;
        }
+       dir_clear(&dir);
        clear_unpack_trees_porcelain(&opts);
 
        if (write_locked_index(r->index, &lock_file, COMMIT_LOCK))
index 3a69e60faa9c95dcf388cd295d040e9b88e0defd..a89086ee720f842359eefe58f369af2774457438 100644 (file)
@@ -21,3 +21,8 @@ translate_merge_tool_path() {
                echo bcompare
        fi
 }
+
+list_tool_variants () {
+       echo bc
+       echo bc3
+}
diff --git a/mergetools/bc3 b/mergetools/bc3
deleted file mode 100644 (file)
index 5d8dd48..0000000
+++ /dev/null
@@ -1 +0,0 @@
-. "$MERGE_TOOLS_DIR/bc"
diff --git a/mergetools/gvimdiff3 b/mergetools/gvimdiff3
deleted file mode 100644 (file)
index 04a5bb0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-. "$MERGE_TOOLS_DIR/vimdiff"
similarity index 100%
rename from mergetools/gvimdiff2
rename to mergetools/nvimdiff
index 10d86f3e19304125cecf06ddad928b9ffe2d0c08..abc8ce4ec44e190812ba46b39b8ba2dec1cc14fe 100644 (file)
@@ -5,7 +5,7 @@ diff_cmd () {
 
 merge_cmd () {
        case "$1" in
-       gvimdiff|vimdiff)
+       *vimdiff)
                if $base_present
                then
                        "$merge_tool_path" -f -d -c '4wincmd w | wincmd J' \
@@ -15,11 +15,11 @@ merge_cmd () {
                                "$LOCAL" "$MERGED" "$REMOTE"
                fi
                ;;
-       gvimdiff2|vimdiff2)
+       *vimdiff2)
                "$merge_tool_path" -f -d -c 'wincmd l' \
                        "$LOCAL" "$MERGED" "$REMOTE"
                ;;
-       gvimdiff3|vimdiff3)
+       *vimdiff3)
                if $base_present
                then
                        "$merge_tool_path" -f -d -c 'hid | hid | hid' \
@@ -34,10 +34,13 @@ merge_cmd () {
 
 translate_merge_tool_path() {
        case "$1" in
-       gvimdiff|gvimdiff2|gvimdiff3)
+       nvimdiff*)
+               echo nvim
+               ;;
+       gvimdiff*)
                echo gvim
                ;;
-       vimdiff|vimdiff2|vimdiff3)
+       vimdiff*)
                echo vim
                ;;
        esac
@@ -46,3 +49,11 @@ translate_merge_tool_path() {
 exit_code_trustable () {
        true
 }
+
+list_tool_variants () {
+       for prefix in '' g n; do
+               for suffix in '' 2 3; do
+                       echo "${prefix}vimdiff${suffix}"
+               done
+       done
+}
diff --git a/mergetools/vimdiff2 b/mergetools/vimdiff2
deleted file mode 100644 (file)
index 04a5bb0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-. "$MERGE_TOOLS_DIR/vimdiff"
diff --git a/mergetools/vimdiff3 b/mergetools/vimdiff3
deleted file mode 100644 (file)
index 04a5bb0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-. "$MERGE_TOOLS_DIR/vimdiff"
diff --git a/midx.c b/midx.c
index 6d1584ca51d313343bbb65f9baa7c794259c7bf0..e9b2e1253a678836dab68a1f15cdaf954444cfea 100644 (file)
--- a/midx.c
+++ b/midx.c
@@ -17,7 +17,6 @@
 #define MIDX_BYTE_HASH_VERSION 5
 #define MIDX_BYTE_NUM_CHUNKS 6
 #define MIDX_BYTE_NUM_PACKS 8
-#define MIDX_HASH_VERSION 1
 #define MIDX_HEADER_SIZE 12
 #define MIDX_MIN_SIZE (MIDX_HEADER_SIZE + the_hash_algo->rawsz)
 
 
 #define PACK_EXPIRED UINT_MAX
 
+static uint8_t oid_version(void)
+{
+       switch (hash_algo_by_ptr(the_hash_algo)) {
+       case GIT_HASH_SHA1:
+               return 1;
+       case GIT_HASH_SHA256:
+               return 2;
+       default:
+               die(_("invalid hash version"));
+       }
+}
+
 static char *get_midx_filename(const char *object_dir)
 {
        return xstrfmt("%s/pack/multi-pack-index", object_dir);
@@ -90,8 +101,11 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local
                      m->version);
 
        hash_version = m->data[MIDX_BYTE_HASH_VERSION];
-       if (hash_version != MIDX_HASH_VERSION)
-               die(_("hash version %u does not match"), hash_version);
+       if (hash_version != oid_version()) {
+               error(_("multi-pack-index hash version %u does not match version %u"),
+                     hash_version, oid_version());
+               goto cleanup_fail;
+       }
        m->hash_len = the_hash_algo->rawsz;
 
        m->num_chunks = m->data[MIDX_BYTE_NUM_CHUNKS];
@@ -418,7 +432,7 @@ static size_t write_midx_header(struct hashfile *f,
 
        hashwrite_be32(f, MIDX_SIGNATURE);
        byte_values[0] = MIDX_VERSION;
-       byte_values[1] = MIDX_HASH_VERSION;
+       byte_values[1] = oid_version();
        byte_values[2] = num_chunks;
        byte_values[3] = 0; /* unused */
        hashwrite(f, byte_values, sizeof(byte_values));
@@ -807,11 +821,9 @@ static int write_midx_internal(const char *object_dir, struct multi_pack_index *
        int result = 0;
 
        midx_name = get_midx_filename(object_dir);
-       if (safe_create_leading_directories(midx_name)) {
-               UNLEAK(midx_name);
+       if (safe_create_leading_directories(midx_name))
                die_errno(_("unable to create leading directories of %s"),
                          midx_name);
-       }
 
        if (m)
                packs.m = m;
@@ -1051,10 +1063,8 @@ void clear_midx_file(struct repository *r)
                r->objects->multi_pack_index = NULL;
        }
 
-       if (remove_path(midx)) {
-               UNLEAK(midx);
+       if (remove_path(midx))
                die(_("failed to clear multi-pack-index at %s"), midx);
-       }
 
        free(midx);
 }
@@ -1105,8 +1115,17 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag
        struct multi_pack_index *m = load_multi_pack_index(object_dir, 1);
        verify_midx_error = 0;
 
-       if (!m)
-               return 0;
+       if (!m) {
+               int result = 0;
+               struct stat sb;
+               char *filename = get_midx_filename(object_dir);
+               if (!stat(filename, &sb)) {
+                       error(_("multi-pack-index file exists, but failed to parse"));
+                       result = 1;
+               }
+               free(filename);
+               return result;
+       }
 
        if (flags & MIDX_PROGRESS)
                progress = start_progress(_("Looking for referenced packfiles"),
@@ -1371,7 +1390,7 @@ static int fill_included_packs_batch(struct repository *r,
 
        free(pack_info);
 
-       if (total_size < batch_size || packs_to_repack < 2)
+       if (packs_to_repack < 2)
                return 1;
 
        return 0;
@@ -1383,6 +1402,7 @@ int midx_repack(struct repository *r, const char *object_dir, size_t batch_size,
        uint32_t i;
        unsigned char *include_pack;
        struct child_process cmd = CHILD_PROCESS_INIT;
+       FILE *cmd_in;
        struct strbuf base_name = STRBUF_INIT;
        struct multi_pack_index *m = load_multi_pack_index(object_dir, 1);
 
@@ -1408,21 +1428,21 @@ int midx_repack(struct repository *r, const char *object_dir, size_t batch_size,
        repo_config_get_bool(r, "repack.usedeltabaseoffset", &delta_base_offset);
        repo_config_get_bool(r, "repack.usedeltaislands", &use_delta_islands);
 
-       argv_array_push(&cmd.args, "pack-objects");
+       strvec_push(&cmd.args, "pack-objects");
 
        strbuf_addstr(&base_name, object_dir);
        strbuf_addstr(&base_name, "/pack/pack");
-       argv_array_push(&cmd.args, base_name.buf);
+       strvec_push(&cmd.args, base_name.buf);
 
        if (delta_base_offset)
-               argv_array_push(&cmd.args, "--delta-base-offset");
+               strvec_push(&cmd.args, "--delta-base-offset");
        if (use_delta_islands)
-               argv_array_push(&cmd.args, "--delta-islands");
+               strvec_push(&cmd.args, "--delta-islands");
 
        if (flags & MIDX_PROGRESS)
-               argv_array_push(&cmd.args, "--progress");
+               strvec_push(&cmd.args, "--progress");
        else
-               argv_array_push(&cmd.args, "-q");
+               strvec_push(&cmd.args, "-q");
 
        strbuf_release(&base_name);
 
@@ -1435,6 +1455,8 @@ int midx_repack(struct repository *r, const char *object_dir, size_t batch_size,
                goto cleanup;
        }
 
+       cmd_in = xfdopen(cmd.in, "w");
+
        for (i = 0; i < m->num_objects; i++) {
                struct object_id oid;
                uint32_t pack_int_id = nth_midxed_pack_int_id(m, i);
@@ -1443,10 +1465,9 @@ int midx_repack(struct repository *r, const char *object_dir, size_t batch_size,
                        continue;
 
                nth_midxed_object_oid(&oid, m, i);
-               xwrite(cmd.in, oid_to_hex(&oid), the_hash_algo->hexsz);
-               xwrite(cmd.in, "\n", 1);
+               fprintf(cmd_in, "%s\n", oid_to_hex(&oid));
        }
-       close(cmd.in);
+       fclose(cmd_in);
 
        if (finish_command(&cmd)) {
                error(_("could not finish pack-objects"));
index f439d47af81d1b8772b181cead999bba28980e21..c4fc9dd74ea81c20830ec1b79788a69faaccaf9a 100644 (file)
@@ -239,12 +239,33 @@ int read_loose_object(const char *path,
                      unsigned long *size,
                      void **contents);
 
+/* Retry packed storage after checking packed and loose storage */
+#define HAS_OBJECT_RECHECK_PACKED 1
+
+/*
+ * Returns 1 if the object exists. This function will not lazily fetch objects
+ * in a partial clone.
+ */
+int has_object(struct repository *r, const struct object_id *oid,
+              unsigned flags);
+
+/*
+ * These macros and functions are deprecated. If checking existence for an
+ * object that is likely to be missing and/or whose absence is relatively
+ * inconsequential (or is consequential but the caller is prepared to handle
+ * it), use has_object(), which has better defaults (no lazy fetch in a partial
+ * clone and no rechecking of packed storage). In the unlikely event that a
+ * caller needs to assert existence of an object that it fully expects to
+ * exist, and wants to trigger a lazy fetch in a partial clone, use
+ * oid_object_info_extended() with a NULL struct object_info.
+ *
+ * These functions can be removed once all callers have migrated to
+ * has_object() and/or oid_object_info_extended().
+ */
 #ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
 #define has_sha1_file_with_flags(sha1, flags) repo_has_sha1_file_with_flags(the_repository, sha1, flags)
 #define has_sha1_file(sha1) repo_has_sha1_file(the_repository, sha1)
 #endif
-
-/* Same as the above, except for struct object_id. */
 int repo_has_object_file(struct repository *r, const struct object_id *oid);
 int repo_has_object_file_with_flags(struct repository *r,
                                    const struct object_id *oid, int flags);
index f0017beb9dd4386399c39b34a2157f9a1c5308d1..685d327d800a5cddfd9e6c35d9b0527ac35ce227 100644 (file)
@@ -38,9 +38,8 @@ static int need_large_offset(off_t offset, const struct pack_idx_option *opts)
 }
 
 /*
- * On entry *sha1 contains the pack content SHA1 hash, on exit it is
- * the SHA1 hash of sorted object names. The objects array passed in
- * will be sorted by SHA1 on exit.
+ * The *sha1 contains the pack content SHA1 hash.
+ * The objects array passed in will be sorted by SHA1 on exit.
  */
 const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects,
                           int nr_objects, const struct pack_idx_option *opts,
diff --git a/pager.c b/pager.c
index 41446d4f0543df18fb2430188d886ed1975a55d9..ee435de67562dc5a3142a153e41672c292924640 100644 (file)
--- a/pager.c
+++ b/pager.c
@@ -68,7 +68,7 @@ const char *git_pager(int stdout_is_tty)
        return pager;
 }
 
-static void setup_pager_env(struct argv_array *env)
+static void setup_pager_env(struct strvec *env)
 {
        const char **argv;
        int i;
@@ -88,7 +88,7 @@ static void setup_pager_env(struct argv_array *env)
                *cp = '\0';
                if (!getenv(argv[i])) {
                        *cp = '=';
-                       argv_array_push(env, argv[i]);
+                       strvec_push(env, argv[i]);
                }
        }
        free(pager_env);
@@ -97,7 +97,7 @@ static void setup_pager_env(struct argv_array *env)
 
 void prepare_pager_args(struct child_process *pager_process, const char *pager)
 {
-       argv_array_push(&pager_process->args, pager);
+       strvec_push(&pager_process->args, pager);
        pager_process->use_shell = 1;
        setup_pager_env(&pager_process->env_array);
        pager_process->trace2_child_class = "pager";
@@ -126,7 +126,7 @@ void setup_pager(void)
        /* spawn the pager */
        prepare_pager_args(&pager_process, pager);
        pager_process.in = -1;
-       argv_array_push(&pager_process.env_array, "GIT_PAGER_IN_USE");
+       strvec_push(&pager_process.env_array, "GIT_PAGER_IN_USE");
        if (start_command(&pager_process))
                return;
 
index 86cd3930136e269ca68759b0113875e0a8e80e8a..d9d3b0819f711ea0db1cfa115832f3b2f616c142 100644 (file)
@@ -4,7 +4,7 @@
 #include "commit.h"
 #include "color.h"
 #include "string-list.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "oid-array.h"
 
 /*----- some often used options -----*/
@@ -275,19 +275,19 @@ int parse_opt_passthru(const struct option *opt, const char *arg, int unset)
 
 /**
  * For an option opt, recreate the command-line option, appending it to
- * opt->value which must be a argv_array. This is useful when we need to pass
+ * opt->value which must be a strvec. This is useful when we need to pass
  * the command-line option, which can be specified multiple times, to another
  * command.
  */
 int parse_opt_passthru_argv(const struct option *opt, const char *arg, int unset)
 {
        static struct strbuf sb = STRBUF_INIT;
-       struct argv_array *opt_value = opt->value;
+       struct strvec *opt_value = opt->value;
 
        if (recreate_opt(&sb, opt, arg, unset) < 0)
                return -1;
 
-       argv_array_push(opt_value, sb.buf);
+       strvec_push(opt_value, sb.buf);
 
        return 0;
 }
index c57618d53736c754cee32b341f7c97d881c3036c..f0507432ee35ba8646a510d1a28ec3561f6bcb30 100644 (file)
@@ -525,7 +525,8 @@ void parse_options_start(struct parse_opt_ctx_t *ctx,
        parse_options_start_1(ctx, argc, argv, prefix, options, flags);
 }
 
-static void show_negated_gitcomp(const struct option *opts, int nr_noopts)
+static void show_negated_gitcomp(const struct option *opts, int show_all,
+                                int nr_noopts)
 {
        int printed_dashdash = 0;
 
@@ -535,7 +536,8 @@ static void show_negated_gitcomp(const struct option *opts, int nr_noopts)
 
                if (!opts->long_name)
                        continue;
-               if (opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NOCOMPLETE))
+               if (!show_all &&
+                       (opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NOCOMPLETE)))
                        continue;
                if (opts->flags & PARSE_OPT_NONEG)
                        continue;
@@ -572,7 +574,7 @@ static void show_negated_gitcomp(const struct option *opts, int nr_noopts)
        }
 }
 
-static int show_gitcomp(const struct option *opts)
+static int show_gitcomp(const struct option *opts, int show_all)
 {
        const struct option *original_opts = opts;
        int nr_noopts = 0;
@@ -582,7 +584,8 @@ static int show_gitcomp(const struct option *opts)
 
                if (!opts->long_name)
                        continue;
-               if (opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NOCOMPLETE))
+               if (!show_all &&
+                       (opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NOCOMPLETE)))
                        continue;
 
                switch (opts->type) {
@@ -610,8 +613,8 @@ static int show_gitcomp(const struct option *opts)
                        nr_noopts++;
                printf(" --%s%s", opts->long_name, suffix);
        }
-       show_negated_gitcomp(original_opts, -1);
-       show_negated_gitcomp(original_opts, nr_noopts);
+       show_negated_gitcomp(original_opts, show_all, -1);
+       show_negated_gitcomp(original_opts, show_all, nr_noopts);
        fputc('\n', stdout);
        return PARSE_OPT_COMPLETE;
 }
@@ -723,9 +726,14 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
                if (internal_help && ctx->total == 1 && !strcmp(arg + 1, "h"))
                        goto show_usage;
 
-               /* lone --git-completion-helper is asked by git-completion.bash */
-               if (ctx->total == 1 && !strcmp(arg + 1, "-git-completion-helper"))
-                       return show_gitcomp(options);
+               /*
+                * lone --git-completion-helper and --git-completion-helper-all
+                * are asked by git-completion.bash
+                */
+               if (ctx->total == 1 && !strcmp(arg, "--git-completion-helper"))
+                       return show_gitcomp(options, 0);
+               if (ctx->total == 1 && !strcmp(arg, "--git-completion-helper-all"))
+                       return show_gitcomp(options, 1);
 
                if (arg[1] != '-') {
                        ctx->opt = arg + 1;
index 46af94209305529253c0308a69db9caabd8b6624..7030d8f3da6328cde9557f91cfd80ae60040cfd6 100644 (file)
@@ -314,7 +314,7 @@ int parse_opt_passthru_argv(const struct option *, const char *, int);
 #define OPT__FORCE(var, h, f) OPT_COUNTUP_F('f', "force",   (var), (h), (f))
 #define OPT__ABBREV(var)  \
        { OPTION_CALLBACK, 0, "abbrev", (var), N_("n"), \
-         N_("use <n> digits to display SHA-1s"),       \
+         N_("use <n> digits to display object names"), \
          PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }
 #define OPT__COLOR(var, h) \
        OPT_COLOR_FLAG(0, "color", (var), (h))
diff --git a/path.c b/path.c
index 8b2c7531919eef89b340b3323d1cbd806ba57b0c..7b385e5eb282276f5d2e0becde48d5e09434d6b1 100644 (file)
--- a/path.c
+++ b/path.c
@@ -1528,8 +1528,6 @@ char *xdg_cache_home(const char *filename)
        return NULL;
 }
 
-REPO_GIT_PATH_FUNC(cherry_pick_head, "CHERRY_PICK_HEAD")
-REPO_GIT_PATH_FUNC(revert_head, "REVERT_HEAD")
 REPO_GIT_PATH_FUNC(squash_msg, "SQUASH_MSG")
 REPO_GIT_PATH_FUNC(merge_msg, "MERGE_MSG")
 REPO_GIT_PATH_FUNC(merge_rr, "MERGE_RR")
diff --git a/path.h b/path.h
index 1f1bf8f87a86d4444879d3fdc0a30076b2c111f3..e7e77da6aaa5cf8e4652141ecf785ee18effeaca 100644 (file)
--- a/path.h
+++ b/path.h
@@ -170,8 +170,6 @@ void report_linked_checkout_garbage(void);
        }
 
 struct path_cache {
-       const char *cherry_pick_head;
-       const char *revert_head;
        const char *squash_msg;
        const char *merge_msg;
        const char *merge_rr;
@@ -182,10 +180,11 @@ struct path_cache {
        const char *shallow;
 };
 
-#define PATH_CACHE_INIT { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+#define PATH_CACHE_INIT                                        \
+       {                                                      \
+               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL \
+       }
 
-const char *git_path_cherry_pick_head(struct repository *r);
-const char *git_path_revert_head(struct repository *r);
 const char *git_path_squash_msg(struct repository *r);
 const char *git_path_merge_msg(struct repository *r);
 const char *git_path_merge_rr(struct repository *r);
index 8243e06eab48373d12729959fde8fe666eb312b2..7a229d8d22f2f67a8e267fda302b53b35a13a3d4 100644 (file)
@@ -3,7 +3,7 @@
 #include "dir.h"
 #include "pathspec.h"
 #include "attr.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "quote.h"
 
 /*
@@ -624,7 +624,7 @@ void parse_pathspec_file(struct pathspec *pathspec, unsigned magic_mask,
                         unsigned flags, const char *prefix,
                         const char *file, int nul_term_line)
 {
-       struct argv_array parsed_file = ARGV_ARRAY_INIT;
+       struct strvec parsed_file = STRVEC_INIT;
        strbuf_getline_fn getline_fn = nul_term_line ? strbuf_getline_nul :
                                                       strbuf_getline;
        struct strbuf buf = STRBUF_INIT;
@@ -643,7 +643,7 @@ void parse_pathspec_file(struct pathspec *pathspec, unsigned magic_mask,
                                die(_("line is badly quoted: %s"), buf.buf);
                        strbuf_swap(&buf, &unquoted);
                }
-               argv_array_push(&parsed_file, buf.buf);
+               strvec_push(&parsed_file, buf.buf);
                strbuf_reset(&buf);
        }
 
@@ -652,8 +652,8 @@ void parse_pathspec_file(struct pathspec *pathspec, unsigned magic_mask,
        if (in != stdin)
                fclose(in);
 
-       parse_pathspec(pathspec, magic_mask, flags, prefix, parsed_file.argv);
-       argv_array_clear(&parsed_file);
+       parse_pathspec(pathspec, magic_mask, flags, prefix, parsed_file.v);
+       strvec_clear(&parsed_file);
 }
 
 void copy_pathspec(struct pathspec *dst, const struct pathspec *src)
index 54c9ed0ddee52e4d5b59b59b74e0dbc738ae3ac9..10df990959e63938e1742d1cdaf0d009b61bee96 100644 (file)
@@ -723,6 +723,32 @@ sub config_int {
        return scalar _config_common({'kind' => '--int'}, @_);
 }
 
+=item config_regexp ( RE )
+
+Retrieve the list of configuration key names matching the regular
+expression C<RE>. The return value is a list of strings matching
+this regex.
+
+=cut
+
+sub config_regexp {
+       my ($self, $regex) = _maybe_self(@_);
+       try {
+               my @cmd = ('config', '--name-only', '--get-regexp', $regex);
+               unshift @cmd, $self if $self;
+               my @matches = command(@cmd);
+               return @matches;
+       } catch Git::Error::Command with {
+               my $E = shift;
+               if ($E->value() == 1) {
+                       my @matches = ();
+                       return @matches;
+               } else {
+                       throw $E;
+               }
+       };
+}
+
 # Common subroutine to implement bulk of what the config* family of methods
 # do. This currently wraps command('config') so it is not so fast.
 sub _config_common {
index d20fc440aba9fd39d9f0290b5d58fded5344fdd9..75b1e75f6ae4b031a1c40b74768af833945a6cf4 100644 (file)
--- a/po/fr.po
+++ b/po/fr.po
@@ -6503,7 +6503,7 @@ msgstr "'%s' ne peut pas Ãªtre résolue comme une branche"
 #: remote.c:1088
 #, c-format
 msgid "unable to delete '%s': remote ref does not exist"
-msgstr "suppression d '%s' impossible : la référence distante n'existe pas"
+msgstr "suppression de '%s' impossible : la référence distante n'existe pas"
 
 #: remote.c:1100
 #, c-format
index 3eda914518bfdcd211552d41b5439125b1ea27ed..31014e6fca0512d16b0fbcc35c7fbfd43426e5c8 100644 (file)
@@ -319,9 +319,12 @@ static void finish_if_sparse(struct progress *progress)
 
 void stop_progress(struct progress **p_progress)
 {
+       if (!p_progress)
+               BUG("don't provide NULL to stop_progress");
+
        finish_if_sparse(*p_progress);
 
-       if (p_progress && *p_progress) {
+       if (*p_progress) {
                trace2_data_intmax("progress", the_repository, "total_objects",
                                   (*p_progress)->total);
 
@@ -338,7 +341,12 @@ void stop_progress(struct progress **p_progress)
 
 void stop_progress_msg(struct progress **p_progress, const char *msg)
 {
-       struct progress *progress = *p_progress;
+       struct progress *progress;
+
+       if (!p_progress)
+               BUG("don't provide NULL to stop_progress_msg");
+
+       progress = *p_progress;
        if (!progress)
                return;
        *p_progress = NULL;
index d1dd3424bbaa56e21950e6b95a56fcde87cd5450..8d964fc65edcff60fe011d540211cb244a60032e 100644 (file)
@@ -21,7 +21,7 @@ enum protocol_version get_protocol_version_config(void)
        const char *git_test_k = "GIT_TEST_PROTOCOL_VERSION";
        const char *git_test_v;
 
-       if (!git_config_get_string_const("protocol.version", &value)) {
+       if (!git_config_get_string_tmp("protocol.version", &value)) {
                enum protocol_version version = parse_protocol_version(value);
 
                if (version == protocol_unknown_version)
diff --git a/quote.c b/quote.c
index bcc0dbc50d9b98bb5317398505d6548c98005c2f..ced0245e801861fc4744fe2a803cab40405dd078 100644 (file)
--- a/quote.c
+++ b/quote.c
@@ -1,6 +1,6 @@
 #include "cache.h"
 #include "quote.h"
-#include "argv-array.h"
+#include "strvec.h"
 
 int quote_path_fully = 1;
 
@@ -172,7 +172,7 @@ char *sq_dequote(char *arg)
 
 static int sq_dequote_to_argv_internal(char *arg,
                                       const char ***argv, int *nr, int *alloc,
-                                      struct argv_array *array)
+                                      struct strvec *array)
 {
        char *next = arg;
 
@@ -187,7 +187,7 @@ static int sq_dequote_to_argv_internal(char *arg,
                        (*argv)[(*nr)++] = dequoted;
                }
                if (array)
-                       argv_array_push(array, dequoted);
+                       strvec_push(array, dequoted);
        } while (next);
 
        return 0;
@@ -198,7 +198,7 @@ int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc)
        return sq_dequote_to_argv_internal(arg, argv, nr, alloc, NULL);
 }
 
-int sq_dequote_to_argv_array(char *arg, struct argv_array *array)
+int sq_dequote_to_strvec(char *arg, struct strvec *array)
 {
        return sq_dequote_to_argv_internal(arg, NULL, NULL, NULL, array);
 }
diff --git a/quote.h b/quote.h
index ca8ee3144a6ad2440cce047f7c7afce66f0a8bed..fa09309cf6890fa82b4034dcdf957a59e0339d14 100644 (file)
--- a/quote.h
+++ b/quote.h
@@ -56,12 +56,12 @@ char *sq_dequote(char *);
 int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc);
 
 /*
- * Same as above, but store the unquoted strings in an argv_array. We will
- * still modify arg in place, but unlike sq_dequote_to_argv, the argv_array
+ * Same as above, but store the unquoted strings in a strvec. We will
+ * still modify arg in place, but unlike sq_dequote_to_argv, the strvec
  * will duplicate and take ownership of the strings.
  */
-struct argv_array;
-int sq_dequote_to_argv_array(char *arg, struct argv_array *);
+struct strvec;
+int sq_dequote_to_strvec(char *arg, struct strvec *);
 
 int unquote_c_style(struct strbuf *, const char *quoted, const char **endp);
 size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq);
index 40af0862818c15d6c432da1d02fbe1ba7cadf230..24dc435e482c0364ebc88e7ad55930f437d73ad2 100644 (file)
@@ -2,7 +2,7 @@
 #include "range-diff.h"
 #include "string-list.h"
 #include "run-command.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "hashmap.h"
 #include "xdiff-interface.h"
 #include "linear-assignment.h"
@@ -41,7 +41,7 @@ static size_t find_end_of_line(char *buffer, unsigned long size)
  * as struct object_id (will need to be free()d).
  */
 static int read_patches(const char *range, struct string_list *list,
-                       const struct argv_array *other_arg)
+                       const struct strvec *other_arg)
 {
        struct child_process cp = CHILD_PROCESS_INIT;
        struct strbuf buf = STRBUF_INIT, contents = STRBUF_INIT;
@@ -51,24 +51,24 @@ static int read_patches(const char *range, struct string_list *list,
        int offset, len;
        size_t size;
 
-       argv_array_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
-                       "--reverse", "--date-order", "--decorate=no",
-                       "--no-prefix",
-                       /*
-                        * Choose indicators that are not used anywhere
-                        * else in diffs, but still look reasonable
-                        * (e.g. will not be confusing when debugging)
-                        */
-                       "--output-indicator-new=>",
-                       "--output-indicator-old=<",
-                       "--output-indicator-context=#",
-                       "--no-abbrev-commit",
-                       "--pretty=medium",
-                       "--notes",
-                       NULL);
+       strvec_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
+                    "--reverse", "--date-order", "--decorate=no",
+                    "--no-prefix",
+                    /*
+                     * Choose indicators that are not used anywhere
+                     * else in diffs, but still look reasonable
+                     * (e.g. will not be confusing when debugging)
+                     */
+                    "--output-indicator-new=>",
+                    "--output-indicator-old=<",
+                    "--output-indicator-context=#",
+                    "--no-abbrev-commit",
+                    "--pretty=medium",
+                    "--notes",
+                    NULL);
        if (other_arg)
-               argv_array_pushv(&cp.args, other_arg->argv);
-       argv_array_push(&cp.args, range);
+               strvec_pushv(&cp.args, other_arg->v);
+       strvec_push(&cp.args, range);
        cp.out = -1;
        cp.no_stdin = 1;
        cp.git_cmd = 1;
@@ -523,7 +523,7 @@ static struct strbuf *output_prefix_cb(struct diff_options *opt, void *data)
 int show_range_diff(const char *range1, const char *range2,
                    int creation_factor, int dual_color,
                    const struct diff_options *diffopt,
-                   const struct argv_array *other_arg)
+                   const struct strvec *other_arg)
 {
        int res = 0;
 
index e11976dc81baf21542e39eb113adf1fe9e37e9c2..583ced2e8e749003b9a22fe2496d0db49f5ba7f9 100644 (file)
@@ -2,7 +2,7 @@
 #define RANGE_DIFF_H
 
 #include "diff.h"
-#include "argv-array.h"
+#include "strvec.h"
 
 #define RANGE_DIFF_CREATION_FACTOR_DEFAULT 60
 
@@ -14,6 +14,6 @@
 int show_range_diff(const char *range1, const char *range2,
                    int creation_factor, int dual_color,
                    const struct diff_options *diffopt,
-                   const struct argv_array *other_arg);
+                   const struct strvec *other_arg);
 
 #endif
index aa427c5c170f02c0c2300f4de5e16a03c83dd975..fa291cdbee0bb435122194c3e0fa8efdb750c47e 100644 (file)
@@ -89,8 +89,10 @@ static struct mem_pool *find_mem_pool(struct index_state *istate)
        else
                pool_ptr = &istate->ce_mem_pool;
 
-       if (!*pool_ptr)
-               mem_pool_init(pool_ptr, 0);
+       if (!*pool_ptr) {
+               *pool_ptr = xmalloc(sizeof(**pool_ptr));
+               mem_pool_init(*pool_ptr, 0);
+       }
 
        return *pool_ptr;
 }
@@ -1171,20 +1173,6 @@ static int has_dir_name(struct index_state *istate,
                                return retval;
                        }
 
-                       if (istate->cache_nr > 0 &&
-                               ce_namelen(istate->cache[istate->cache_nr - 1]) > len) {
-                               /*
-                                * The directory prefix lines up with part of
-                                * a longer file or directory name, but sorts
-                                * after it, so this sub-directory cannot
-                                * collide with a file.
-                                *
-                                * last: xxx/yy-file (because '-' sorts before '/')
-                                * this: xxx/yy/abc
-                                */
-                               return retval;
-                       }
-
                        /*
                         * This is a possible collision. Fall through and
                         * let the regular search code handle it.
@@ -2020,11 +2008,12 @@ static unsigned long load_all_cache_entries(struct index_state *istate,
 {
        unsigned long consumed;
 
+       istate->ce_mem_pool = xmalloc(sizeof(*istate->ce_mem_pool));
        if (istate->version == 4) {
-               mem_pool_init(&istate->ce_mem_pool,
+               mem_pool_init(istate->ce_mem_pool,
                                estimate_cache_size_from_compressed(istate->cache_nr));
        } else {
-               mem_pool_init(&istate->ce_mem_pool,
+               mem_pool_init(istate->ce_mem_pool,
                                estimate_cache_size(mmap_size, istate->cache_nr));
        }
 
@@ -2084,7 +2073,8 @@ static unsigned long load_cache_entries_threaded(struct index_state *istate, con
        if (istate->name_hash_initialized)
                BUG("the name hash isn't thread safe");
 
-       mem_pool_init(&istate->ce_mem_pool, 0);
+       istate->ce_mem_pool = xmalloc(sizeof(*istate->ce_mem_pool));
+       mem_pool_init(istate->ce_mem_pool, 0);
 
        /* ensure we have no more threads than we have blocks to process */
        if (nr_threads > ieot->nr)
@@ -2111,11 +2101,12 @@ static unsigned long load_cache_entries_threaded(struct index_state *istate, con
                nr = 0;
                for (j = p->ieot_start; j < p->ieot_start + p->ieot_blocks; j++)
                        nr += p->ieot->entries[j].nr;
+               istate->ce_mem_pool = xmalloc(sizeof(*istate->ce_mem_pool));
                if (istate->version == 4) {
-                       mem_pool_init(&p->ce_mem_pool,
+                       mem_pool_init(p->ce_mem_pool,
                                estimate_cache_size_from_compressed(nr));
                } else {
-                       mem_pool_init(&p->ce_mem_pool,
+                       mem_pool_init(p->ce_mem_pool,
                                estimate_cache_size(mmap_size, nr));
                }
 
@@ -2372,7 +2363,7 @@ int discard_index(struct index_state *istate)
 
        if (istate->ce_mem_pool) {
                mem_pool_discard(istate->ce_mem_pool, should_validate_cache_entries());
-               istate->ce_mem_pool = NULL;
+               FREE_AND_NULL(istate->ce_mem_pool);
        }
 
        return 0;
index 8447cb09be0c2741b5a20426e6c0db104339fa7e..8ba0e31915021e3d60b814332c6a10c10f3a147e 100644 (file)
@@ -22,7 +22,7 @@
 #include "commit-reach.h"
 #include "worktree.h"
 #include "hashmap.h"
-#include "argv-array.h"
+#include "strvec.h"
 
 static struct ref_msg {
        const char *gone;
@@ -127,7 +127,8 @@ static struct used_atom {
                        unsigned int nobracket : 1, push : 1, push_remote : 1;
                } remote_ref;
                struct {
-                       enum { C_BARE, C_BODY, C_BODY_DEP, C_LINES, C_SIG, C_SUB, C_TRAILERS } option;
+                       enum { C_BARE, C_BODY, C_BODY_DEP, C_LENGTH,
+                              C_LINES, C_SIG, C_SUB, C_TRAILERS } option;
                        struct process_trailer_options trailer_opts;
                        unsigned int nlines;
                } contents;
@@ -338,13 +339,17 @@ static int contents_atom_parser(const struct ref_format *format, struct used_ato
                atom->u.contents.option = C_BARE;
        else if (!strcmp(arg, "body"))
                atom->u.contents.option = C_BODY;
+       else if (!strcmp(arg, "size"))
+               atom->u.contents.option = C_LENGTH;
        else if (!strcmp(arg, "signature"))
                atom->u.contents.option = C_SIG;
        else if (!strcmp(arg, "subject"))
                atom->u.contents.option = C_SUB;
-       else if (skip_prefix(arg, "trailers", &arg)) {
-               skip_prefix(arg, ":", &arg);
-               if (trailers_atom_parser(format, atom, *arg ? arg : NULL, err))
+       else if (!strcmp(arg, "trailers")) {
+               if (trailers_atom_parser(format, atom, NULL, err))
+                       return -1;
+       } else if (skip_prefix(arg, "trailers:", &arg)) {
+               if (trailers_atom_parser(format, atom, arg, err))
                        return -1;
        } else if (skip_prefix(arg, "lines=", &arg)) {
                atom->u.contents.option = C_LINES;
@@ -1253,6 +1258,8 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf)
                        v->s = copy_subject(subpos, sublen);
                else if (atom->u.contents.option == C_BODY_DEP)
                        v->s = xmemdupz(bodypos, bodylen);
+               else if (atom->u.contents.option == C_LENGTH)
+                       v->s = xstrfmt("%"PRIuMAX, (uintmax_t)strlen(subpos));
                else if (atom->u.contents.option == C_BODY)
                        v->s = xmemdupz(bodypos, nonsiglen);
                else if (atom->u.contents.option == C_SIG)
@@ -1914,15 +1921,15 @@ static void find_longest_prefixes_1(struct string_list *out,
 static void find_longest_prefixes(struct string_list *out,
                                  const char **patterns)
 {
-       struct argv_array sorted = ARGV_ARRAY_INIT;
+       struct strvec sorted = STRVEC_INIT;
        struct strbuf prefix = STRBUF_INIT;
 
-       argv_array_pushv(&sorted, patterns);
-       QSORT(sorted.argv, sorted.argc, qsort_strcmp);
+       strvec_pushv(&sorted, patterns);
+       QSORT(sorted.v, sorted.nr, qsort_strcmp);
 
-       find_longest_prefixes_1(out, &prefix, sorted.argv, sorted.argc);
+       find_longest_prefixes_1(out, &prefix, sorted.v, sorted.nr);
 
-       argv_array_clear(&sorted);
+       strvec_clear(&sorted);
        strbuf_release(&prefix);
 }
 
@@ -1980,7 +1987,7 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
  * of oids. If the given ref is a tag, check if the given tag points
  * at one of the oids in the given oid array.
  * NEEDSWORK:
- * 1. Only a single level of inderection is obtained, we might want to
+ * 1. Only a single level of indirection is obtained, we might want to
  * change this to account for multiple levels (e.g. annotated tags
  * pointing to annotated tags pointing to a commit.)
  * 2. As the refs are cached we might know what refname peels to without
diff --git a/refs.c b/refs.c
index 639cba93b4e0a78697a55995c926adc3e05d5126..6aa4893996076a4c104055e884df2f4720c85dbf 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -15,7 +15,7 @@
 #include "tag.h"
 #include "submodule.h"
 #include "worktree.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "repository.h"
 #include "sigchain.h"
 
@@ -313,7 +313,7 @@ int read_ref(const char *refname, struct object_id *oid)
        return read_ref_full(refname, RESOLVE_REF_READING, oid, NULL);
 }
 
-static int refs_ref_exists(struct ref_store *refs, const char *refname)
+int refs_ref_exists(struct ref_store *refs, const char *refname)
 {
        return !!refs_resolve_ref_unsafe(refs, refname, RESOLVE_REF_READING, NULL, NULL);
 }
@@ -553,13 +553,13 @@ int refname_match(const char *abbrev_name, const char *full_name)
  * Given a 'prefix' expand it by the rules in 'ref_rev_parse_rules' and add
  * the results to 'prefixes'
  */
-void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
+void expand_ref_prefix(struct strvec *prefixes, const char *prefix)
 {
        const char **p;
        int len = strlen(prefix);
 
        for (p = ref_rev_parse_rules; *p; p++)
-               argv_array_pushf(prefixes, *p, len, prefix);
+               strvec_pushf(prefixes, *p, len, prefix);
 }
 
 char *repo_default_branch_name(struct repository *r)
@@ -708,10 +708,9 @@ int dwim_log(const char *str, int len, struct object_id *oid, char **log)
 
 static int is_per_worktree_ref(const char *refname)
 {
-       return !strcmp(refname, "HEAD") ||
-               starts_with(refname, "refs/worktree/") ||
-               starts_with(refname, "refs/bisect/") ||
-               starts_with(refname, "refs/rewritten/");
+       return starts_with(refname, "refs/worktree/") ||
+              starts_with(refname, "refs/bisect/") ||
+              starts_with(refname, "refs/rewritten/");
 }
 
 static int is_pseudoref_syntax(const char *refname)
@@ -771,102 +770,6 @@ long get_files_ref_lock_timeout_ms(void)
        return timeout_ms;
 }
 
-static int write_pseudoref(const char *pseudoref, const struct object_id *oid,
-                          const struct object_id *old_oid, struct strbuf *err)
-{
-       const char *filename;
-       int fd;
-       struct lock_file lock = LOCK_INIT;
-       struct strbuf buf = STRBUF_INIT;
-       int ret = -1;
-
-       if (!oid)
-               return 0;
-
-       strbuf_addf(&buf, "%s\n", oid_to_hex(oid));
-
-       filename = git_path("%s", pseudoref);
-       fd = hold_lock_file_for_update_timeout(&lock, filename, 0,
-                                              get_files_ref_lock_timeout_ms());
-       if (fd < 0) {
-               strbuf_addf(err, _("could not open '%s' for writing: %s"),
-                           filename, strerror(errno));
-               goto done;
-       }
-
-       if (old_oid) {
-               struct object_id actual_old_oid;
-
-               if (read_ref(pseudoref, &actual_old_oid)) {
-                       if (!is_null_oid(old_oid)) {
-                               strbuf_addf(err, _("could not read ref '%s'"),
-                                           pseudoref);
-                               rollback_lock_file(&lock);
-                               goto done;
-                       }
-               } else if (is_null_oid(old_oid)) {
-                       strbuf_addf(err, _("ref '%s' already exists"),
-                                   pseudoref);
-                       rollback_lock_file(&lock);
-                       goto done;
-               } else if (!oideq(&actual_old_oid, old_oid)) {
-                       strbuf_addf(err, _("unexpected object ID when writing '%s'"),
-                                   pseudoref);
-                       rollback_lock_file(&lock);
-                       goto done;
-               }
-       }
-
-       if (write_in_full(fd, buf.buf, buf.len) < 0) {
-               strbuf_addf(err, _("could not write to '%s'"), filename);
-               rollback_lock_file(&lock);
-               goto done;
-       }
-
-       commit_lock_file(&lock);
-       ret = 0;
-done:
-       strbuf_release(&buf);
-       return ret;
-}
-
-static int delete_pseudoref(const char *pseudoref, const struct object_id *old_oid)
-{
-       const char *filename;
-
-       filename = git_path("%s", pseudoref);
-
-       if (old_oid && !is_null_oid(old_oid)) {
-               struct lock_file lock = LOCK_INIT;
-               int fd;
-               struct object_id actual_old_oid;
-
-               fd = hold_lock_file_for_update_timeout(
-                               &lock, filename, 0,
-                               get_files_ref_lock_timeout_ms());
-               if (fd < 0) {
-                       error_errno(_("could not open '%s' for writing"),
-                                   filename);
-                       return -1;
-               }
-               if (read_ref(pseudoref, &actual_old_oid))
-                       die(_("could not read ref '%s'"), pseudoref);
-               if (!oideq(&actual_old_oid, old_oid)) {
-                       error(_("unexpected object ID when deleting '%s'"),
-                             pseudoref);
-                       rollback_lock_file(&lock);
-                       return -1;
-               }
-
-               unlink(filename);
-               rollback_lock_file(&lock);
-       } else {
-               unlink(filename);
-       }
-
-       return 0;
-}
-
 int refs_delete_ref(struct ref_store *refs, const char *msg,
                    const char *refname,
                    const struct object_id *old_oid,
@@ -875,11 +778,6 @@ int refs_delete_ref(struct ref_store *refs, const char *msg,
        struct ref_transaction *transaction;
        struct strbuf err = STRBUF_INIT;
 
-       if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
-               assert(refs == get_main_ref_store(the_repository));
-               return delete_pseudoref(refname, old_oid);
-       }
-
        transaction = ref_store_transaction_begin(refs, &err);
        if (!transaction ||
            ref_transaction_delete(transaction, refname, old_oid,
@@ -902,12 +800,11 @@ int delete_ref(const char *msg, const char *refname,
                               old_oid, flags);
 }
 
-void copy_reflog_msg(struct strbuf *sb, const char *msg)
+static void copy_reflog_msg(struct strbuf *sb, const char *msg)
 {
        char c;
        int wasspace = 1;
 
-       strbuf_addch(sb, '\t');
        while ((c = *msg++)) {
                if (wasspace && isspace(c))
                        continue;
@@ -919,6 +816,15 @@ void copy_reflog_msg(struct strbuf *sb, const char *msg)
        strbuf_rtrim(sb);
 }
 
+static char *normalize_reflog_message(const char *msg)
+{
+       struct strbuf sb = STRBUF_INIT;
+
+       if (msg && *msg)
+               copy_reflog_msg(&sb, msg);
+       return strbuf_detach(&sb, NULL);
+}
+
 int should_autocreate_reflog(const char *refname)
 {
        switch (log_all_ref_updates) {
@@ -1124,7 +1030,7 @@ struct ref_update *ref_transaction_add_update(
                oidcpy(&update->new_oid, new_oid);
        if (flags & REF_HAVE_OLD)
                oidcpy(&update->old_oid, old_oid);
-       update->msg = xstrdup_or_null(msg);
+       update->msg = normalize_reflog_message(msg);
        return update;
 }
 
@@ -1202,18 +1108,13 @@ int refs_update_ref(struct ref_store *refs, const char *msg,
        struct strbuf err = STRBUF_INIT;
        int ret = 0;
 
-       if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
-               assert(refs == get_main_ref_store(the_repository));
-               ret = write_pseudoref(refname, new_oid, old_oid, &err);
-       } else {
-               t = ref_store_transaction_begin(refs, &err);
-               if (!t ||
-                   ref_transaction_update(t, refname, new_oid, old_oid,
-                                          flags, msg, &err) ||
-                   ref_transaction_commit(t, &err)) {
-                       ret = 1;
-                       ref_transaction_free(t);
-               }
+       t = ref_store_transaction_begin(refs, &err);
+       if (!t ||
+           ref_transaction_update(t, refname, new_oid, old_oid, flags, msg,
+                                  &err) ||
+           ref_transaction_commit(t, &err)) {
+               ret = 1;
+               ref_transaction_free(t);
        }
        if (ret) {
                const char *str = _("update_ref failed for ref '%s': %s");
@@ -1626,11 +1527,37 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
        return refs_for_each_rawref(get_main_ref_store(the_repository), fn, cb_data);
 }
 
+static int refs_read_special_head(struct ref_store *ref_store,
+                                 const char *refname, struct object_id *oid,
+                                 struct strbuf *referent, unsigned int *type)
+{
+       struct strbuf full_path = STRBUF_INIT;
+       struct strbuf content = STRBUF_INIT;
+       int result = -1;
+       strbuf_addf(&full_path, "%s/%s", ref_store->gitdir, refname);
+
+       if (strbuf_read_file(&content, full_path.buf, 0) < 0)
+               goto done;
+
+       result = parse_loose_ref_contents(content.buf, oid, referent, type);
+
+done:
+       strbuf_release(&full_path);
+       strbuf_release(&content);
+       return result;
+}
+
 int refs_read_raw_ref(struct ref_store *ref_store,
                      const char *refname, struct object_id *oid,
                      struct strbuf *referent, unsigned int *type)
 {
-       return ref_store->be->read_raw_ref(ref_store, refname, oid, referent, type);
+       if (!strcmp(refname, "FETCH_HEAD") || !strcmp(refname, "MERGE_HEAD")) {
+               return refs_read_special_head(ref_store, refname, oid, referent,
+                                             type);
+       }
+
+       return ref_store->be->read_raw_ref(ref_store, refname, oid, referent,
+                                          type);
 }
 
 /* This function needs to return a meaningful errno on failure */
@@ -1983,9 +1910,14 @@ int refs_create_symref(struct ref_store *refs,
                       const char *refs_heads_master,
                       const char *logmsg)
 {
-       return refs->be->create_symref(refs, ref_target,
-                                      refs_heads_master,
-                                      logmsg);
+       char *msg;
+       int retval;
+
+       msg = normalize_reflog_message(logmsg);
+       retval = refs->be->create_symref(refs, ref_target, refs_heads_master,
+                                        msg);
+       free(msg);
+       return retval;
 }
 
 int create_symref(const char *ref_target, const char *refs_heads_master,
@@ -2031,13 +1963,13 @@ static int run_transaction_hook(struct ref_transaction *transaction,
        if (hook == &hook_not_found)
                return ret;
        if (!hook)
-               hook = find_hook("reference-transaction");
+               hook = xstrdup_or_null(find_hook("reference-transaction"));
        if (!hook) {
                hook = &hook_not_found;
                return ret;
        }
 
-       argv_array_pushl(&proc.args, hook, state, NULL);
+       strvec_pushl(&proc.args, hook, state, NULL);
        proc.in = -1;
        proc.stdout_to_stderr = 1;
        proc.trace2_hook_name = "reference-transaction";
@@ -2370,10 +2302,16 @@ int initial_ref_transaction_commit(struct ref_transaction *transaction,
        return refs->be->initial_transaction_commit(refs, transaction, err);
 }
 
-int refs_delete_refs(struct ref_store *refs, const char *msg,
+int refs_delete_refs(struct ref_store *refs, const char *logmsg,
                     struct string_list *refnames, unsigned int flags)
 {
-       return refs->be->delete_refs(refs, msg, refnames, flags);
+       char *msg;
+       int retval;
+
+       msg = normalize_reflog_message(logmsg);
+       retval = refs->be->delete_refs(refs, msg, refnames, flags);
+       free(msg);
+       return retval;
 }
 
 int delete_refs(const char *msg, struct string_list *refnames,
@@ -2385,7 +2323,13 @@ int delete_refs(const char *msg, struct string_list *refnames,
 int refs_rename_ref(struct ref_store *refs, const char *oldref,
                    const char *newref, const char *logmsg)
 {
-       return refs->be->rename_ref(refs, oldref, newref, logmsg);
+       char *msg;
+       int retval;
+
+       msg = normalize_reflog_message(logmsg);
+       retval = refs->be->rename_ref(refs, oldref, newref, msg);
+       free(msg);
+       return retval;
 }
 
 int rename_ref(const char *oldref, const char *newref, const char *logmsg)
@@ -2396,7 +2340,13 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
 int refs_copy_existing_ref(struct ref_store *refs, const char *oldref,
                    const char *newref, const char *logmsg)
 {
-       return refs->be->copy_ref(refs, oldref, newref, logmsg);
+       char *msg;
+       int retval;
+
+       msg = normalize_reflog_message(logmsg);
+       retval = refs->be->copy_ref(refs, oldref, newref, msg);
+       free(msg);
+       return retval;
 }
 
 int copy_existing_ref(const char *oldref, const char *newref, const char *logmsg)
diff --git a/refs.h b/refs.h
index f212f8945e10a5a041a7f1c49a07f8f468589748..04bd25019f344b72a3e05470f675dab9b4ffc19d 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -105,6 +105,8 @@ int refs_verify_refname_available(struct ref_store *refs,
                                  const struct string_list *skip,
                                  struct strbuf *err);
 
+int refs_ref_exists(struct ref_store *refs, const char *refname);
+
 int ref_exists(const char *refname);
 
 int should_autocreate_reflog(const char *refname);
@@ -145,8 +147,8 @@ int refname_match(const char *abbrev_name, const char *full_name);
  * Given a 'prefix' expand it by the rules in 'ref_rev_parse_rules' and add
  * the results to 'prefixes'
  */
-struct argv_array;
-void expand_ref_prefix(struct argv_array *prefixes, const char *prefix);
+struct strvec;
+void expand_ref_prefix(struct strvec *prefixes, const char *prefix);
 
 int expand_ref(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
 int repo_dwim_ref(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
index 6516c7bc8c8fea09cfd296c5c4185332b8358d06..dd712e47f4190e6a0f7a1a5ecc446790827e9563 100644 (file)
@@ -67,7 +67,6 @@ struct files_ref_store {
        struct ref_store base;
        unsigned int store_flags;
 
-       char *gitdir;
        char *gitcommondir;
 
        struct ref_cache *loose;
@@ -94,18 +93,17 @@ static struct ref_store *files_ref_store_create(const char *gitdir,
        struct ref_store *ref_store = (struct ref_store *)refs;
        struct strbuf sb = STRBUF_INIT;
 
+       ref_store->gitdir = xstrdup(gitdir);
        base_ref_store_init(ref_store, &refs_be_files);
        refs->store_flags = flags;
 
-       refs->gitdir = xstrdup(gitdir);
        get_common_dir_noenv(&sb, gitdir);
        refs->gitcommondir = strbuf_detach(&sb, NULL);
        strbuf_addf(&sb, "%s/packed-refs", refs->gitcommondir);
        refs->packed_ref_store = packed_ref_store_create(sb.buf, flags);
        strbuf_release(&sb);
 
-       chdir_notify_reparent("files-backend $GIT_DIR",
-                             &refs->gitdir);
+       chdir_notify_reparent("files-backend $GIT_DIR", &refs->base.gitdir);
        chdir_notify_reparent("files-backend $GIT_COMMONDIR",
                              &refs->gitcommondir);
 
@@ -176,7 +174,7 @@ static void files_reflog_path(struct files_ref_store *refs,
        switch (ref_type(refname)) {
        case REF_TYPE_PER_WORKTREE:
        case REF_TYPE_PSEUDOREF:
-               strbuf_addf(sb, "%s/logs/%s", refs->gitdir, refname);
+               strbuf_addf(sb, "%s/logs/%s", refs->base.gitdir, refname);
                break;
        case REF_TYPE_OTHER_PSEUDOREF:
        case REF_TYPE_MAIN_PSEUDOREF:
@@ -198,7 +196,7 @@ static void files_ref_path(struct files_ref_store *refs,
        switch (ref_type(refname)) {
        case REF_TYPE_PER_WORKTREE:
        case REF_TYPE_PSEUDOREF:
-               strbuf_addf(sb, "%s/%s", refs->gitdir, refname);
+               strbuf_addf(sb, "%s/%s", refs->base.gitdir, refname);
                break;
        case REF_TYPE_MAIN_PSEUDOREF:
                if (!skip_prefix(refname, "main-worktree/", &refname))
@@ -360,7 +358,6 @@ static int files_read_raw_ref(struct ref_store *ref_store,
        struct strbuf sb_path = STRBUF_INIT;
        const char *path;
        const char *buf;
-       const char *p;
        struct stat st;
        int fd;
        int ret = -1;
@@ -465,6 +462,21 @@ stat_ref:
        close(fd);
        strbuf_rtrim(&sb_contents);
        buf = sb_contents.buf;
+
+       ret = parse_loose_ref_contents(buf, oid, referent, type);
+
+out:
+       save_errno = errno;
+       strbuf_release(&sb_path);
+       strbuf_release(&sb_contents);
+       errno = save_errno;
+       return ret;
+}
+
+int parse_loose_ref_contents(const char *buf, struct object_id *oid,
+                            struct strbuf *referent, unsigned int *type)
+{
+       const char *p;
        if (skip_prefix(buf, "ref:", &buf)) {
                while (isspace(*buf))
                        buf++;
@@ -472,29 +484,19 @@ stat_ref:
                strbuf_reset(referent);
                strbuf_addstr(referent, buf);
                *type |= REF_ISSYMREF;
-               ret = 0;
-               goto out;
+               return 0;
        }
 
        /*
-        * Please note that FETCH_HEAD has additional
-        * data after the sha.
+        * FETCH_HEAD has additional data after the sha.
         */
        if (parse_oid_hex(buf, oid, &p) ||
            (*p != '\0' && !isspace(*p))) {
                *type |= REF_ISBROKEN;
                errno = EINVAL;
-               goto out;
+               return -1;
        }
-
-       ret = 0;
-
-out:
-       save_errno = errno;
-       strbuf_release(&sb_path);
-       strbuf_release(&sb_contents);
-       errno = save_errno;
-       return ret;
+       return 0;
 }
 
 static void unlock_ref(struct ref_lock *lock)
@@ -1628,8 +1630,10 @@ static int log_ref_write_fd(int fd, const struct object_id *old_oid,
        int ret = 0;
 
        strbuf_addf(&sb, "%s %s %s", oid_to_hex(old_oid), oid_to_hex(new_oid), committer);
-       if (msg && *msg)
-               copy_reflog_msg(&sb, msg);
+       if (msg && *msg) {
+               strbuf_addch(&sb, '\t');
+               strbuf_addstr(&sb, msg);
+       }
        strbuf_addch(&sb, '\n');
        if (write_in_full(fd, sb.buf, sb.len) < 0)
                ret = -1;
@@ -2197,12 +2201,11 @@ static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_st
                files_downcast(ref_store, REF_STORE_READ,
                               "reflog_iterator_begin");
 
-       if (!strcmp(refs->gitdir, refs->gitcommondir)) {
+       if (!strcmp(refs->base.gitdir, refs->gitcommondir)) {
                return reflog_iterator_begin(ref_store, refs->gitcommondir);
        } else {
                return merge_ref_iterator_begin(
-                       0,
-                       reflog_iterator_begin(ref_store, refs->gitdir),
+                       0, reflog_iterator_begin(ref_store, refs->base.gitdir),
                        reflog_iterator_begin(ref_store, refs->gitcommondir),
                        reflog_iterator_select, refs);
        }
index 4458a0f69ccb216681dc515bd2986ecdce456c0f..b912f2505fee298225d3daa5719cbe6bdeba2365 100644 (file)
@@ -200,6 +200,7 @@ struct ref_store *packed_ref_store_create(const char *path,
        struct ref_store *ref_store = (struct ref_store *)refs;
 
        base_ref_store_init(ref_store, &refs_be_packed);
+       ref_store->gitdir = xstrdup(path);
        refs->store_flags = store_flags;
 
        refs->path = xstrdup(path);
index 4271362d26458f8fffca016684d0b47f00307f75..527b0a6e2e636b129cfcff2a88c1c112c41a8c57 100644 (file)
@@ -96,12 +96,6 @@ enum peel_status {
  */
 enum peel_status peel_object(const struct object_id *name, struct object_id *oid);
 
-/*
- * Copy the reflog message msg to sb while cleaning up the whitespaces.
- * Especially, convert LF to space, because reflog file is one line per entry.
- */
-void copy_reflog_msg(struct strbuf *sb, const char *msg);
-
 /**
  * Information needed for a single ref update. Set new_oid to the new
  * value or to null_oid to delete the ref. To check the old value
@@ -673,13 +667,22 @@ extern struct ref_storage_be refs_be_packed;
 /*
  * A representation of the reference store for the main repository or
  * a submodule. The ref_store instances for submodules are kept in a
- * linked list.
+ * hash map; see get_submodule_ref_store() for more info.
  */
 struct ref_store {
        /* The backend describing this ref_store's storage scheme: */
        const struct ref_storage_be *be;
+
+       /* The gitdir that this ref_store applies to: */
+       char *gitdir;
 };
 
+/*
+ * Parse contents of a loose ref file.
+ */
+int parse_loose_ref_contents(const char *buf, struct object_id *oid,
+                            struct strbuf *referent, unsigned int *type);
+
 /*
  * Fill in the generic part of refs and add it to our collection of
  * reference stores.
index 9a9bf21934afb74e34b8cef1042860824f4c7282..f10ef284cef95aef60b8b485f5909ba9a8c76b50 100644 (file)
--- a/refspec.c
+++ b/refspec.c
@@ -1,5 +1,5 @@
 #include "cache.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "refs.h"
 #include "refspec.h"
 
@@ -202,7 +202,7 @@ int valid_fetch_refspec(const char *fetch_refspec_str)
 }
 
 void refspec_ref_prefixes(const struct refspec *rs,
-                         struct argv_array *ref_prefixes)
+                         struct strvec *ref_prefixes)
 {
        int i;
        for (i = 0; i < rs->nr; i++) {
@@ -221,9 +221,9 @@ void refspec_ref_prefixes(const struct refspec *rs,
                if (prefix) {
                        if (item->pattern) {
                                const char *glob = strchr(prefix, '*');
-                               argv_array_pushf(ref_prefixes, "%.*s",
-                                                (int)(glob - prefix),
-                                                prefix);
+                               strvec_pushf(ref_prefixes, "%.*s",
+                                            (int)(glob - prefix),
+                                            prefix);
                        } else {
                                expand_ref_prefix(ref_prefixes, prefix);
                        }
index 3f2bd4aaa5e04e744ee8c5411523b689660f1a38..8d654e3a3ac40940c7d05f7ce671f538b7d250f2 100644 (file)
--- a/refspec.h
+++ b/refspec.h
@@ -4,6 +4,19 @@
 #define TAG_REFSPEC "refs/tags/*:refs/tags/*"
 extern const struct refspec_item *tag_refspec;
 
+/**
+ * A struct refspec_item holds the parsed interpretation of a refspec.  If it will
+ * force updates (starts with a '+'), force is true.  If it is a pattern
+ * (sides end with '*') pattern is true.  src and dest are the two sides
+ * (including '*' characters if present); if there is only one side, it is src,
+ * and dst is NULL; if sides exist but are empty (i.e., the refspec either
+ * starts or ends with ':'), the corresponding side is "".
+ *
+ * remote_find_tracking(), given a remote and a struct refspec_item with either src
+ * or dst filled out, will fill out the other such that the result is in the
+ * "fetch" specification for the remote (note that this evaluates patterns and
+ * returns a single result).
+ */
 struct refspec_item {
        unsigned force : 1;
        unsigned pattern : 1;
@@ -21,20 +34,8 @@ struct refspec_item {
 #define REFSPEC_INIT_PUSH { .fetch = REFSPEC_PUSH }
 
 /**
- * A struct refspec holds the parsed interpretation of a refspec.  If it will
- * force updates (starts with a '+'), force is true.  If it is a pattern
- * (sides end with '*') pattern is true.  src and dest are the two sides
- * (including '*' characters if present); if there is only one side, it is src,
- * and dst is NULL; if sides exist but are empty (i.e., the refspec either
- * starts or ends with ':'), the corresponding side is "".
- *
- * An array of strings can be parsed into an array of struct refspecs using
+ * An array of strings can be parsed into a struct refspec using
  * parse_fetch_refspec() or parse_push_refspec().
- *
- * remote_find_tracking(), given a remote and a struct refspec with either src
- * or dst filled out, will fill out the other such that the result is in the
- * "fetch" specification for the remote (note that this evaluates patterns and
- * returns a single result).
  */
 struct refspec {
        struct refspec_item *items;
@@ -60,12 +61,12 @@ void refspec_clear(struct refspec *rs);
 
 int valid_fetch_refspec(const char *refspec);
 
-struct argv_array;
+struct strvec;
 /*
  * Determine what <prefix> values to pass to the peer in ref-prefix lines
  * (see Documentation/technical/protocol-v2.txt).
  */
 void refspec_ref_prefixes(const struct refspec *rs,
-                         struct argv_array *ref_prefixes);
+                         struct strvec *ref_prefixes);
 
 #endif /* REFSPEC_H */
index 5cbc6e50025b7cbf8b210cdd7bd6638fe2fa57fa..62b3a45cde26b028fcfe2c242dbd79f6dab25a80 100644 (file)
@@ -10,7 +10,7 @@
 #include "pkt-line.h"
 #include "string-list.h"
 #include "sideband.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "credential.h"
 #include "oid-array.h"
 #include "send-pack.h"
@@ -121,7 +121,11 @@ static int set_option(const char *name, const char *value)
        }
        else if (!strcmp(name, "cas")) {
                struct strbuf val = STRBUF_INIT;
-               strbuf_addf(&val, "--" CAS_OPT_NAME "=%s", value);
+               strbuf_addstr(&val, "--force-with-lease=");
+               if (*value != '"')
+                       strbuf_addstr(&val, value);
+               else if (unquote_c_style(&val, value, NULL))
+                       return -1;
                string_list_append(&cas_options, val.buf);
                strbuf_release(&val);
                return 0;
@@ -1141,41 +1145,41 @@ static int fetch_git(struct discovery *heads,
        struct rpc_state rpc;
        struct strbuf preamble = STRBUF_INIT;
        int i, err;
-       struct argv_array args = ARGV_ARRAY_INIT;
+       struct strvec args = STRVEC_INIT;
        struct strbuf rpc_result = STRBUF_INIT;
 
-       argv_array_pushl(&args, "fetch-pack", "--stateless-rpc",
-                        "--stdin", "--lock-pack", NULL);
+       strvec_pushl(&args, "fetch-pack", "--stateless-rpc",
+                    "--stdin", "--lock-pack", NULL);
        if (options.followtags)
-               argv_array_push(&args, "--include-tag");
+               strvec_push(&args, "--include-tag");
        if (options.thin)
-               argv_array_push(&args, "--thin");
+               strvec_push(&args, "--thin");
        if (options.verbosity >= 3)
-               argv_array_pushl(&args, "-v", "-v", NULL);
+               strvec_pushl(&args, "-v", "-v", NULL);
        if (options.check_self_contained_and_connected)
-               argv_array_push(&args, "--check-self-contained-and-connected");
+               strvec_push(&args, "--check-self-contained-and-connected");
        if (options.cloning)
-               argv_array_push(&args, "--cloning");
+               strvec_push(&args, "--cloning");
        if (options.update_shallow)
-               argv_array_push(&args, "--update-shallow");
+               strvec_push(&args, "--update-shallow");
        if (!options.progress)
-               argv_array_push(&args, "--no-progress");
+               strvec_push(&args, "--no-progress");
        if (options.depth)
-               argv_array_pushf(&args, "--depth=%lu", options.depth);
+               strvec_pushf(&args, "--depth=%lu", options.depth);
        if (options.deepen_since)
-               argv_array_pushf(&args, "--shallow-since=%s", options.deepen_since);
+               strvec_pushf(&args, "--shallow-since=%s", options.deepen_since);
        for (i = 0; i < options.deepen_not.nr; i++)
-               argv_array_pushf(&args, "--shallow-exclude=%s",
-                                options.deepen_not.items[i].string);
+               strvec_pushf(&args, "--shallow-exclude=%s",
+                            options.deepen_not.items[i].string);
        if (options.deepen_relative && options.depth)
-               argv_array_push(&args, "--deepen-relative");
+               strvec_push(&args, "--deepen-relative");
        if (options.from_promisor)
-               argv_array_push(&args, "--from-promisor");
+               strvec_push(&args, "--from-promisor");
        if (options.no_dependents)
-               argv_array_push(&args, "--no-dependents");
+               strvec_push(&args, "--no-dependents");
        if (options.filter)
-               argv_array_pushf(&args, "--filter=%s", options.filter);
-       argv_array_push(&args, url.buf);
+               strvec_pushf(&args, "--filter=%s", options.filter);
+       strvec_push(&args, url.buf);
 
        for (i = 0; i < nr_heads; i++) {
                struct ref *ref = to_fetch[i];
@@ -1190,12 +1194,12 @@ static int fetch_git(struct discovery *heads,
        rpc.service_name = "git-upload-pack",
        rpc.gzip_request = 1;
 
-       err = rpc_service(&rpc, heads, args.argv, &preamble, &rpc_result);
+       err = rpc_service(&rpc, heads, args.v, &preamble, &rpc_result);
        if (rpc_result.len)
                write_or_die(1, rpc_result.buf, rpc_result.len);
        strbuf_release(&rpc_result);
        strbuf_release(&preamble);
-       argv_array_clear(&args);
+       strvec_clear(&args);
        return err;
 }
 
@@ -1267,15 +1271,15 @@ static int push_dav(int nr_spec, const char **specs)
        size_t i;
 
        child.git_cmd = 1;
-       argv_array_push(&child.args, "http-push");
-       argv_array_push(&child.args, "--helper-status");
+       strvec_push(&child.args, "http-push");
+       strvec_push(&child.args, "--helper-status");
        if (options.dry_run)
-               argv_array_push(&child.args, "--dry-run");
+               strvec_push(&child.args, "--dry-run");
        if (options.verbosity > 1)
-               argv_array_push(&child.args, "--verbose");
-       argv_array_push(&child.args, url.buf);
+               strvec_push(&child.args, "--verbose");
+       strvec_push(&child.args, url.buf);
        for (i = 0; i < nr_spec; i++)
-               argv_array_push(&child.args, specs[i]);
+               strvec_push(&child.args, specs[i]);
 
        if (run_command(&child))
                die(_("git-http-push failed"));
@@ -1286,38 +1290,38 @@ static int push_git(struct discovery *heads, int nr_spec, const char **specs)
 {
        struct rpc_state rpc;
        int i, err;
-       struct argv_array args;
+       struct strvec args;
        struct string_list_item *cas_option;
        struct strbuf preamble = STRBUF_INIT;
        struct strbuf rpc_result = STRBUF_INIT;
 
-       argv_array_init(&args);
-       argv_array_pushl(&args, "send-pack", "--stateless-rpc", "--helper-status",
-                        NULL);
+       strvec_init(&args);
+       strvec_pushl(&args, "send-pack", "--stateless-rpc", "--helper-status",
+                    NULL);
 
        if (options.thin)
-               argv_array_push(&args, "--thin");
+               strvec_push(&args, "--thin");
        if (options.dry_run)
-               argv_array_push(&args, "--dry-run");
+               strvec_push(&args, "--dry-run");
        if (options.push_cert == SEND_PACK_PUSH_CERT_ALWAYS)
-               argv_array_push(&args, "--signed=yes");
+               strvec_push(&args, "--signed=yes");
        else if (options.push_cert == SEND_PACK_PUSH_CERT_IF_ASKED)
-               argv_array_push(&args, "--signed=if-asked");
+               strvec_push(&args, "--signed=if-asked");
        if (options.atomic)
-               argv_array_push(&args, "--atomic");
+               strvec_push(&args, "--atomic");
        if (options.verbosity == 0)
-               argv_array_push(&args, "--quiet");
+               strvec_push(&args, "--quiet");
        else if (options.verbosity > 1)
-               argv_array_push(&args, "--verbose");
+               strvec_push(&args, "--verbose");
        for (i = 0; i < options.push_options.nr; i++)
-               argv_array_pushf(&args, "--push-option=%s",
-                                options.push_options.items[i].string);
-       argv_array_push(&args, options.progress ? "--progress" : "--no-progress");
+               strvec_pushf(&args, "--push-option=%s",
+                            options.push_options.items[i].string);
+       strvec_push(&args, options.progress ? "--progress" : "--no-progress");
        for_each_string_list_item(cas_option, &cas_options)
-               argv_array_push(&args, cas_option->string);
-       argv_array_push(&args, url.buf);
+               strvec_push(&args, cas_option->string);
+       strvec_push(&args, url.buf);
 
-       argv_array_push(&args, "--stdin");
+       strvec_push(&args, "--stdin");
        for (i = 0; i < nr_spec; i++)
                packet_buf_write(&preamble, "%s\n", specs[i]);
        packet_buf_flush(&preamble);
@@ -1325,12 +1329,12 @@ static int push_git(struct discovery *heads, int nr_spec, const char **specs)
        memset(&rpc, 0, sizeof(rpc));
        rpc.service_name = "git-receive-pack",
 
-       err = rpc_service(&rpc, heads, args.argv, &preamble, &rpc_result);
+       err = rpc_service(&rpc, heads, args.v, &preamble, &rpc_result);
        if (rpc_result.len)
                write_or_die(1, rpc_result.buf, rpc_result.len);
        strbuf_release(&rpc_result);
        strbuf_release(&preamble);
-       argv_array_clear(&args);
+       strvec_clear(&args);
        return err;
 }
 
@@ -1349,13 +1353,13 @@ static int push(int nr_spec, const char **specs)
 
 static void parse_push(struct strbuf *buf)
 {
-       struct argv_array specs = ARGV_ARRAY_INIT;
+       struct strvec specs = STRVEC_INIT;
        int ret;
 
        do {
                const char *arg;
                if (skip_prefix(buf->buf, "push ", &arg))
-                       argv_array_push(&specs, arg);
+                       strvec_push(&specs, arg);
                else
                        die(_("http transport does not support %s"), buf->buf);
 
@@ -1366,7 +1370,7 @@ static void parse_push(struct strbuf *buf)
                        break;
        } while (1);
 
-       ret = push(specs.argc, specs.argv);
+       ret = push(specs.nr, specs.v);
        printf("\n");
        fflush(stdout);
 
@@ -1374,7 +1378,7 @@ static void parse_push(struct strbuf *buf)
                exit(128); /* error already reported */
 
 free_specs:
-       argv_array_clear(&specs);
+       strvec_clear(&specs);
 }
 
 static int stateless_connect(const char *service_name)
index cde39b94fb8439a9da3c57428a7f5e15056ae54a..636b2b62a60276920614cd14cdbcb34232d88573 100644 (file)
@@ -8,7 +8,7 @@
 #include "run-command.h"
 #include "vcs-svn/svndump.h"
 #include "notes.h"
-#include "argv-array.h"
+#include "strvec.h"
 
 static const char *url;
 static int dump_from_file;
@@ -198,10 +198,10 @@ static int cmd_import(const char *line)
                        die_errno("Couldn't open svn dump file %s.", url);
        } else {
                svndump_proc.out = -1;
-               argv_array_push(&svndump_proc.args, command);
-               argv_array_push(&svndump_proc.args, "dump");
-               argv_array_push(&svndump_proc.args, url);
-               argv_array_pushf(&svndump_proc.args, "-r%u:HEAD", startrev);
+               strvec_push(&svndump_proc.args, command);
+               strvec_push(&svndump_proc.args, "dump");
+               strvec_push(&svndump_proc.args, url);
+               strvec_pushf(&svndump_proc.args, "-r%u:HEAD", startrev);
 
                code = start_command(&svndump_proc);
                if (code)
index bc46413e6a75788da66b5c0c6bec9aa5a52c5403..c5ed74f91c63b090ddd916c4fa235a0ebf62f558 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -11,7 +11,7 @@
 #include "tag.h"
 #include "string-list.h"
 #include "mergesort.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "commit-reach.h"
 #include "advice.h"
 
@@ -1885,7 +1885,7 @@ static int stat_branch_pair(const char *branch_name, const char *base,
        struct object_id oid;
        struct commit *ours, *theirs;
        struct rev_info revs;
-       struct argv_array argv = ARGV_ARRAY_INIT;
+       struct strvec argv = STRVEC_INIT;
 
        /* Cannot stat if what we used to build on no longer exists */
        if (read_ref(base, &oid))
@@ -1911,15 +1911,15 @@ static int stat_branch_pair(const char *branch_name, const char *base,
                BUG("stat_branch_pair: invalid abf '%d'", abf);
 
        /* Run "rev-list --left-right ours...theirs" internally... */
-       argv_array_push(&argv, ""); /* ignored */
-       argv_array_push(&argv, "--left-right");
-       argv_array_pushf(&argv, "%s...%s",
-                        oid_to_hex(&ours->object.oid),
-                        oid_to_hex(&theirs->object.oid));
-       argv_array_push(&argv, "--");
+       strvec_push(&argv, ""); /* ignored */
+       strvec_push(&argv, "--left-right");
+       strvec_pushf(&argv, "%s...%s",
+                    oid_to_hex(&ours->object.oid),
+                    oid_to_hex(&theirs->object.oid));
+       strvec_push(&argv, "--");
 
        repo_init_revisions(the_repository, &revs, NULL);
-       setup_revisions(argv.argc, argv.argv, &revs, NULL);
+       setup_revisions(argv.nr, argv.v, &revs, NULL);
        if (prepare_revision_walk(&revs))
                die(_("revision walk setup failed"));
 
@@ -1938,7 +1938,7 @@ static int stat_branch_pair(const char *branch_name, const char *base,
        clear_commit_marks(ours, ALL_REV_FLAGS);
        clear_commit_marks(theirs, ALL_REV_FLAGS);
 
-       argv_array_clear(&argv);
+       strvec_clear(&argv);
        return 1;
 }
 
index 5cc26c1b3b3e1f1e2c97c24088f866de6840eab0..5e3ea5a26deb1d0db7deb6ff9ed2f3ef778084d4 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -168,7 +168,7 @@ void free_refs(struct ref *ref);
 
 struct oid_array;
 struct packet_reader;
-struct argv_array;
+struct strvec;
 struct string_list;
 struct ref **get_remote_heads(struct packet_reader *reader,
                              struct ref **list, unsigned int flags,
@@ -178,7 +178,7 @@ struct ref **get_remote_heads(struct packet_reader *reader,
 /* Used for protocol v2 in order to retrieve refs from a remote */
 struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
                             struct ref **list, int for_push,
-                            const struct argv_array *ref_prefixes,
+                            const struct strvec *ref_prefixes,
                             const struct string_list *server_options,
                             int stateless_rpc);
 
index 6f7f6f002b1a45faa52305ca8c370e2e959b2f5e..a4174ddb0629cdd690142fb42c5d4182492485c4 100644 (file)
@@ -89,10 +89,6 @@ void repo_set_gitdir(struct repository *repo,
 void repo_set_hash_algo(struct repository *repo, int hash_algo)
 {
        repo->hash_algo = &hash_algos[hash_algo];
-#ifndef ENABLE_SHA256
-       if (hash_algo != GIT_HASH_SHA1)
-               die(_("The hash algorithm %s is not supported in this build."), repo->hash_algo->name);
-#endif
 }
 
 /*
index 6aa7f4f56755bdc2b79455c61a9882085980f90a..96630e31867dd6987b8d5447bcaedb777303679d 100644 (file)
@@ -23,7 +23,7 @@
 #include "bisect.h"
 #include "packfile.h"
 #include "worktree.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "commit-reach.h"
 #include "commit-graph.h"
 #include "prio-queue.h"
@@ -633,7 +633,6 @@ static unsigned int count_bloom_filter_maybe;
 static unsigned int count_bloom_filter_definitely_not;
 static unsigned int count_bloom_filter_false_positive;
 static unsigned int count_bloom_filter_not_present;
-static unsigned int count_bloom_filter_length_zero;
 
 static void trace2_bloom_filter_statistics_atexit(void)
 {
@@ -641,7 +640,6 @@ static void trace2_bloom_filter_statistics_atexit(void)
 
        jw_object_begin(&jw, 0);
        jw_object_intmax(&jw, "filter_not_present", count_bloom_filter_not_present);
-       jw_object_intmax(&jw, "zero_length_filter", count_bloom_filter_length_zero);
        jw_object_intmax(&jw, "maybe", count_bloom_filter_maybe);
        jw_object_intmax(&jw, "definitely_not", count_bloom_filter_definitely_not);
        jw_object_intmax(&jw, "false_positive", count_bloom_filter_false_positive);
@@ -670,9 +668,9 @@ static void prepare_to_use_bloom_filter(struct rev_info *revs)
 {
        struct pathspec_item *pi;
        char *path_alloc = NULL;
-       const char *path;
-       int last_index;
-       int len;
+       const char *path, *p;
+       size_t len;
+       int path_component_nr = 1;
 
        if (!revs->commits)
                return;
@@ -693,20 +691,48 @@ static void prepare_to_use_bloom_filter(struct rev_info *revs)
                return;
 
        pi = &revs->pruning.pathspec.items[0];
-       last_index = pi->len - 1;
 
        /* remove single trailing slash from path, if needed */
-       if (pi->match[last_index] == '/') {
-           path_alloc = xstrdup(pi->match);
-           path_alloc[last_index] = '\0';
-           path = path_alloc;
+       if (pi->len > 0 && pi->match[pi->len - 1] == '/') {
+               path_alloc = xmemdupz(pi->match, pi->len - 1);
+               path = path_alloc;
        } else
-           path = pi->match;
+               path = pi->match;
 
        len = strlen(path);
+       if (!len) {
+               revs->bloom_filter_settings = NULL;
+               free(path_alloc);
+               return;
+       }
 
-       revs->bloom_key = xmalloc(sizeof(struct bloom_key));
-       fill_bloom_key(path, len, revs->bloom_key, revs->bloom_filter_settings);
+       p = path;
+       while (*p) {
+               /*
+                * At this point, the path is normalized to use Unix-style
+                * path separators. This is required due to how the
+                * changed-path Bloom filters store the paths.
+                */
+               if (*p == '/')
+                       path_component_nr++;
+               p++;
+       }
+
+       revs->bloom_keys_nr = path_component_nr;
+       ALLOC_ARRAY(revs->bloom_keys, revs->bloom_keys_nr);
+
+       fill_bloom_key(path, len, &revs->bloom_keys[0],
+                      revs->bloom_filter_settings);
+       path_component_nr = 1;
+
+       p = path + len - 1;
+       while (p > path) {
+               if (*p == '/')
+                       fill_bloom_key(path, p - path,
+                                      &revs->bloom_keys[path_component_nr++],
+                                      revs->bloom_filter_settings);
+               p--;
+       }
 
        if (trace2_is_enabled() && !bloom_filter_atexit_registered) {
                atexit(trace2_bloom_filter_statistics_atexit);
@@ -720,7 +746,7 @@ static int check_maybe_different_in_bloom_filter(struct rev_info *revs,
                                                 struct commit *commit)
 {
        struct bloom_filter *filter;
-       int result;
+       int result = 1, j;
 
        if (!revs->repo->objects->commit_graph)
                return -1;
@@ -735,15 +761,12 @@ static int check_maybe_different_in_bloom_filter(struct rev_info *revs,
                return -1;
        }
 
-       if (!filter->len) {
-               count_bloom_filter_length_zero++;
-               return -1;
+       for (j = 0; result && j < revs->bloom_keys_nr; j++) {
+               result = bloom_filter_contains(filter,
+                                              &revs->bloom_keys[j],
+                                              revs->bloom_filter_settings);
        }
 
-       result = bloom_filter_contains(filter,
-                                      revs->bloom_key,
-                                      revs->bloom_filter_settings);
-
        if (result)
                count_bloom_filter_maybe++;
        else
@@ -782,7 +805,7 @@ static int rev_compare_tree(struct rev_info *revs,
                        return REV_TREE_SAME;
        }
 
-       if (revs->bloom_key && !nth_parent) {
+       if (revs->bloom_keys_nr && !nth_parent) {
                bloom_ret = check_maybe_different_in_bloom_filter(revs, commit);
 
                if (bloom_ret == 0)
@@ -791,9 +814,7 @@ static int rev_compare_tree(struct rev_info *revs,
 
        tree_difference = REV_TREE_SAME;
        revs->pruning.flags.has_changes = 0;
-       if (diff_tree_oid(&t1->object.oid, &t2->object.oid, "",
-                          &revs->pruning) < 0)
-               return REV_TREE_DIFFERENT;
+       diff_tree_oid(&t1->object.oid, &t2->object.oid, "", &revs->pruning);
 
        if (!nth_parent)
                if (bloom_ret == 1 && tree_difference == REV_TREE_SAME)
@@ -804,7 +825,6 @@ static int rev_compare_tree(struct rev_info *revs,
 
 static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit)
 {
-       int retval;
        struct tree *t1 = get_commit_tree(commit);
 
        if (!t1)
@@ -812,9 +832,9 @@ static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit)
 
        tree_difference = REV_TREE_SAME;
        revs->pruning.flags.has_changes = 0;
-       retval = diff_tree_oid(NULL, &t1->object.oid, "", &revs->pruning);
+       diff_tree_oid(NULL, &t1->object.oid, "", &revs->pruning);
 
-       return retval >= 0 && (tree_difference == REV_TREE_SAME);
+       return tree_difference == REV_TREE_SAME;
 }
 
 struct treesame_state {
@@ -1795,7 +1815,7 @@ void repo_init_revisions(struct repository *r,
 
        revs->repo = r;
        revs->abbrev = DEFAULT_ABBREV;
-       revs->ignore_merges = 1;
+       revs->ignore_merges = -1;
        revs->simplify_history = 1;
        revs->pruning.repo = r;
        revs->pruning.flags.recursive = 1;
@@ -2073,14 +2093,14 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi
 }
 
 static void read_pathspec_from_stdin(struct strbuf *sb,
-                                    struct argv_array *prune)
+                                    struct strvec *prune)
 {
        while (strbuf_getline(sb, stdin) != EOF)
-               argv_array_push(prune, sb->buf);
+               strvec_push(prune, sb->buf);
 }
 
 static void read_revisions_from_stdin(struct rev_info *revs,
-                                     struct argv_array *prune)
+                                     struct strvec *prune)
 {
        struct strbuf sb;
        int seen_dashdash = 0;
@@ -2315,7 +2335,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
        } else if (!strcmp(arg, "--unpacked")) {
                revs->unpacked = 1;
        } else if (starts_with(arg, "--unpacked=")) {
-               die("--unpacked=<packfile> no longer supported.");
+               die(_("--unpacked=<packfile> no longer supported"));
        } else if (!strcmp(arg, "-r")) {
                revs->diff = 1;
                revs->diffopt.flags.recursive = 1;
@@ -2325,6 +2345,15 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
                revs->diffopt.flags.tree_in_recursive = 1;
        } else if (!strcmp(arg, "-m")) {
                revs->ignore_merges = 0;
+       } else if ((argcount = parse_long_opt("diff-merges", argv, &optarg))) {
+               if (!strcmp(optarg, "off")) {
+                       revs->ignore_merges = 1;
+               } else {
+                       die(_("unknown value for --diff-merges: %s"), optarg);
+               }
+               return argcount;
+       } else if (!strcmp(arg, "--no-diff-merges")) {
+               revs->ignore_merges = 1;
        } else if (!strcmp(arg, "-c")) {
                revs->diff = 1;
                revs->dense_combined_merges = 0;
@@ -2675,7 +2704,7 @@ static void NORETURN diagnose_missing_default(const char *def)
 int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct setup_revision_opt *opt)
 {
        int i, flags, left, seen_dashdash, got_rev_arg = 0, revarg_opt;
-       struct argv_array prune_data = ARGV_ARRAY_INIT;
+       struct strvec prune_data = STRVEC_INIT;
        const char *submodule = NULL;
        int seen_end_of_options = 0;
 
@@ -2694,7 +2723,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
                        argv[i] = NULL;
                        argc = i;
                        if (argv[i + 1])
-                               argv_array_pushv(&prune_data, argv + i + 1);
+                               strvec_pushv(&prune_data, argv + i + 1);
                        seen_dashdash = 1;
                        break;
                }
@@ -2760,14 +2789,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
                        for (j = i; j < argc; j++)
                                verify_filename(revs->prefix, argv[j], j == i);
 
-                       argv_array_pushv(&prune_data, argv + i);
+                       strvec_pushv(&prune_data, argv + i);
                        break;
                }
                else
                        got_rev_arg = 1;
        }
 
-       if (prune_data.argc) {
+       if (prune_data.nr) {
                /*
                 * If we need to introduce the magic "a lone ':' means no
                 * pathspec whatsoever", here is the place to do so.
@@ -2783,9 +2812,9 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
                 * }
                 */
                parse_pathspec(&revs->prune_data, 0, 0,
-                              revs->prefix, prune_data.argv);
+                              revs->prefix, prune_data.v);
        }
-       argv_array_clear(&prune_data);
+       strvec_clear(&prune_data);
 
        if (revs->def == NULL)
                revs->def = opt ? opt->def : NULL;
@@ -2834,8 +2863,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
                        copy_pathspec(&revs->diffopt.pathspec,
                                      &revs->prune_data);
        }
-       if (revs->combine_merges)
+       if (revs->combine_merges && revs->ignore_merges < 0)
                revs->ignore_merges = 0;
+       if (revs->ignore_merges < 0)
+               revs->ignore_merges = 1;
        if (revs->combined_all_paths && !revs->combine_merges)
                die("--combined-all-paths makes no sense without -c or --cc");
 
@@ -2869,9 +2900,6 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
        if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
                die("cannot use --grep-reflog without --walk-reflogs");
 
-       if (revs->first_parent_only && revs->bisect)
-               die(_("--first-parent is incompatible with --bisect"));
-
        if (revs->line_level_traverse &&
            (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT)))
                die(_("-L does not yet support diff formats besides -p and -s"));
index f412ae85ebafe0a1ecb8e2d7d2c56470682820ec..c1e5bcf139d7a31d9bf851ada3bc8373f5ab932e 100644 (file)
@@ -190,11 +190,11 @@ struct rev_info {
                        show_root_diff:1,
                        no_commit_id:1,
                        verbose_header:1,
-                       ignore_merges:1,
                        combine_merges:1,
                        combined_all_paths:1,
                        dense_combined_merges:1,
                        always_show_header:1;
+       int             ignore_merges:2;
 
        /* Format info */
        int             show_notes;
@@ -301,8 +301,10 @@ struct rev_info {
        struct topo_walk_info *topo_walk_info;
 
        /* Commit graph bloom filter fields */
-       /* The bloom filter key for the pathspec */
-       struct bloom_key *bloom_key;
+       /* The bloom filter key(s) for the pathspec */
+       struct bloom_key *bloom_keys;
+       int bloom_keys_nr;
+
        /*
         * The bloom filter settings used to generate the key.
         * This is loaded from the commit-graph being used.
index a735e380a9c2bb8e461e1182ab3103cbd5cc960b..cc9c3296ba0cbb852300d7d5ccb3d6f29f931034 100644 (file)
@@ -2,7 +2,7 @@
 #include "run-command.h"
 #include "exec-cmd.h"
 #include "sigchain.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "thread-utils.h"
 #include "strbuf.h"
 #include "string-list.h"
 void child_process_init(struct child_process *child)
 {
        memset(child, 0, sizeof(*child));
-       argv_array_init(&child->args);
-       argv_array_init(&child->env_array);
+       strvec_init(&child->args);
+       strvec_init(&child->env_array);
 }
 
 void child_process_clear(struct child_process *child)
 {
-       argv_array_clear(&child->args);
-       argv_array_clear(&child->env_array);
+       strvec_clear(&child->args);
+       strvec_clear(&child->env_array);
 }
 
 struct child_to_clean {
@@ -263,31 +263,31 @@ int sane_execvp(const char *file, char * const argv[])
        return -1;
 }
 
-static const char **prepare_shell_cmd(struct argv_array *out, const char **argv)
+static const char **prepare_shell_cmd(struct strvec *out, const char **argv)
 {
        if (!argv[0])
                BUG("shell command is empty");
 
        if (strcspn(argv[0], "|&;<>()$`\\\"' \t\n*?[#~=%") != strlen(argv[0])) {
 #ifndef GIT_WINDOWS_NATIVE
-               argv_array_push(out, SHELL_PATH);
+               strvec_push(out, SHELL_PATH);
 #else
-               argv_array_push(out, "sh");
+               strvec_push(out, "sh");
 #endif
-               argv_array_push(out, "-c");
+               strvec_push(out, "-c");
 
                /*
                 * If we have no extra arguments, we do not even need to
                 * bother with the "$@" magic.
                 */
                if (!argv[1])
-                       argv_array_push(out, argv[0]);
+                       strvec_push(out, argv[0]);
                else
-                       argv_array_pushf(out, "%s \"$@\"", argv[0]);
+                       strvec_pushf(out, "%s \"$@\"", argv[0]);
        }
 
-       argv_array_pushv(out, argv);
-       return out->argv;
+       strvec_pushv(out, argv);
+       return out->v;
 }
 
 #ifndef GIT_WINDOWS_NATIVE
@@ -401,7 +401,7 @@ static void child_err_spew(struct child_process *cmd, struct child_err *cerr)
        set_error_routine(old_errfn);
 }
 
-static int prepare_cmd(struct argv_array *out, const struct child_process *cmd)
+static int prepare_cmd(struct strvec *out, const struct child_process *cmd)
 {
        if (!cmd->argv[0])
                BUG("command is empty");
@@ -410,14 +410,14 @@ static int prepare_cmd(struct argv_array *out, const struct child_process *cmd)
         * Add SHELL_PATH so in the event exec fails with ENOEXEC we can
         * attempt to interpret the command with 'sh'.
         */
-       argv_array_push(out, SHELL_PATH);
+       strvec_push(out, SHELL_PATH);
 
        if (cmd->git_cmd) {
                prepare_git_cmd(out, cmd->argv);
        } else if (cmd->use_shell) {
                prepare_shell_cmd(out, cmd->argv);
        } else {
-               argv_array_pushv(out, cmd->argv);
+               strvec_pushv(out, cmd->argv);
        }
 
        /*
@@ -426,13 +426,13 @@ static int prepare_cmd(struct argv_array *out, const struct child_process *cmd)
         * there are dir separator characters, we have exec attempt to invoke
         * the command directly.
         */
-       if (!has_dir_sep(out->argv[1])) {
-               char *program = locate_in_PATH(out->argv[1]);
+       if (!has_dir_sep(out->v[1])) {
+               char *program = locate_in_PATH(out->v[1]);
                if (program) {
-                       free((char *)out->argv[1]);
-                       out->argv[1] = program;
+                       free((char *)out->v[1]);
+                       out->v[1] = program;
                } else {
-                       argv_array_clear(out);
+                       strvec_clear(out);
                        errno = ENOENT;
                        return -1;
                }
@@ -672,9 +672,9 @@ int start_command(struct child_process *cmd)
        char *str;
 
        if (!cmd->argv)
-               cmd->argv = cmd->args.argv;
+               cmd->argv = cmd->args.v;
        if (!cmd->env)
-               cmd->env = cmd->env_array.argv;
+               cmd->env = cmd->env_array.v;
 
        /*
         * In case of errors we must keep the promise to close FDs
@@ -742,7 +742,7 @@ fail_pipe:
        int notify_pipe[2];
        int null_fd = -1;
        char **childenv;
-       struct argv_array argv = ARGV_ARRAY_INIT;
+       struct strvec argv = STRVEC_INIT;
        struct child_err cerr;
        struct atfork_state as;
 
@@ -846,10 +846,10 @@ fail_pipe:
                 * be used in the event exec failed with ENOEXEC at which point
                 * we will try to interpret the command using 'sh'.
                 */
-               execve(argv.argv[1], (char *const *) argv.argv + 1,
+               execve(argv.v[1], (char *const *) argv.v + 1,
                       (char *const *) childenv);
                if (errno == ENOEXEC)
-                       execve(argv.argv[0], (char *const *) argv.argv,
+                       execve(argv.v[0], (char *const *) argv.v,
                               (char *const *) childenv);
 
                if (errno == ENOENT) {
@@ -888,7 +888,7 @@ fail_pipe:
 
        if (null_fd >= 0)
                close(null_fd);
-       argv_array_clear(&argv);
+       strvec_clear(&argv);
        free(childenv);
 }
 end_of_spawn:
@@ -897,7 +897,7 @@ end_of_spawn:
 {
        int fhin = 0, fhout = 1, fherr = 2;
        const char **sargv = cmd->argv;
-       struct argv_array nargv = ARGV_ARRAY_INIT;
+       struct strvec nargv = STRVEC_INIT;
 
        if (cmd->no_stdin)
                fhin = open("/dev/null", O_RDWR);
@@ -935,7 +935,7 @@ end_of_spawn:
        if (cmd->clean_on_exit && cmd->pid >= 0)
                mark_child_for_cleanup(cmd->pid, cmd);
 
-       argv_array_clear(&nargv);
+       strvec_clear(&nargv);
        cmd->argv = sargv;
        if (fhin != 0)
                close(fhin);
@@ -1352,9 +1352,9 @@ int run_hook_ve(const char *const *env, const char *name, va_list args)
        if (!p)
                return 0;
 
-       argv_array_push(&hook.args, p);
+       strvec_push(&hook.args, p);
        while ((p = va_arg(args, const char *)))
-               argv_array_push(&hook.args, p);
+               strvec_push(&hook.args, p);
        hook.env = env;
        hook.no_stdin = 1;
        hook.stdout_to_stderr = 1;
@@ -1868,13 +1868,13 @@ int run_processes_parallel_tr2(int n, get_next_task_fn get_next_task,
 
 int run_auto_gc(int quiet)
 {
-       struct argv_array argv_gc_auto = ARGV_ARRAY_INIT;
+       struct strvec argv_gc_auto = STRVEC_INIT;
        int status;
 
-       argv_array_pushl(&argv_gc_auto, "gc", "--auto", NULL);
+       strvec_pushl(&argv_gc_auto, "gc", "--auto", NULL);
        if (quiet)
-               argv_array_push(&argv_gc_auto, "--quiet");
-       status = run_command_v_opt(argv_gc_auto.argv, RUN_GIT_CMD);
-       argv_array_clear(&argv_gc_auto);
+               strvec_push(&argv_gc_auto, "--quiet");
+       status = run_command_v_opt(argv_gc_auto.v, RUN_GIT_CMD);
+       strvec_clear(&argv_gc_auto);
        return status;
 }
index ef3071a56560a53aac8072dcd001113e28c65877..8b9bfaef16c8d1932ba1449da205675113097103 100644 (file)
@@ -3,7 +3,7 @@
 
 #include "thread-utils.h"
 
-#include "argv-array.h"
+#include "strvec.h"
 
 /**
  * The run-command API offers a versatile tool to run sub-processes with
@@ -52,15 +52,15 @@ struct child_process {
         * Note that the ownership of the memory pointed to by .argv stays with the
         * caller, but it should survive until `finish_command` completes. If the
         * .argv member is NULL, `start_command` will point it at the .args
-        * `argv_array` (so you may use one or the other, but you must use exactly
+        * `strvec` (so you may use one or the other, but you must use exactly
         * one). The memory in .args will be cleaned up automatically during
         * `finish_command` (or during `start_command` when it is unsuccessful).
         *
         */
        const char **argv;
 
-       struct argv_array args;
-       struct argv_array env_array;
+       struct strvec args;
+       struct strvec env_array;
        pid_t pid;
 
        int trace2_child_id;
@@ -107,7 +107,7 @@ struct child_process {
         *   variable that will be removed from the child process's environment.
         *
         * If the .env member is NULL, `start_command` will point it at the
-        * .env_array `argv_array` (so you may use one or the other, but not both).
+        * .env_array `strvec` (so you may use one or the other, but not both).
         * The memory in .env_array will be cleaned up automatically during
         * `finish_command` (or during `start_command` when it is unsuccessful).
         */
@@ -134,7 +134,7 @@ struct child_process {
        void *clean_on_exit_handler_cbdata;
 };
 
-#define CHILD_PROCESS_INIT { NULL, ARGV_ARRAY_INIT, ARGV_ARRAY_INIT }
+#define CHILD_PROCESS_INIT { NULL, STRVEC_INIT, STRVEC_INIT }
 
 /**
  * The functions: child_process_init, start_command, finish_command,
index d671ab5d05c5dfd5acb1c597f68caf58d98dca9b..632f1580cab9acd38daaa25e3f7172e098410f56 100644 (file)
@@ -68,20 +68,20 @@ static int pack_objects(int fd, struct ref *refs, struct oid_array *extra, struc
        int i;
        int rc;
 
-       argv_array_push(&po.args, "pack-objects");
-       argv_array_push(&po.args, "--all-progress-implied");
-       argv_array_push(&po.args, "--revs");
-       argv_array_push(&po.args, "--stdout");
+       strvec_push(&po.args, "pack-objects");
+       strvec_push(&po.args, "--all-progress-implied");
+       strvec_push(&po.args, "--revs");
+       strvec_push(&po.args, "--stdout");
        if (args->use_thin_pack)
-               argv_array_push(&po.args, "--thin");
+               strvec_push(&po.args, "--thin");
        if (args->use_ofs_delta)
-               argv_array_push(&po.args, "--delta-base-offset");
+               strvec_push(&po.args, "--delta-base-offset");
        if (args->quiet || !args->progress)
-               argv_array_push(&po.args, "-q");
+               strvec_push(&po.args, "-q");
        if (args->progress)
-               argv_array_push(&po.args, "--progress");
+               strvec_push(&po.args, "--progress");
        if (is_repository_shallow(the_repository))
-               argv_array_push(&po.args, "--shallow");
+               strvec_push(&po.args, "--shallow");
        po.in = -1;
        po.out = args->stateless_rpc ? -1 : fd;
        po.git_cmd = 1;
index fd7701c88a8643c424d4f61fd0cc86fde3097d7d..d7db076715ad6ef622fdb558a39b9fec66861ea4 100644 (file)
@@ -16,7 +16,7 @@
 #include "rerere.h"
 #include "merge-recursive.h"
 #include "refs.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "quote.h"
 #include "trailer.h"
 #include "log-tree.h"
@@ -355,7 +355,7 @@ static int get_message(struct commit *commit, struct commit_message *out)
        subject_len = find_commit_subject(out->message, &subject);
 
        out->subject = xmemdupz(subject, subject_len);
-       out->label = xstrfmt("%s... %s", abbrev, out->subject);
+       out->label = xstrfmt("%s (%s)", abbrev, out->subject);
        out->parent_label = xstrfmt("parent of %s", out->label);
 
        return 0;
@@ -381,7 +381,8 @@ static void print_advice(struct repository *r, int show_hint,
                 * (typically rebase --interactive) wants to take care
                 * of the commit itself so remove CHERRY_PICK_HEAD
                 */
-               unlink(git_path_cherry_pick_head(r));
+               refs_delete_ref(get_main_ref_store(r), "", "CHERRY_PICK_HEAD",
+                               NULL, 0);
                return;
        }
 
@@ -830,10 +831,10 @@ finish:
 
 /*
  * Read a GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL AND GIT_AUTHOR_DATE from a
- * file with shell quoting into struct argv_array. Returns -1 on
+ * file with shell quoting into struct strvec. Returns -1 on
  * error, 0 otherwise.
  */
-static int read_env_script(struct argv_array *env)
+static int read_env_script(struct strvec *env)
 {
        char *name, *email, *date;
 
@@ -841,9 +842,9 @@ static int read_env_script(struct argv_array *env)
                               &name, &email, &date, 0))
                return -1;
 
-       argv_array_pushf(env, "GIT_AUTHOR_NAME=%s", name);
-       argv_array_pushf(env, "GIT_AUTHOR_EMAIL=%s", email);
-       argv_array_pushf(env, "GIT_AUTHOR_DATE=%s", date);
+       strvec_pushf(env, "GIT_AUTHOR_NAME=%s", name);
+       strvec_pushf(env, "GIT_AUTHOR_EMAIL=%s", email);
+       strvec_pushf(env, "GIT_AUTHOR_DATE=%s", date);
        free(name);
        free(email);
        free(date);
@@ -929,34 +930,34 @@ static int run_git_commit(struct repository *r,
                             gpg_opt, gpg_opt);
        }
 
-       argv_array_push(&cmd.args, "commit");
+       strvec_push(&cmd.args, "commit");
 
        if (!(flags & VERIFY_MSG))
-               argv_array_push(&cmd.args, "-n");
+               strvec_push(&cmd.args, "-n");
        if ((flags & AMEND_MSG))
-               argv_array_push(&cmd.args, "--amend");
+               strvec_push(&cmd.args, "--amend");
        if (opts->gpg_sign)
-               argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
+               strvec_pushf(&cmd.args, "-S%s", opts->gpg_sign);
        else
-               argv_array_push(&cmd.args, "--no-gpg-sign");
+               strvec_push(&cmd.args, "--no-gpg-sign");
        if (defmsg)
-               argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
+               strvec_pushl(&cmd.args, "-F", defmsg, NULL);
        else if (!(flags & EDIT_MSG))
-               argv_array_pushl(&cmd.args, "-C", "HEAD", NULL);
+               strvec_pushl(&cmd.args, "-C", "HEAD", NULL);
        if ((flags & CLEANUP_MSG))
-               argv_array_push(&cmd.args, "--cleanup=strip");
+               strvec_push(&cmd.args, "--cleanup=strip");
        if ((flags & EDIT_MSG))
-               argv_array_push(&cmd.args, "-e");
+               strvec_push(&cmd.args, "-e");
        else if (!(flags & CLEANUP_MSG) &&
                 !opts->signoff && !opts->record_origin &&
                 !opts->explicit_cleanup)
-               argv_array_push(&cmd.args, "--cleanup=verbatim");
+               strvec_push(&cmd.args, "--cleanup=verbatim");
 
        if ((flags & ALLOW_EMPTY))
-               argv_array_push(&cmd.args, "--allow-empty");
+               strvec_push(&cmd.args, "--allow-empty");
 
        if (!(flags & EDIT_MSG))
-               argv_array_push(&cmd.args, "--allow-empty-message");
+               strvec_push(&cmd.args, "--allow-empty-message");
 
        if (is_rebase_i(opts) && !(flags & EDIT_MSG))
                return run_command_silent_on_success(&cmd);
@@ -1455,7 +1456,8 @@ static int do_commit(struct repository *r,
                                    author, opts, flags, &oid);
                strbuf_release(&sb);
                if (!res) {
-                       unlink(git_path_cherry_pick_head(r));
+                       refs_delete_ref(get_main_ref_store(r), "",
+                                       "CHERRY_PICK_HEAD", NULL, 0);
                        unlink(git_path_merge_msg(r));
                        if (!is_rebase_i(opts))
                                print_commit_summary(r, NULL, &oid,
@@ -1966,7 +1968,8 @@ static int do_pick_commit(struct repository *r,
                flags |= ALLOW_EMPTY;
        } else if (allow == 2) {
                drop_commit = 1;
-               unlink(git_path_cherry_pick_head(r));
+               refs_delete_ref(get_main_ref_store(r), "", "CHERRY_PICK_HEAD",
+                               NULL, 0);
                unlink(git_path_merge_msg(r));
                fprintf(stderr,
                        _("dropping %s %s -- patch contents already upstream\n"),
@@ -2305,15 +2308,19 @@ void sequencer_post_commit_cleanup(struct repository *r, int verbose)
        struct replay_opts opts = REPLAY_OPTS_INIT;
        int need_cleanup = 0;
 
-       if (file_exists(git_path_cherry_pick_head(r))) {
-               if (!unlink(git_path_cherry_pick_head(r)) && verbose)
+       if (refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD")) {
+               if (!refs_delete_ref(get_main_ref_store(r), "",
+                                    "CHERRY_PICK_HEAD", NULL, 0) &&
+                   verbose)
                        warning(_("cancelling a cherry picking in progress"));
                opts.action = REPLAY_PICK;
                need_cleanup = 1;
        }
 
-       if (file_exists(git_path_revert_head(r))) {
-               if (!unlink(git_path_revert_head(r)) && verbose)
+       if (refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD")) {
+               if (!refs_delete_ref(get_main_ref_store(r), "", "REVERT_HEAD",
+                                    NULL, 0) &&
+                   verbose)
                        warning(_("cancelling a revert in progress"));
                opts.action = REPLAY_REVERT;
                need_cleanup = 1;
@@ -2671,8 +2678,9 @@ static int create_seq_dir(struct repository *r)
        enum replay_action action;
        const char *in_progress_error = NULL;
        const char *in_progress_advice = NULL;
-       unsigned int advise_skip = file_exists(git_path_revert_head(r)) ||
-                               file_exists(git_path_cherry_pick_head(r));
+       unsigned int advise_skip =
+               refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD") ||
+               refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD");
 
        if (!sequencer_get_last_command(r, &action)) {
                switch (action) {
@@ -2754,15 +2762,15 @@ static int rollback_is_safe(void)
 static int reset_merge(const struct object_id *oid)
 {
        int ret;
-       struct argv_array argv = ARGV_ARRAY_INIT;
+       struct strvec argv = STRVEC_INIT;
 
-       argv_array_pushl(&argv, "reset", "--merge", NULL);
+       strvec_pushl(&argv, "reset", "--merge", NULL);
 
        if (!is_null_oid(oid))
-               argv_array_push(&argv, oid_to_hex(oid));
+               strvec_push(&argv, oid_to_hex(oid));
 
-       ret = run_command_v_opt(argv.argv, RUN_GIT_CMD);
-       argv_array_clear(&argv);
+       ret = run_command_v_opt(argv.v, RUN_GIT_CMD);
+       strvec_clear(&argv);
 
        return ret;
 }
@@ -2771,8 +2779,8 @@ static int rollback_single_pick(struct repository *r)
 {
        struct object_id head_oid;
 
-       if (!file_exists(git_path_cherry_pick_head(r)) &&
-           !file_exists(git_path_revert_head(r)))
+       if (!refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD") &&
+           !refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD"))
                return error(_("no cherry-pick or revert in progress"));
        if (read_ref_full("HEAD", 0, &head_oid, NULL))
                return error(_("cannot resolve HEAD"));
@@ -2866,7 +2874,7 @@ int sequencer_skip(struct repository *r, struct replay_opts *opts)
         */
        switch (opts->action) {
        case REPLAY_REVERT:
-               if (!file_exists(git_path_revert_head(r))) {
+               if (!refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD")) {
                        if (action != REPLAY_REVERT)
                                return error(_("no revert in progress"));
                        if (!rollback_is_safe())
@@ -2874,7 +2882,8 @@ int sequencer_skip(struct repository *r, struct replay_opts *opts)
                }
                break;
        case REPLAY_PICK:
-               if (!file_exists(git_path_cherry_pick_head(r))) {
+               if (!refs_ref_exists(get_main_ref_store(r),
+                                    "CHERRY_PICK_HEAD")) {
                        if (action != REPLAY_PICK)
                                return error(_("no cherry-pick in progress"));
                        if (!rollback_is_safe())
@@ -3125,17 +3134,17 @@ static int error_failed_squash(struct repository *r,
 
 static int do_exec(struct repository *r, const char *command_line)
 {
-       struct argv_array child_env = ARGV_ARRAY_INIT;
+       struct strvec child_env = STRVEC_INIT;
        const char *child_argv[] = { NULL, NULL };
        int dirty, status;
 
        fprintf(stderr, _("Executing: %s\n"), command_line);
        child_argv[0] = command_line;
-       argv_array_pushf(&child_env, "GIT_DIR=%s", absolute_path(get_git_dir()));
-       argv_array_pushf(&child_env, "GIT_WORK_TREE=%s",
-                        absolute_path(get_git_work_tree()));
+       strvec_pushf(&child_env, "GIT_DIR=%s", absolute_path(get_git_dir()));
+       strvec_pushf(&child_env, "GIT_WORK_TREE=%s",
+                    absolute_path(get_git_work_tree()));
        status = run_command_v_opt_cd_env(child_argv, RUN_USING_SHELL, NULL,
-                                         child_env.argv);
+                                         child_env.v);
 
        /* force re-reading of the cache */
        if (discard_index(r->index) < 0 || repo_read_index(r) < 0)
@@ -3165,7 +3174,7 @@ static int do_exec(struct repository *r, const char *command_line)
                status = 1;
        }
 
-       argv_array_clear(&child_env);
+       strvec_clear(&child_env);
 
        return status;
 }
@@ -3544,32 +3553,33 @@ static int do_merge(struct repository *r,
                }
 
                cmd.git_cmd = 1;
-               argv_array_push(&cmd.args, "merge");
-               argv_array_push(&cmd.args, "-s");
+               strvec_push(&cmd.args, "merge");
+               strvec_push(&cmd.args, "-s");
                if (!strategy)
-                       argv_array_push(&cmd.args, "octopus");
+                       strvec_push(&cmd.args, "octopus");
                else {
-                       argv_array_push(&cmd.args, strategy);
+                       strvec_push(&cmd.args, strategy);
                        for (k = 0; k < opts->xopts_nr; k++)
-                               argv_array_pushf(&cmd.args,
-                                                "-X%s", opts->xopts[k]);
+                               strvec_pushf(&cmd.args,
+                                            "-X%s", opts->xopts[k]);
                }
-               argv_array_push(&cmd.args, "--no-edit");
-               argv_array_push(&cmd.args, "--no-ff");
-               argv_array_push(&cmd.args, "--no-log");
-               argv_array_push(&cmd.args, "--no-stat");
-               argv_array_push(&cmd.args, "-F");
-               argv_array_push(&cmd.args, git_path_merge_msg(r));
+               strvec_push(&cmd.args, "--no-edit");
+               strvec_push(&cmd.args, "--no-ff");
+               strvec_push(&cmd.args, "--no-log");
+               strvec_push(&cmd.args, "--no-stat");
+               strvec_push(&cmd.args, "-F");
+               strvec_push(&cmd.args, git_path_merge_msg(r));
                if (opts->gpg_sign)
-                       argv_array_push(&cmd.args, opts->gpg_sign);
+                       strvec_push(&cmd.args, opts->gpg_sign);
 
                /* Add the tips to be merged */
                for (j = to_merge; j; j = j->next)
-                       argv_array_push(&cmd.args,
-                                       oid_to_hex(&j->item->object.oid));
+                       strvec_push(&cmd.args,
+                                   oid_to_hex(&j->item->object.oid));
 
                strbuf_release(&ref_name);
-               unlink(git_path_cherry_pick_head(r));
+               refs_delete_ref(get_main_ref_store(r), "", "CHERRY_PICK_HEAD",
+                               NULL, 0);
                rollback_lock_file(&lock);
 
                rollback_lock_file(&lock);
@@ -3694,8 +3704,8 @@ void create_autostash(struct repository *r, const char *path,
                struct child_process stash = CHILD_PROCESS_INIT;
                struct object_id oid;
 
-               argv_array_pushl(&stash.args,
-                                "stash", "create", "autostash", NULL);
+               strvec_pushl(&stash.args,
+                            "stash", "create", "autostash", NULL);
                stash.git_cmd = 1;
                stash.no_stdin = 1;
                strbuf_reset(&buf);
@@ -3734,9 +3744,9 @@ static int apply_save_autostash_oid(const char *stash_oid, int attempt_apply)
                child.git_cmd = 1;
                child.no_stdout = 1;
                child.no_stderr = 1;
-               argv_array_push(&child.args, "stash");
-               argv_array_push(&child.args, "apply");
-               argv_array_push(&child.args, stash_oid);
+               strvec_push(&child.args, "stash");
+               strvec_push(&child.args, "apply");
+               strvec_push(&child.args, stash_oid);
                ret = run_command(&child);
        }
 
@@ -3746,12 +3756,12 @@ static int apply_save_autostash_oid(const char *stash_oid, int attempt_apply)
                struct child_process store = CHILD_PROCESS_INIT;
 
                store.git_cmd = 1;
-               argv_array_push(&store.args, "stash");
-               argv_array_push(&store.args, "store");
-               argv_array_push(&store.args, "-m");
-               argv_array_push(&store.args, "autostash");
-               argv_array_push(&store.args, "-q");
-               argv_array_push(&store.args, stash_oid);
+               strvec_push(&store.args, "stash");
+               strvec_push(&store.args, "store");
+               strvec_push(&store.args, "-m");
+               strvec_push(&store.args, "autostash");
+               strvec_push(&store.args, "-q");
+               strvec_push(&store.args, stash_oid);
                if (run_command(&store))
                        ret = error(_("cannot store %s"), stash_oid);
                else
@@ -3831,9 +3841,9 @@ static int run_git_checkout(struct repository *r, struct replay_opts *opts,
 
        cmd.git_cmd = 1;
 
-       argv_array_push(&cmd.args, "checkout");
-       argv_array_push(&cmd.args, commit);
-       argv_array_pushf(&cmd.env_array, GIT_REFLOG_ACTION "=%s", action);
+       strvec_push(&cmd.args, "checkout");
+       strvec_push(&cmd.args, commit);
+       strvec_pushf(&cmd.env_array, GIT_REFLOG_ACTION "=%s", action);
 
        if (opts->verbose)
                ret = run_command(&cmd);
@@ -4157,9 +4167,9 @@ cleanup_head_ref:
 
                        child.in = open(rebase_path_rewritten_list(), O_RDONLY);
                        child.git_cmd = 1;
-                       argv_array_push(&child.args, "notes");
-                       argv_array_push(&child.args, "copy");
-                       argv_array_push(&child.args, "--for-rewrite=rebase");
+                       strvec_push(&child.args, "notes");
+                       strvec_push(&child.args, "copy");
+                       strvec_push(&child.args, "--for-rewrite=rebase");
                        /* we don't care if this copying failed */
                        run_command(&child);
 
@@ -4170,8 +4180,8 @@ cleanup_head_ref:
                                        O_RDONLY);
                                hook.stdout_to_stderr = 1;
                                hook.trace2_hook_name = "post-rewrite";
-                               argv_array_push(&hook.args, post_rewrite_hook);
-                               argv_array_push(&hook.args, "rebase");
+                               strvec_push(&hook.args, post_rewrite_hook);
+                               strvec_push(&hook.args, "rebase");
                                /* we don't care if this hook failed */
                                run_command(&hook);
                        }
@@ -4201,8 +4211,8 @@ static int continue_single_pick(struct repository *r)
 {
        const char *argv[] = { "commit", NULL };
 
-       if (!file_exists(git_path_cherry_pick_head(r)) &&
-           !file_exists(git_path_revert_head(r)))
+       if (!refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD") &&
+           !refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD"))
                return error(_("no cherry-pick or revert in progress"));
        return run_command_v_opt(argv, RUN_GIT_CMD);
 }
@@ -4318,9 +4328,10 @@ static int commit_staged_changes(struct repository *r,
        }
 
        if (is_clean) {
-               const char *cherry_pick_head = git_path_cherry_pick_head(r);
-
-               if (file_exists(cherry_pick_head) && unlink(cherry_pick_head))
+               if (refs_ref_exists(get_main_ref_store(r),
+                                   "CHERRY_PICK_HEAD") &&
+                   refs_delete_ref(get_main_ref_store(r), "",
+                                   "CHERRY_PICK_HEAD", NULL, 0))
                        return error(_("could not remove CHERRY_PICK_HEAD"));
                if (!final_fixup)
                        return 0;
@@ -4379,8 +4390,9 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts)
 
        if (!is_rebase_i(opts)) {
                /* Verify that the conflict has been resolved */
-               if (file_exists(git_path_cherry_pick_head(r)) ||
-                   file_exists(git_path_revert_head(r))) {
+               if (refs_ref_exists(get_main_ref_store(r),
+                                   "CHERRY_PICK_HEAD") ||
+                   refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD")) {
                        res = continue_single_pick(r);
                        if (res)
                                goto release_todo_list;
@@ -5178,13 +5190,14 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
                    struct string_list *commands, unsigned autosquash,
                    struct todo_list *todo_list)
 {
-       const char *shortonto, *todo_file = rebase_path_todo();
+       char shortonto[GIT_MAX_HEXSZ + 1];
+       const char *todo_file = rebase_path_todo();
        struct todo_list new_todo = TODO_LIST_INIT;
        struct strbuf *buf = &todo_list->buf, buf2 = STRBUF_INIT;
        struct object_id oid = onto->object.oid;
        int res;
 
-       shortonto = find_unique_abbrev(&oid, DEFAULT_ABBREV);
+       find_unique_abbrev_r(shortonto, &oid, DEFAULT_ABBREV);
 
        if (buf->len == 0) {
                struct todo_item *item = append_new_todo(todo_list);
@@ -5442,7 +5455,7 @@ int todo_list_rearrange_squash(struct todo_list *todo_list)
 
 int sequencer_determine_whence(struct repository *r, enum commit_whence *whence)
 {
-       if (file_exists(git_path_cherry_pick_head(r))) {
+       if (refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD")) {
                struct object_id cherry_pick_head, rebase_head;
 
                if (file_exists(git_path_seq_dir()))
diff --git a/serve.c b/serve.c
index fbd2fcdfb52f7151e53bed7fdc182305bc015df2..f6341206c4e30122c3cb819ef8c01f6d2be06d22 100644 (file)
--- a/serve.c
+++ b/serve.c
@@ -3,7 +3,7 @@
 #include "config.h"
 #include "pkt-line.h"
 #include "version.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "ls-refs.h"
 #include "serve.h"
 #include "upload-pack.h"
@@ -56,7 +56,7 @@ struct protocol_capability {
         * This field should be NULL for capabilities which are not commands.
         */
        int (*command)(struct repository *r,
-                      struct argv_array *keys,
+                      struct strvec *keys,
                       struct packet_reader *request);
 };
 
@@ -142,13 +142,13 @@ static int is_command(const char *key, struct protocol_capability **command)
        return 0;
 }
 
-int has_capability(const struct argv_array *keys, const char *capability,
+int has_capability(const struct strvec *keys, const char *capability,
                   const char **value)
 {
        int i;
-       for (i = 0; i < keys->argc; i++) {
+       for (i = 0; i < keys->nr; i++) {
                const char *out;
-               if (skip_prefix(keys->argv[i], capability, &out) &&
+               if (skip_prefix(keys->v[i], capability, &out) &&
                    (!*out || *out == '=')) {
                        if (value) {
                                if (*out == '=')
@@ -162,7 +162,7 @@ int has_capability(const struct argv_array *keys, const char *capability,
        return 0;
 }
 
-static void check_algorithm(struct repository *r, struct argv_array *keys)
+static void check_algorithm(struct repository *r, struct strvec *keys)
 {
        int client = GIT_HASH_SHA1, server = hash_algo_by_ptr(r->hash_algo);
        const char *algo_name;
@@ -187,7 +187,7 @@ static int process_request(void)
 {
        enum request_state state = PROCESS_REQUEST_KEYS;
        struct packet_reader reader;
-       struct argv_array keys = ARGV_ARRAY_INIT;
+       struct strvec keys = STRVEC_INIT;
        struct protocol_capability *command = NULL;
 
        packet_reader_init(&reader, 0, NULL, 0,
@@ -211,7 +211,7 @@ static int process_request(void)
                        /* collect request; a sequence of keys and values */
                        if (is_command(reader.line, &command) ||
                            is_valid_capability(reader.line))
-                               argv_array_push(&keys, reader.line);
+                               strvec_push(&keys, reader.line);
                        else
                                die("unknown capability '%s'", reader.line);
 
@@ -223,7 +223,7 @@ static int process_request(void)
                         * If no command and no keys were given then the client
                         * wanted to terminate the connection.
                         */
-                       if (!keys.argc)
+                       if (!keys.nr)
                                return 1;
 
                        /*
@@ -254,7 +254,7 @@ static int process_request(void)
 
        command->command(the_repository, &keys, &reader);
 
-       argv_array_clear(&keys);
+       strvec_clear(&keys);
        return 0;
 }
 
diff --git a/serve.h b/serve.h
index 42ddca7f8b4fdd6bb78ab6da710a086645dd44f2..fc2683e24d30577c41d4800239bf19b134316140 100644 (file)
--- a/serve.h
+++ b/serve.h
@@ -1,8 +1,8 @@
 #ifndef SERVE_H
 #define SERVE_H
 
-struct argv_array;
-int has_capability(const struct argv_array *keys, const char *capability,
+struct strvec;
+int has_capability(const struct strvec *keys, const char *capability,
                   const char **value);
 
 struct serve_options {
diff --git a/setup.c b/setup.c
index 3a81307602e2b029115f0c6db2c985508e590bd1..c04cd25a30dfe0e97d93087c0e7f29910d1b46a5 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -447,6 +447,63 @@ static int read_worktree_config(const char *var, const char *value, void *vdata)
        return 0;
 }
 
+enum extension_result {
+       EXTENSION_ERROR = -1, /* compatible with error(), etc */
+       EXTENSION_UNKNOWN = 0,
+       EXTENSION_OK = 1
+};
+
+/*
+ * Do not add new extensions to this function. It handles extensions which are
+ * respected even in v0-format repositories for historical compatibility.
+ */
+static enum extension_result handle_extension_v0(const char *var,
+                                                const char *value,
+                                                const char *ext,
+                                                struct repository_format *data)
+{
+               if (!strcmp(ext, "noop")) {
+                       return EXTENSION_OK;
+               } else if (!strcmp(ext, "preciousobjects")) {
+                       data->precious_objects = git_config_bool(var, value);
+                       return EXTENSION_OK;
+               } else if (!strcmp(ext, "partialclone")) {
+                       if (!value)
+                               return config_error_nonbool(var);
+                       data->partial_clone = xstrdup(value);
+                       return EXTENSION_OK;
+               } else if (!strcmp(ext, "worktreeconfig")) {
+                       data->worktree_config = git_config_bool(var, value);
+                       return EXTENSION_OK;
+               }
+
+               return EXTENSION_UNKNOWN;
+}
+
+/*
+ * Record any new extensions in this function.
+ */
+static enum extension_result handle_extension(const char *var,
+                                             const char *value,
+                                             const char *ext,
+                                             struct repository_format *data)
+{
+       if (!strcmp(ext, "noop-v1")) {
+               return EXTENSION_OK;
+       } else if (!strcmp(ext, "objectformat")) {
+               int format;
+
+               if (!value)
+                       return config_error_nonbool(var);
+               format = hash_algo_by_name(value);
+               if (format == GIT_HASH_UNKNOWN)
+                       return error("invalid value for 'extensions.objectformat'");
+               data->hash_algo = format;
+               return EXTENSION_OK;
+       }
+       return EXTENSION_UNKNOWN;
+}
+
 static int check_repo_format(const char *var, const char *value, void *vdata)
 {
        struct repository_format *data = vdata;
@@ -455,23 +512,25 @@ static int check_repo_format(const char *var, const char *value, void *vdata)
        if (strcmp(var, "core.repositoryformatversion") == 0)
                data->version = git_config_int(var, value);
        else if (skip_prefix(var, "extensions.", &ext)) {
-               /*
-                * record any known extensions here; otherwise,
-                * we fall through to recording it as unknown, and
-                * check_repository_format will complain
-                */
-               if (!strcmp(ext, "noop"))
-                       ;
-               else if (!strcmp(ext, "preciousobjects"))
-                       data->precious_objects = git_config_bool(var, value);
-               else if (!strcmp(ext, "partialclone")) {
-                       if (!value)
-                               return config_error_nonbool(var);
-                       data->partial_clone = xstrdup(value);
-               } else if (!strcmp(ext, "worktreeconfig"))
-                       data->worktree_config = git_config_bool(var, value);
-               else
+               switch (handle_extension_v0(var, value, ext, data)) {
+               case EXTENSION_ERROR:
+                       return -1;
+               case EXTENSION_OK:
+                       return 0;
+               case EXTENSION_UNKNOWN:
+                       break;
+               }
+
+               switch (handle_extension(var, value, ext, data)) {
+               case EXTENSION_ERROR:
+                       return -1;
+               case EXTENSION_OK:
+                       string_list_append(&data->v1_only_extensions, ext);
+                       return 0;
+               case EXTENSION_UNKNOWN:
                        string_list_append(&data->unknown_extensions, ext);
+                       return 0;
+               }
        }
 
        return read_worktree_config(var, value, vdata);
@@ -510,6 +569,7 @@ static int check_repository_format_gently(const char *gitdir, struct repository_
        set_repository_format_partial_clone(candidate->partial_clone);
        repository_format_worktree_config = candidate->worktree_config;
        string_list_clear(&candidate->unknown_extensions, 0);
+       string_list_clear(&candidate->v1_only_extensions, 0);
 
        if (repository_format_worktree_config) {
                /*
@@ -588,6 +648,7 @@ int read_repository_format(struct repository_format *format, const char *path)
 void clear_repository_format(struct repository_format *format)
 {
        string_list_clear(&format->unknown_extensions, 0);
+       string_list_clear(&format->v1_only_extensions, 0);
        free(format->work_tree);
        free(format->partial_clone);
        init_repository_format(format);
@@ -613,6 +674,18 @@ int verify_repository_format(const struct repository_format *format,
                return -1;
        }
 
+       if (format->version == 0 && format->v1_only_extensions.nr) {
+               int i;
+
+               strbuf_addstr(err,
+                             _("repo version is 0, but v1-only extensions found:"));
+
+               for (i = 0; i < format->v1_only_extensions.nr; i++)
+                       strbuf_addf(err, "\n\t%s",
+                                   format->v1_only_extensions.items[i].string);
+               return -1;
+       }
+
        return 0;
 }
 
index ccd34dd9e8ce9c498facd694162c30656bfe3195..dd65bd5c681513c1f7c9bf908dc9f8675e24a829 100644 (file)
@@ -763,18 +763,18 @@ static void fill_alternate_refs_command(struct child_process *cmd,
        if (!git_config_get_value("core.alternateRefsCommand", &value)) {
                cmd->use_shell = 1;
 
-               argv_array_push(&cmd->args, value);
-               argv_array_push(&cmd->args, repo_path);
+               strvec_push(&cmd->args, value);
+               strvec_push(&cmd->args, repo_path);
        } else {
                cmd->git_cmd = 1;
 
-               argv_array_pushf(&cmd->args, "--git-dir=%s", repo_path);
-               argv_array_push(&cmd->args, "for-each-ref");
-               argv_array_push(&cmd->args, "--format=%(objectname)");
+               strvec_pushf(&cmd->args, "--git-dir=%s", repo_path);
+               strvec_push(&cmd->args, "for-each-ref");
+               strvec_push(&cmd->args, "--format=%(objectname)");
 
                if (!git_config_get_value("core.alternateRefsPrefixes", &value)) {
-                       argv_array_push(&cmd->args, "--");
-                       argv_array_split(&cmd->args, value);
+                       strvec_push(&cmd->args, "--");
+                       strvec_split(&cmd->args, value);
                }
        }
 
@@ -1600,7 +1600,8 @@ int pretend_object_file(void *buf, unsigned long len, enum object_type type,
        struct cached_object *co;
 
        hash_object_file(the_hash_algo, buf, len, type_name(type), oid);
-       if (has_object_file(oid) || find_cached_object(oid))
+       if (has_object_file_with_flags(oid, OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT) ||
+           find_cached_object(oid))
                return 0;
        ALLOC_GROW(cached_objects, cached_object_nr + 1, cached_object_alloc);
        co = &cached_objects[cached_object_nr++];
@@ -1988,6 +1989,18 @@ int force_object_loose(const struct object_id *oid, time_t mtime)
        return ret;
 }
 
+int has_object(struct repository *r, const struct object_id *oid,
+              unsigned flags)
+{
+       int quick = !(flags & HAS_OBJECT_RECHECK_PACKED);
+       unsigned object_info_flags = OBJECT_INFO_SKIP_FETCH_OBJECT |
+               (quick ? OBJECT_INFO_QUICK : 0);
+
+       if (!startup_info->have_repository)
+               return 0;
+       return oid_object_info_extended(r, oid, NULL, object_info_flags) >= 0;
+}
+
 int repo_has_object_file_with_flags(struct repository *r,
                                    const struct object_id *oid, int flags)
 {
index b826de9b676c1c0d61fb30638284ed32c0f8403e..91b9e1073c9fb8427c42eb8a638e628f4a13c22a 100644 (file)
--- a/shallow.c
+++ b/shallow.c
@@ -110,6 +110,10 @@ void rollback_shallow_file(struct repository *r, struct shallow_lock *lk)
  * supports a "valid" flag.
  */
 define_commit_slab(commit_depth, int *);
+static void free_depth_in_slab(int **ptr)
+{
+       FREE_AND_NULL(*ptr);
+}
 struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
                int shallow_flag, int not_shallow_flag)
 {
@@ -176,15 +180,7 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
                        }
                }
        }
-       for (i = 0; i < depths.slab_count; i++) {
-               int j;
-
-               if (!depths.slab[i])
-                       continue;
-               for (j = 0; j < depths.slab_size; j++)
-                       free(depths.slab[i][j]);
-       }
-       clear_commit_depth(&depths);
+       deep_clear_commit_depth(&depths, free_depth_in_slab);
 
        return result;
 }
index ef851113c44ee91e594734bf68567110b7ac8c6b..0a60662fa64b34a9b70c9c362fac02aa8c61083c 100644 (file)
@@ -147,7 +147,7 @@ int demultiplex_sideband(const char *me, char *buf, int len,
        switch (band) {
        case 3:
                if (die_on_error)
-                       die("remote error: %s", buf + 1);
+                       die(_("remote error: %s"), buf + 1);
                strbuf_addf(scratch, "%s%s", scratch->len ? "\n" : "",
                            DISPLAY_PREFIX);
                maybe_colorize_sideband(scratch, buf + 1, len);
index e6154e4ea9552cfc2b868453f017ba786cd24a2f..c0e8ad670d0a17a28fd049b6814d8e77c7654dc2 100644 (file)
@@ -79,8 +79,10 @@ void move_cache_to_base_index(struct index_state *istate)
        if (si->base &&
                si->base->ce_mem_pool) {
 
-               if (!istate->ce_mem_pool)
-                       mem_pool_init(&istate->ce_mem_pool, 0);
+               if (!istate->ce_mem_pool) {
+                       istate->ce_mem_pool = xmalloc(sizeof(struct mem_pool));
+                       mem_pool_init(istate->ce_mem_pool, 0);
+               }
 
                mem_pool_combine(istate->ce_mem_pool, istate->split_index->base->ce_mem_pool);
        }
diff --git a/strvec.c b/strvec.c
new file mode 100644 (file)
index 0000000..21dce0a
--- /dev/null
+++ b/strvec.c
@@ -0,0 +1,109 @@
+#include "cache.h"
+#include "strvec.h"
+#include "strbuf.h"
+
+const char *empty_strvec[] = { NULL };
+
+void strvec_init(struct strvec *array)
+{
+       array->v = empty_strvec;
+       array->nr = 0;
+       array->alloc = 0;
+}
+
+static void strvec_push_nodup(struct strvec *array, const char *value)
+{
+       if (array->v == empty_strvec)
+               array->v = NULL;
+
+       ALLOC_GROW(array->v, array->nr + 2, array->alloc);
+       array->v[array->nr++] = value;
+       array->v[array->nr] = NULL;
+}
+
+const char *strvec_push(struct strvec *array, const char *value)
+{
+       strvec_push_nodup(array, xstrdup(value));
+       return array->v[array->nr - 1];
+}
+
+const char *strvec_pushf(struct strvec *array, const char *fmt, ...)
+{
+       va_list ap;
+       struct strbuf v = STRBUF_INIT;
+
+       va_start(ap, fmt);
+       strbuf_vaddf(&v, fmt, ap);
+       va_end(ap);
+
+       strvec_push_nodup(array, strbuf_detach(&v, NULL));
+       return array->v[array->nr - 1];
+}
+
+void strvec_pushl(struct strvec *array, ...)
+{
+       va_list ap;
+       const char *arg;
+
+       va_start(ap, array);
+       while ((arg = va_arg(ap, const char *)))
+               strvec_push(array, arg);
+       va_end(ap);
+}
+
+void strvec_pushv(struct strvec *array, const char **items)
+{
+       for (; *items; items++)
+               strvec_push(array, *items);
+}
+
+void strvec_pop(struct strvec *array)
+{
+       if (!array->nr)
+               return;
+       free((char *)array->v[array->nr - 1]);
+       array->v[array->nr - 1] = NULL;
+       array->nr--;
+}
+
+void strvec_split(struct strvec *array, const char *to_split)
+{
+       while (isspace(*to_split))
+               to_split++;
+       for (;;) {
+               const char *p = to_split;
+
+               if (!*p)
+                       break;
+
+               while (*p && !isspace(*p))
+                       p++;
+               strvec_push_nodup(array, xstrndup(to_split, p - to_split));
+
+               while (isspace(*p))
+                       p++;
+               to_split = p;
+       }
+}
+
+void strvec_clear(struct strvec *array)
+{
+       if (array->v != empty_strvec) {
+               int i;
+               for (i = 0; i < array->nr; i++)
+                       free((char *)array->v[i]);
+               free(array->v);
+       }
+       strvec_init(array);
+}
+
+const char **strvec_detach(struct strvec *array)
+{
+       if (array->v == empty_strvec)
+               return xcalloc(1, sizeof(const char *));
+       else {
+               const char **ret = array->v;
+               strvec_init(array);
+               return ret;
+       }
+}
similarity index 50%
rename from argv-array.h
rename to strvec.h
index a7d3b107077aba26602e0ffe02eea1f2a8174cbb..fdcad75b45b33fdc6974fd35c2102ecbcaba31e4 100644 (file)
+++ b/strvec.h
@@ -1,11 +1,11 @@
-#ifndef ARGV_ARRAY_H
-#define ARGV_ARRAY_H
+#ifndef STRVEC_H
+#define STRVEC_H
 
 /**
- * The argv-array API allows one to dynamically build and store
- * NULL-terminated lists.  An argv-array maintains the invariant that the
- * `argv` member always points to a non-NULL array, and that the array is
- * always NULL-terminated at the element pointed to by `argv[argc]`. This
+ * The strvec API allows one to dynamically build and store
+ * NULL-terminated arrays of strings. A strvec maintains the invariant that the
+ * `items` member always points to a non-NULL array, and that the array is
+ * always NULL-terminated at the element pointed to by `items[nr]`. This
  * makes the result suitable for passing to functions expecting to receive
  * argv from main().
  *
  * it contains an item structure with a `util` field that is not compatible
  * with the traditional argv interface.
  *
- * Each `argv_array` manages its own memory. Any strings pushed into the
- * array are duplicated, and all memory is freed by argv_array_clear().
+ * Each `strvec` manages its own memory. Any strings pushed into the
+ * array are duplicated, and all memory is freed by strvec_clear().
  */
 
-extern const char *empty_argv[];
+extern const char *empty_strvec[];
 
 /**
  * A single array. This should be initialized by assignment from
- * `ARGV_ARRAY_INIT`, or by calling `argv_array_init`. The `argv`
- * member contains the actual array; the `argc` member contains the
+ * `STRVEC_INIT`, or by calling `strvec_init`. The `items`
+ * member contains the actual array; the `nr` member contains the
  * number of elements in the array, not including the terminating
  * NULL.
  */
-struct argv_array {
-       const char **argv;
-       int argc;
+struct strvec {
+       const char **v;
+       int nr;
        int alloc;
 };
 
-#define ARGV_ARRAY_INIT { empty_argv, 0, 0 }
+#define STRVEC_INIT { empty_strvec, 0, 0 }
 
 /**
  * Initialize an array. This is no different than assigning from
- * `ARGV_ARRAY_INIT`.
+ * `STRVEC_INIT`.
  */
-void argv_array_init(struct argv_array *);
+void strvec_init(struct strvec *);
 
 /* Push a copy of a string onto the end of the array. */
-const char *argv_array_push(struct argv_array *, const char *);
+const char *strvec_push(struct strvec *, const char *);
 
 /**
  * Format a string and push it onto the end of the array. This is a
- * convenience wrapper combining `strbuf_addf` and `argv_array_push`.
+ * convenience wrapper combining `strbuf_addf` and `strvec_push`.
  */
 __attribute__((format (printf,2,3)))
-const char *argv_array_pushf(struct argv_array *, const char *fmt, ...);
+const char *strvec_pushf(struct strvec *, const char *fmt, ...);
 
 /**
  * Push a list of strings onto the end of the array. The arguments
@@ -57,33 +57,33 @@ const char *argv_array_pushf(struct argv_array *, const char *fmt, ...);
  * argument.
  */
 LAST_ARG_MUST_BE_NULL
-void argv_array_pushl(struct argv_array *, ...);
+void strvec_pushl(struct strvec *, ...);
 
 /* Push a null-terminated array of strings onto the end of the array. */
-void argv_array_pushv(struct argv_array *, const char **);
+void strvec_pushv(struct strvec *, const char **);
 
 /**
  * Remove the final element from the array. If there are no
  * elements in the array, do nothing.
  */
-void argv_array_pop(struct argv_array *);
+void strvec_pop(struct strvec *);
 
 /* Splits by whitespace; does not handle quoted arguments! */
-void argv_array_split(struct argv_array *, const char *);
+void strvec_split(struct strvec *, const char *);
 
 /**
  * Free all memory associated with the array and return it to the
  * initial, empty state.
  */
-void argv_array_clear(struct argv_array *);
+void strvec_clear(struct strvec *);
 
 /**
- * Disconnect the `argv` member from the `argv_array` struct and
+ * Disconnect the `items` member from the `strvec` struct and
  * return it. The caller is responsible for freeing the memory used
  * by the array, and by the strings it references. After detaching,
- * the `argv_array` is in a reinitialized state and can be pushed
+ * the `strvec` is in a reinitialized state and can be pushed
  * into again.
  */
-const char **argv_array_detach(struct argv_array *);
+const char **strvec_detach(struct strvec *);
 
-#endif /* ARGV_ARRAY_H */
+#endif /* STRVEC_H */
index 1b1af9dcbd95990dfd9d0ef11471f766a6015a80..dfa790d3ff91c637efc14843a9a26e507f116b83 100644 (file)
@@ -84,7 +84,7 @@ int subprocess_start(struct hashmap *hashmap, struct subprocess_entry *entry, co
        process = &entry->process;
 
        child_process_init(process);
-       argv_array_push(&process->args, cmd);
+       strvec_push(&process->args, cmd);
        process->use_shell = 1;
        process->in = -1;
        process->out = -1;
index e2ef5698c893c3587e500ac88b46aa9ba68609ea..d0b70ca536143adc41d66a448e6b3f9243067076 100644 (file)
@@ -13,7 +13,7 @@
 #include "refs.h"
 #include "string-list.h"
 #include "oid-array.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "blob.h"
 #include "thread-utils.h"
 #include "quote.h"
@@ -194,7 +194,7 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
                char *key;
 
                key = xstrfmt("submodule.%s.ignore", submodule->name);
-               if (repo_config_get_string_const(the_repository, key, &ignore))
+               if (repo_config_get_string_tmp(the_repository, key, &ignore))
                        ignore = submodule->ignore;
                free(key);
 
@@ -262,17 +262,17 @@ int is_submodule_active(struct repository *repo, const char *path)
        sl = repo_config_get_value_multi(repo, "submodule.active");
        if (sl) {
                struct pathspec ps;
-               struct argv_array args = ARGV_ARRAY_INIT;
+               struct strvec args = STRVEC_INIT;
                const struct string_list_item *item;
 
                for_each_string_list_item(item, sl) {
-                       argv_array_push(&args, item->string);
+                       strvec_push(&args, item->string);
                }
 
-               parse_pathspec(&ps, 0, 0, NULL, args.argv);
+               parse_pathspec(&ps, 0, 0, NULL, args.v);
                ret = match_pathspec(repo->index, &ps, path, strlen(path), 0, NULL, 1);
 
-               argv_array_clear(&args);
+               strvec_clear(&args);
                clear_pathspec(&ps);
                return ret;
        }
@@ -481,27 +481,27 @@ static void print_submodule_summary(struct repository *r, struct rev_info *rev,
        strbuf_release(&sb);
 }
 
-static void prepare_submodule_repo_env_no_git_dir(struct argv_array *out)
+static void prepare_submodule_repo_env_no_git_dir(struct strvec *out)
 {
        const char * const *var;
 
        for (var = local_repo_env; *var; var++) {
                if (strcmp(*var, CONFIG_DATA_ENVIRONMENT))
-                       argv_array_push(out, *var);
+                       strvec_push(out, *var);
        }
 }
 
-void prepare_submodule_repo_env(struct argv_array *out)
+void prepare_submodule_repo_env(struct strvec *out)
 {
        prepare_submodule_repo_env_no_git_dir(out);
-       argv_array_pushf(out, "%s=%s", GIT_DIR_ENVIRONMENT,
-                        DEFAULT_GIT_DIR_ENVIRONMENT);
+       strvec_pushf(out, "%s=%s", GIT_DIR_ENVIRONMENT,
+                    DEFAULT_GIT_DIR_ENVIRONMENT);
 }
 
-static void prepare_submodule_repo_env_in_gitdir(struct argv_array *out)
+static void prepare_submodule_repo_env_in_gitdir(struct strvec *out)
 {
        prepare_submodule_repo_env_no_git_dir(out);
-       argv_array_pushf(out, "%s=.", GIT_DIR_ENVIRONMENT);
+       strvec_pushf(out, "%s=.", GIT_DIR_ENVIRONMENT);
 }
 
 /*
@@ -681,22 +681,22 @@ void show_submodule_inline_diff(struct diff_options *o, const char *path,
        cp.no_stdin = 1;
 
        /* TODO: other options may need to be passed here. */
-       argv_array_pushl(&cp.args, "diff", "--submodule=diff", NULL);
-       argv_array_pushf(&cp.args, "--color=%s", want_color(o->use_color) ?
+       strvec_pushl(&cp.args, "diff", "--submodule=diff", NULL);
+       strvec_pushf(&cp.args, "--color=%s", want_color(o->use_color) ?
                         "always" : "never");
 
        if (o->flags.reverse_diff) {
-               argv_array_pushf(&cp.args, "--src-prefix=%s%s/",
-                                o->b_prefix, path);
-               argv_array_pushf(&cp.args, "--dst-prefix=%s%s/",
-                                o->a_prefix, path);
+               strvec_pushf(&cp.args, "--src-prefix=%s%s/",
+                            o->b_prefix, path);
+               strvec_pushf(&cp.args, "--dst-prefix=%s%s/",
+                            o->a_prefix, path);
        } else {
-               argv_array_pushf(&cp.args, "--src-prefix=%s%s/",
-                                o->a_prefix, path);
-               argv_array_pushf(&cp.args, "--dst-prefix=%s%s/",
-                                o->b_prefix, path);
+               strvec_pushf(&cp.args, "--src-prefix=%s%s/",
+                            o->a_prefix, path);
+               strvec_pushf(&cp.args, "--dst-prefix=%s%s/",
+                            o->b_prefix, path);
        }
-       argv_array_push(&cp.args, oid_to_hex(old_oid));
+       strvec_push(&cp.args, oid_to_hex(old_oid));
        /*
         * If the submodule has modified content, we will diff against the
         * work tree, under the assumption that the user has asked for the
@@ -704,7 +704,7 @@ void show_submodule_inline_diff(struct diff_options *o, const char *path,
         * haven't yet been committed to the submodule yet.
         */
        if (!(dirty_submodule & DIRTY_SUBMODULE_MODIFIED))
-               argv_array_push(&cp.args, oid_to_hex(new_oid));
+               strvec_push(&cp.args, oid_to_hex(new_oid));
 
        prepare_submodule_repo_env(&cp.env_array);
        if (start_command(&cp))
@@ -836,13 +836,13 @@ static void collect_changed_submodules_cb(struct diff_queue_struct *q,
  */
 static void collect_changed_submodules(struct repository *r,
                                       struct string_list *changed,
-                                      struct argv_array *argv)
+                                      struct strvec *argv)
 {
        struct rev_info rev;
        const struct commit *commit;
 
        repo_init_revisions(r, &rev, NULL);
-       setup_revisions(argv->argc, argv->argv, &rev, NULL);
+       setup_revisions(argv->nr, argv->v, &rev, NULL);
        if (prepare_revision_walk(&rev))
                die(_("revision walk setup failed"));
 
@@ -879,8 +879,8 @@ static int has_remote(const char *refname, const struct object_id *oid,
 
 static int append_oid_to_argv(const struct object_id *oid, void *data)
 {
-       struct argv_array *argv = data;
-       argv_array_push(argv, oid_to_hex(oid));
+       struct strvec *argv = data;
+       strvec_push(argv, oid_to_hex(oid));
        return 0;
 }
 
@@ -941,9 +941,9 @@ static int submodule_has_commits(struct repository *r,
                struct child_process cp = CHILD_PROCESS_INIT;
                struct strbuf out = STRBUF_INIT;
 
-               argv_array_pushl(&cp.args, "rev-list", "-n", "1", NULL);
+               strvec_pushl(&cp.args, "rev-list", "-n", "1", NULL);
                oid_array_for_each_unique(commits, append_oid_to_argv, &cp.args);
-               argv_array_pushl(&cp.args, "--not", "--all", NULL);
+               strvec_pushl(&cp.args, "--not", "--all", NULL);
 
                prepare_submodule_repo_env(&cp.env_array);
                cp.git_cmd = 1;
@@ -982,9 +982,9 @@ static int submodule_needs_pushing(struct repository *r,
                struct strbuf buf = STRBUF_INIT;
                int needs_pushing = 0;
 
-               argv_array_push(&cp.args, "rev-list");
+               strvec_push(&cp.args, "rev-list");
                oid_array_for_each_unique(commits, append_oid_to_argv, &cp.args);
-               argv_array_pushl(&cp.args, "--not", "--remotes", "-n", "1" , NULL);
+               strvec_pushl(&cp.args, "--not", "--remotes", "-n", "1" , NULL);
 
                prepare_submodule_repo_env(&cp.env_array);
                cp.git_cmd = 1;
@@ -1012,13 +1012,13 @@ int find_unpushed_submodules(struct repository *r,
 {
        struct string_list submodules = STRING_LIST_INIT_DUP;
        struct string_list_item *name;
-       struct argv_array argv = ARGV_ARRAY_INIT;
+       struct strvec argv = STRVEC_INIT;
 
-       /* argv.argv[0] will be ignored by setup_revisions */
-       argv_array_push(&argv, "find_unpushed_submodules");
+       /* argv.v[0] will be ignored by setup_revisions */
+       strvec_push(&argv, "find_unpushed_submodules");
        oid_array_for_each_unique(commits, append_oid_to_argv, &argv);
-       argv_array_push(&argv, "--not");
-       argv_array_pushf(&argv, "--remotes=%s", remotes_name);
+       strvec_push(&argv, "--not");
+       strvec_pushf(&argv, "--remotes=%s", remotes_name);
 
        collect_changed_submodules(r, &submodules, &argv);
 
@@ -1041,7 +1041,7 @@ int find_unpushed_submodules(struct repository *r,
        }
 
        free_submodules_oids(&submodules);
-       argv_array_clear(&argv);
+       strvec_clear(&argv);
 
        return needs_pushing->nr;
 }
@@ -1054,22 +1054,22 @@ static int push_submodule(const char *path,
 {
        if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) {
                struct child_process cp = CHILD_PROCESS_INIT;
-               argv_array_push(&cp.args, "push");
+               strvec_push(&cp.args, "push");
                if (dry_run)
-                       argv_array_push(&cp.args, "--dry-run");
+                       strvec_push(&cp.args, "--dry-run");
 
                if (push_options && push_options->nr) {
                        const struct string_list_item *item;
                        for_each_string_list_item(item, push_options)
-                               argv_array_pushf(&cp.args, "--push-option=%s",
-                                                item->string);
+                               strvec_pushf(&cp.args, "--push-option=%s",
+                                            item->string);
                }
 
                if (remote->origin != REMOTE_UNCONFIGURED) {
                        int i;
-                       argv_array_push(&cp.args, remote->name);
+                       strvec_push(&cp.args, remote->name);
                        for (i = 0; i < rs->raw_nr; i++)
-                               argv_array_push(&cp.args, rs->raw[i]);
+                               strvec_push(&cp.args, rs->raw[i]);
                }
 
                prepare_submodule_repo_env(&cp.env_array);
@@ -1095,13 +1095,13 @@ static void submodule_push_check(const char *path, const char *head,
        struct child_process cp = CHILD_PROCESS_INIT;
        int i;
 
-       argv_array_push(&cp.args, "submodule--helper");
-       argv_array_push(&cp.args, "push-check");
-       argv_array_push(&cp.args, head);
-       argv_array_push(&cp.args, remote->name);
+       strvec_push(&cp.args, "submodule--helper");
+       strvec_push(&cp.args, "push-check");
+       strvec_push(&cp.args, head);
+       strvec_push(&cp.args, remote->name);
 
        for (i = 0; i < rs->raw_nr; i++)
-               argv_array_push(&cp.args, rs->raw[i]);
+               strvec_push(&cp.args, rs->raw[i]);
 
        prepare_submodule_repo_env(&cp.env_array);
        cp.git_cmd = 1;
@@ -1189,17 +1189,17 @@ void check_for_new_submodule_commits(struct object_id *oid)
 static void calculate_changed_submodule_paths(struct repository *r,
                struct string_list *changed_submodule_names)
 {
-       struct argv_array argv = ARGV_ARRAY_INIT;
+       struct strvec argv = STRVEC_INIT;
        struct string_list_item *name;
 
        /* No need to check if there are no submodules configured */
        if (!submodule_from_path(r, NULL, NULL))
                return;
 
-       argv_array_push(&argv, "--"); /* argv[0] program name */
+       strvec_push(&argv, "--"); /* argv[0] program name */
        oid_array_for_each_unique(&ref_tips_after_fetch,
                                   append_oid_to_argv, &argv);
-       argv_array_push(&argv, "--not");
+       strvec_push(&argv, "--not");
        oid_array_for_each_unique(&ref_tips_before_fetch,
                                   append_oid_to_argv, &argv);
 
@@ -1231,7 +1231,7 @@ static void calculate_changed_submodule_paths(struct repository *r,
 
        string_list_remove_empty_items(changed_submodule_names, 1);
 
-       argv_array_clear(&argv);
+       strvec_clear(&argv);
        oid_array_clear(&ref_tips_before_fetch);
        oid_array_clear(&ref_tips_after_fetch);
        initialized_fetch_ref_tips = 0;
@@ -1242,24 +1242,24 @@ int submodule_touches_in_range(struct repository *r,
                               struct object_id *incl_oid)
 {
        struct string_list subs = STRING_LIST_INIT_DUP;
-       struct argv_array args = ARGV_ARRAY_INIT;
+       struct strvec args = STRVEC_INIT;
        int ret;
 
        /* No need to check if there are no submodules configured */
        if (!submodule_from_path(r, NULL, NULL))
                return 0;
 
-       argv_array_push(&args, "--"); /* args[0] program name */
-       argv_array_push(&args, oid_to_hex(incl_oid));
+       strvec_push(&args, "--"); /* args[0] program name */
+       strvec_push(&args, oid_to_hex(incl_oid));
        if (!is_null_oid(excl_oid)) {
-               argv_array_push(&args, "--not");
-               argv_array_push(&args, oid_to_hex(excl_oid));
+               strvec_push(&args, "--not");
+               strvec_push(&args, oid_to_hex(excl_oid));
        }
 
        collect_changed_submodules(r, &subs, &args);
        ret = subs.nr;
 
-       argv_array_clear(&args);
+       strvec_clear(&args);
 
        free_submodules_oids(&subs);
        return ret;
@@ -1267,7 +1267,7 @@ int submodule_touches_in_range(struct repository *r,
 
 struct submodule_parallel_fetch {
        int count;
-       struct argv_array args;
+       struct strvec args;
        struct repository *r;
        const char *prefix;
        int command_line_option;
@@ -1283,7 +1283,7 @@ struct submodule_parallel_fetch {
 
        struct strbuf submodules_with_errors;
 };
-#define SPF_INIT {0, ARGV_ARRAY_INIT, NULL, NULL, 0, 0, 0, 0, \
+#define SPF_INIT {0, STRVEC_INIT, NULL, NULL, 0, 0, 0, 0, \
                  STRING_LIST_INIT_DUP, \
                  NULL, 0, 0, STRBUF_INIT}
 
@@ -1299,7 +1299,7 @@ static int get_fetch_recurse_config(const struct submodule *submodule,
 
                int fetch_recurse = submodule->fetch_recurse;
                key = xstrfmt("submodule.%s.fetchRecurseSubmodules", submodule->name);
-               if (!repo_config_get_string_const(spf->r, key, &value)) {
+               if (!repo_config_get_string_tmp(spf->r, key, &value)) {
                        fetch_recurse = parse_fetch_recurse_submodules_arg(key, value);
                }
                free(key);
@@ -1452,15 +1452,15 @@ static int get_next_submodule(struct child_process *cp,
                        if (!spf->quiet)
                                strbuf_addf(err, _("Fetching submodule %s%s\n"),
                                            spf->prefix, ce->name);
-                       argv_array_init(&cp->args);
-                       argv_array_pushv(&cp->args, spf->args.argv);
-                       argv_array_push(&cp->args, default_argv);
-                       argv_array_push(&cp->args, "--submodule-prefix");
+                       strvec_init(&cp->args);
+                       strvec_pushv(&cp->args, spf->args.v);
+                       strvec_push(&cp->args, default_argv);
+                       strvec_push(&cp->args, "--submodule-prefix");
 
                        strbuf_addf(&submodule_prefix, "%s%s/",
                                                       spf->prefix,
                                                       task->sub->path);
-                       argv_array_push(&cp->args, submodule_prefix.buf);
+                       strvec_push(&cp->args, submodule_prefix.buf);
 
                        spf->count++;
                        *task_cb = task;
@@ -1500,14 +1500,14 @@ static int get_next_submodule(struct child_process *cp,
                cp->git_cmd = 1;
                cp->dir = task->repo->gitdir;
 
-               argv_array_init(&cp->args);
-               argv_array_pushv(&cp->args, spf->args.argv);
-               argv_array_push(&cp->args, "on-demand");
-               argv_array_push(&cp->args, "--submodule-prefix");
-               argv_array_push(&cp->args, submodule_prefix.buf);
+               strvec_init(&cp->args);
+               strvec_pushv(&cp->args, spf->args.v);
+               strvec_push(&cp->args, "on-demand");
+               strvec_push(&cp->args, "--submodule-prefix");
+               strvec_push(&cp->args, submodule_prefix.buf);
 
                /* NEEDSWORK: have get_default_remote from submodule--helper */
-               argv_array_push(&cp->args, "origin");
+               strvec_push(&cp->args, "origin");
                oid_array_for_each_unique(task->commits,
                                          append_oid_to_argv, &cp->args);
 
@@ -1598,7 +1598,7 @@ out:
 }
 
 int fetch_populated_submodules(struct repository *r,
-                              const struct argv_array *options,
+                              const struct strvec *options,
                               const char *prefix, int command_line_option,
                               int default_option,
                               int quiet, int max_parallel_jobs)
@@ -1618,10 +1618,10 @@ int fetch_populated_submodules(struct repository *r,
        if (repo_read_index(r) < 0)
                die(_("index file corrupt"));
 
-       argv_array_push(&spf.args, "fetch");
-       for (i = 0; i < options->argc; i++)
-               argv_array_push(&spf.args, options->argv[i]);
-       argv_array_push(&spf.args, "--recurse-submodules-default");
+       strvec_push(&spf.args, "fetch");
+       for (i = 0; i < options->nr; i++)
+               strvec_push(&spf.args, options->v[i]);
+       strvec_push(&spf.args, "--recurse-submodules-default");
        /* default value, "--submodule-prefix" and its value are added later */
 
        calculate_changed_submodule_paths(r, &spf.changed_submodule_names);
@@ -1638,7 +1638,7 @@ int fetch_populated_submodules(struct repository *r,
                        spf.submodules_with_errors.buf);
 
 
-       argv_array_clear(&spf.args);
+       strvec_clear(&spf.args);
 out:
        free_submodules_oids(&spf.changed_submodule_names);
        return spf.result;
@@ -1666,9 +1666,9 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked)
        }
        strbuf_reset(&buf);
 
-       argv_array_pushl(&cp.args, "status", "--porcelain=2", NULL);
+       strvec_pushl(&cp.args, "status", "--porcelain=2", NULL);
        if (ignore_untracked)
-               argv_array_push(&cp.args, "-uno");
+               strvec_push(&cp.args, "-uno");
 
        prepare_submodule_repo_env(&cp.env_array);
        cp.git_cmd = 1;
@@ -1779,16 +1779,16 @@ int bad_to_remove_submodule(const char *path, unsigned flags)
        if (!submodule_uses_gitfile(path))
                return 1;
 
-       argv_array_pushl(&cp.args, "status", "--porcelain",
-                                  "--ignore-submodules=none", NULL);
+       strvec_pushl(&cp.args, "status", "--porcelain",
+                    "--ignore-submodules=none", NULL);
 
        if (flags & SUBMODULE_REMOVAL_IGNORE_UNTRACKED)
-               argv_array_push(&cp.args, "-uno");
+               strvec_push(&cp.args, "-uno");
        else
-               argv_array_push(&cp.args, "-uall");
+               strvec_push(&cp.args, "-uall");
 
        if (!(flags & SUBMODULE_REMOVAL_IGNORE_IGNORED_UNTRACKED))
-               argv_array_push(&cp.args, "--ignored");
+               strvec_push(&cp.args, "--ignored");
 
        prepare_submodule_repo_env(&cp.env_array);
        cp.git_cmd = 1;
@@ -1846,8 +1846,8 @@ static int submodule_has_dirty_index(const struct submodule *sub)
        prepare_submodule_repo_env(&cp.env_array);
 
        cp.git_cmd = 1;
-       argv_array_pushl(&cp.args, "diff-index", "--quiet",
-                                  "--cached", "HEAD", NULL);
+       strvec_pushl(&cp.args, "diff-index", "--quiet",
+                    "--cached", "HEAD", NULL);
        cp.no_stdin = 1;
        cp.no_stdout = 1;
        cp.dir = sub->path;
@@ -1866,11 +1866,11 @@ static void submodule_reset_index(const char *path)
        cp.no_stdin = 1;
        cp.dir = path;
 
-       argv_array_pushf(&cp.args, "--super-prefix=%s%s/",
-                                  get_super_prefix_or_empty(), path);
-       argv_array_pushl(&cp.args, "read-tree", "-u", "--reset", NULL);
+       strvec_pushf(&cp.args, "--super-prefix=%s%s/",
+                    get_super_prefix_or_empty(), path);
+       strvec_pushl(&cp.args, "read-tree", "-u", "--reset", NULL);
 
-       argv_array_push(&cp.args, empty_tree_oid_hex());
+       strvec_push(&cp.args, empty_tree_oid_hex());
 
        if (run_command(&cp))
                die(_("could not reset submodule index"));
@@ -1947,24 +1947,24 @@ int submodule_move_head(const char *path,
        cp.no_stdin = 1;
        cp.dir = path;
 
-       argv_array_pushf(&cp.args, "--super-prefix=%s%s/",
-                       get_super_prefix_or_empty(), path);
-       argv_array_pushl(&cp.args, "read-tree", "--recurse-submodules", NULL);
+       strvec_pushf(&cp.args, "--super-prefix=%s%s/",
+                    get_super_prefix_or_empty(), path);
+       strvec_pushl(&cp.args, "read-tree", "--recurse-submodules", NULL);
 
        if (flags & SUBMODULE_MOVE_HEAD_DRY_RUN)
-               argv_array_push(&cp.args, "-n");
+               strvec_push(&cp.args, "-n");
        else
-               argv_array_push(&cp.args, "-u");
+               strvec_push(&cp.args, "-u");
 
        if (flags & SUBMODULE_MOVE_HEAD_FORCE)
-               argv_array_push(&cp.args, "--reset");
+               strvec_push(&cp.args, "--reset");
        else
-               argv_array_push(&cp.args, "-m");
+               strvec_push(&cp.args, "-m");
 
        if (!(flags & SUBMODULE_MOVE_HEAD_FORCE))
-               argv_array_push(&cp.args, old_head ? old_head : empty_tree_oid_hex());
+               strvec_push(&cp.args, old_head ? old_head : empty_tree_oid_hex());
 
-       argv_array_push(&cp.args, new_head ? new_head : empty_tree_oid_hex());
+       strvec_push(&cp.args, new_head ? new_head : empty_tree_oid_hex());
 
        if (run_command(&cp)) {
                ret = error(_("Submodule '%s' could not be updated."), path);
@@ -1980,8 +1980,8 @@ int submodule_move_head(const char *path,
                        cp.dir = path;
 
                        prepare_submodule_repo_env(&cp.env_array);
-                       argv_array_pushl(&cp.args, "update-ref", "HEAD",
-                                        "--no-deref", new_head, NULL);
+                       strvec_pushl(&cp.args, "update-ref", "HEAD",
+                                    "--no-deref", new_head, NULL);
 
                        if (run_command(&cp)) {
                                ret = -1;
@@ -2157,9 +2157,9 @@ void absorb_git_dir_into_superproject(const char *path,
                cp.dir = path;
                cp.git_cmd = 1;
                cp.no_stdin = 1;
-               argv_array_pushl(&cp.args, "--super-prefix", sb.buf,
-                                          "submodule--helper",
-                                          "absorb-git-dirs", NULL);
+               strvec_pushl(&cp.args, "--super-prefix", sb.buf,
+                            "submodule--helper",
+                            "absorb-git-dirs", NULL);
                prepare_submodule_repo_env(&cp.env_array);
                if (run_command(&cp))
                        die(_("could not recurse into submodule '%s'"), path);
@@ -2194,11 +2194,11 @@ int get_superproject_working_tree(struct strbuf *buf)
        strbuf_release(&one_up);
 
        prepare_submodule_repo_env(&cp.env_array);
-       argv_array_pop(&cp.env_array);
+       strvec_pop(&cp.env_array);
 
-       argv_array_pushl(&cp.args, "--literal-pathspecs", "-C", "..",
-                       "ls-files", "-z", "--stage", "--full-name", "--",
-                       subpath, NULL);
+       strvec_pushl(&cp.args, "--literal-pathspecs", "-C", "..",
+                    "ls-files", "-z", "--stage", "--full-name", "--",
+                    subpath, NULL);
        strbuf_reset(&sb);
 
        cp.no_stdin = 1;
index 4dad649f94220e3897e629a5737da5f08705a5fb..9ce85c03fed9950d366edb4bf550db22ffced06b 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef SUBMODULE_H
 #define SUBMODULE_H
 
-struct argv_array;
+struct strvec;
 struct cache_entry;
 struct diff_options;
 struct index_state;
@@ -84,7 +84,7 @@ int should_update_submodules(void);
 const struct submodule *submodule_from_ce(const struct cache_entry *ce);
 void check_for_new_submodule_commits(struct object_id *oid);
 int fetch_populated_submodules(struct repository *r,
-                              const struct argv_array *options,
+                              const struct strvec *options,
                               const char *prefix,
                               int command_line_option,
                               int default_option,
@@ -143,7 +143,7 @@ void submodule_unset_core_worktree(const struct submodule *sub);
  * a submodule by clearing any repo-specific environment variables, but
  * retaining any config in the environment.
  */
-void prepare_submodule_repo_env(struct argv_array *out);
+void prepare_submodule_repo_env(struct strvec *out);
 
 #define ABSORB_GITDIR_RECURSE_SUBMODULES (1<<0)
 void absorb_git_dir_into_superproject(const char *path,
index 70ec61cf887fcacb3e7f9ffe09cee636caa37732..2adaf7c2d2747a1426b11a8d75e0cac667232b60 100644 (file)
--- a/t/README
+++ b/t/README
@@ -421,6 +421,10 @@ GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=<boolean>, when true (which is
 the default when running tests), errors out when an abbreviated option
 is used.
 
+GIT_TEST_DEFAULT_HASH=<hash-algo> specifies which hash algorithm to
+use in the test scripts. Recognized values for <hash-algo> are "sha1"
+and "sha256".
+
 Naming Tests
 ------------
 
index f0aa80b98eb3240c59db99e2b5fbc186fd87c717..5e77d56f599cb9641d853cd4f6e3fd8b3bee0001 100644 (file)
@@ -50,6 +50,8 @@ static const char *bloom_usage = "\n"
 
 int cmd__bloom(int argc, const char **argv)
 {
+       setup_git_directory();
+
        if (argc < 2)
                usage(bloom_usage);
 
index 234c722b485e1ecdf9f00ba56d119c8364a6f949..a6e936721fe660bb110e3d691d61dad80fddc307 100644 (file)
@@ -126,7 +126,7 @@ int cmd__config(int argc, const char **argv)
                        goto exit1;
                }
        } else if (argc == 3 && !strcmp(argv[1], "get_string")) {
-               if (!git_config_get_string_const(argv[2], &v)) {
+               if (!git_config_get_string_tmp(argv[2], &v)) {
                        printf("%s\n", v);
                        goto exit0;
                } else {
index 831b586d022215ff75b4e426d79e7149b3bfb3bb..2430880f78f8ec674666d2fd04f7fded4e00ef89 100644 (file)
@@ -7,14 +7,18 @@
 static int read_midx_file(const char *object_dir)
 {
        uint32_t i;
-       struct multi_pack_index *m = load_multi_pack_index(object_dir, 1);
+       struct multi_pack_index *m;
+
+       setup_git_directory();
+       m = load_multi_pack_index(object_dir, 1);
 
        if (!m)
                return 1;
 
-       printf("header: %08x %d %d %d\n",
+       printf("header: %08x %d %d %d %d\n",
               m->signature,
               m->version,
+              m->hash_len,
               m->num_chunks,
               m->num_packs);
 
index 1646aa25d82f9e705d8d4b097e95fec768337e70..7ae03dc7123468463d02a28dce2b1c6175576b6f 100644 (file)
@@ -12,7 +12,7 @@
 #include "git-compat-util.h"
 #include "cache.h"
 #include "run-command.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "strbuf.h"
 #include "parse-options.h"
 #include "string-list.h"
@@ -31,7 +31,7 @@ static int parallel_next(struct child_process *cp,
        if (number_callbacks >= 4)
                return 0;
 
-       argv_array_pushv(&cp->args, d->argv);
+       strvec_pushv(&cp->args, d->argv);
        strbuf_addstr(err, "preloaded output of a child\n");
        number_callbacks++;
        return 1;
@@ -72,19 +72,19 @@ static int next_test(struct child_process *cp, struct strbuf *err, void *cb,
                return 0;
 
        test = suite->tests.items[suite->next++].string;
-       argv_array_pushl(&cp->args, "sh", test, NULL);
+       strvec_pushl(&cp->args, "sh", test, NULL);
        if (suite->quiet)
-               argv_array_push(&cp->args, "--quiet");
+               strvec_push(&cp->args, "--quiet");
        if (suite->immediate)
-               argv_array_push(&cp->args, "-i");
+               strvec_push(&cp->args, "-i");
        if (suite->verbose)
-               argv_array_push(&cp->args, "-v");
+               strvec_push(&cp->args, "-v");
        if (suite->verbose_log)
-               argv_array_push(&cp->args, "-V");
+               strvec_push(&cp->args, "-V");
        if (suite->trace)
-               argv_array_push(&cp->args, "-x");
+               strvec_push(&cp->args, "-x");
        if (suite->write_junit_xml)
-               argv_array_push(&cp->args, "--write-junit-xml");
+               strvec_push(&cp->args, "--write-junit-xml");
 
        strbuf_addf(err, "Output of '%s':\n", test);
        *task_cb = (void *)test;
@@ -220,7 +220,7 @@ static int quote_stress_test(int argc, const char **argv)
        char special[] = ".?*\\^_\"'`{}()[]<>@~&+:;$%"; // \t\r\n\a";
        int i, j, k, trials = 100, skip = 0, msys2 = 0;
        struct strbuf out = STRBUF_INIT;
-       struct argv_array args = ARGV_ARRAY_INIT;
+       struct strvec args = STRVEC_INIT;
        struct option options[] = {
                OPT_INTEGER('n', "trials", &trials, "Number of trials"),
                OPT_INTEGER('s', "skip", &skip, "Skip <n> trials"),
@@ -241,20 +241,20 @@ static int quote_stress_test(int argc, const char **argv)
                size_t arg_count, arg_offset;
                int ret = 0;
 
-               argv_array_clear(&args);
+               strvec_clear(&args);
                if (msys2)
-                       argv_array_pushl(&args, "sh", "-c",
-                                        "printf %s\\\\0 \"$@\"", "skip", NULL);
+                       strvec_pushl(&args, "sh", "-c",
+                                    "printf %s\\\\0 \"$@\"", "skip", NULL);
                else
-                       argv_array_pushl(&args, "test-tool", "run-command",
-                                        "quote-echo", NULL);
-               arg_offset = args.argc;
+                       strvec_pushl(&args, "test-tool", "run-command",
+                                    "quote-echo", NULL);
+               arg_offset = args.nr;
 
                if (argc > 0) {
                        trials = 1;
                        arg_count = argc;
                        for (j = 0; j < arg_count; j++)
-                               argv_array_push(&args, argv[j]);
+                               strvec_push(&args, argv[j]);
                } else {
                        arg_count = 1 + (my_random() % 5);
                        for (j = 0; j < arg_count; j++) {
@@ -268,20 +268,20 @@ static int quote_stress_test(int argc, const char **argv)
                                                ARRAY_SIZE(special)];
                                buf[arg_len] = '\0';
 
-                               argv_array_push(&args, buf);
+                               strvec_push(&args, buf);
                        }
                }
 
                if (i < skip)
                        continue;
 
-               cp.argv = args.argv;
+               cp.argv = args.v;
                strbuf_reset(&out);
                if (pipe_command(&cp, NULL, 0, &out, 0, NULL, 0) < 0)
                        return error("Failed to spawn child process");
 
                for (j = 0, k = 0; j < arg_count; j++) {
-                       const char *arg = args.argv[j + arg_offset];
+                       const char *arg = args.v[j + arg_offset];
 
                        if (strcmp(arg, out.buf + k))
                                ret = error("incorrectly quoted arg: '%s', "
@@ -298,10 +298,10 @@ static int quote_stress_test(int argc, const char **argv)
                        fprintf(stderr, "Trial #%d failed. Arguments:\n", i);
                        for (j = 0; j < arg_count; j++)
                                fprintf(stderr, "arg #%d: '%s'\n",
-                                       (int)j, args.argv[j + arg_offset]);
+                                       (int)j, args.v[j + arg_offset]);
 
                        strbuf_release(&out);
-                       argv_array_clear(&args);
+                       strvec_clear(&args);
 
                        return ret;
                }
@@ -311,7 +311,7 @@ static int quote_stress_test(int argc, const char **argv)
        }
 
        strbuf_release(&out);
-       argv_array_clear(&args);
+       strvec_clear(&args);
 
        return 0;
 }
@@ -338,8 +338,8 @@ static int inherit_handle(const char *argv0)
        xsnprintf(path, sizeof(path), "out-XXXXXX");
        tmp = xmkstemp(path);
 
-       argv_array_pushl(&cp.args,
-                        "test-tool", argv0, "inherited-handle-child", NULL);
+       strvec_pushl(&cp.args,
+                    "test-tool", argv0, "inherited-handle-child", NULL);
        cp.in = -1;
        cp.no_stdout = cp.no_stderr = 1;
        if (start_command(&cp) < 0)
@@ -391,7 +391,7 @@ int cmd__run_command(int argc, const char **argv)
        while (!strcmp(argv[1], "env")) {
                if (!argv[2])
                        die("env specifier without a value");
-               argv_array_push(&proc.env_array, argv[2]);
+               strvec_push(&proc.env_array, argv[2]);
                argv += 2;
                argc -= 2;
        }
index 197819c872eec78c7c12ad56f8b8d9ff36f161d7..823f33ceff4aadac07128786f01c8a38a223cdcf 100644 (file)
@@ -1,6 +1,6 @@
 #include "test-tool.h"
 #include "cache.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "run-command.h"
 #include "exec-cmd.h"
 #include "config.h"
index f3463170b39fee8befa08ee3f3e460426f731498..bb8938ccbeebbb14c19c372638365275e0724443 100644 (file)
@@ -35,8 +35,6 @@ pack_header () {
 # have hardcoded some well-known objects. See the case statements below for the
 # complete list.
 pack_obj () {
-       test_oid_init
-
        case "$1" in
        # empty blob
        $EMPTY_BLOB)
@@ -93,6 +91,14 @@ pack_obj () {
                        ;;
                esac
                ;;
+       # blob containing "\3\326"
+       471819e8c52bf11513f100b2810a8aa0622d5cd3d1c913758a071dd4b3bad8fe)
+               case "$2" in
+               '')
+                       printf '\062\170\234\143\276\006\000\000\336\000\332'
+                       return
+                       ;;
+               esac
        esac
 
        # If it's not a delta, we can convince pack-objects to generate a pack
@@ -113,7 +119,6 @@ pack_obj () {
 
 # Compute and append pack trailer to "$1"
 pack_trailer () {
-       test_oid_init &&
        test-tool $(test_oid algo) -b <"$1" >trailer.tmp &&
        cat trailer.tmp >>"$1" &&
        rm -f trailer.tmp
index 07c822c8ff5f31eb8f0a81adffcec75ec752f737..87a759149faf37c748568c31b0a9017ae5ec6940 100644 (file)
@@ -196,7 +196,6 @@ test_git_directory_exists () {
 # the submodule repo if it doesn't exist and configures the most problematic
 # settings for diff.ignoreSubmodules.
 prolog () {
-       test_oid_init &&
        (test -d submodule_update_repo || create_lib_submodule_repo) &&
        test_config_global diff.ignoreSubmodules all &&
        test_config diff.ignoreSubmodules all
index b0ed4767e320e200c592e979dce0fa1e4cfd6ede..fba6778ca35a2022513c8b36434fc24825e875c2 100644 (file)
@@ -1,7 +1,5 @@
 : included from 6002 and others
 
-mkdir -p .git/refs/tags
-
 >sed.script
 
 # Answer the sha1 has associated with the tag. The tag must exist under refs/tags
@@ -26,7 +24,8 @@ save_tag () {
        _tag=$1
        test -n "$_tag" || error "usage: save_tag tag commit-args ..."
        shift 1
-       "$@" >".git/refs/tags/$_tag"
+
+       git update-ref "refs/tags/$_tag" $("$@")
 
        echo "s/$(tag $_tag)/$_tag/g" >sed.script.tmp
        cat sed.script >>sed.script.tmp
index c7b70e2d28ba3f8b24a3c4dfe4bb436b1f4acfa5..bd649afa978393373c209b507f3713c8f716986c 100644 (file)
@@ -84,6 +84,15 @@ You can set the following variables (also in your config.mak):
        probably be about linux.git size for optimal results.
        Both default to the git.git you are running from.
 
+    GIT_PERF_EXTRA
+       Boolean to enable additional tests. Most test scripts are
+       written to detect regressions between two versions of Git, and
+       the output will compare timings for individual tests between
+       those versions. Some scripts have additional tests which are not
+       run by default, that show patterns within a single version of
+       Git (e.g., performance of index-pack as the number of threads
+       changes). These can be enabled with GIT_PERF_EXTRA.
+
 You can also pass the options taken by ordinary git tests; the most
 useful one is:
 
index a9b3e112d98223134d791727ffcde01e9123b117..228593d9ad6b3a5c9a0b45eb5814a3a8746d42bc 100755 (executable)
@@ -13,35 +13,36 @@ test_expect_success 'repack' '
        export PACK
 '
 
-test_perf 'index-pack 0 threads' '
-       rm -rf repo.git &&
-       git init --bare repo.git &&
-       GIT_DIR=repo.git git index-pack --threads=1 --stdin < $PACK
-'
-
-test_perf 'index-pack 1 thread ' '
-       rm -rf repo.git &&
-       git init --bare repo.git &&
-       GIT_DIR=repo.git GIT_FORCE_THREADS=1 git index-pack --threads=1 --stdin < $PACK
+# Rather than counting up and doubling each time, count down from the endpoint,
+# halving each time. That ensures that our final test uses as many threads as
+# CPUs, even if it isn't a power of 2.
+test_expect_success 'set up thread-counting tests' '
+       t=$(test-tool online-cpus) &&
+       threads= &&
+       while test $t -gt 0
+       do
+               threads="$t $threads"
+               t=$((t / 2))
+       done
 '
 
-test_perf 'index-pack 2 threads' '
+test_perf PERF_EXTRA 'index-pack 0 threads' '
        rm -rf repo.git &&
        git init --bare repo.git &&
-       GIT_DIR=repo.git git index-pack --threads=2 --stdin < $PACK
-'
-
-test_perf 'index-pack 4 threads' '
-       rm -rf repo.git &&
-       git init --bare repo.git &&
-       GIT_DIR=repo.git git index-pack --threads=4 --stdin < $PACK
+       GIT_DIR=repo.git git index-pack --threads=1 --stdin < $PACK
 '
 
-test_perf 'index-pack 8 threads' '
-       rm -rf repo.git &&
-       git init --bare repo.git &&
-       GIT_DIR=repo.git git index-pack --threads=8 --stdin < $PACK
-'
+for t in $threads
+do
+       THREADS=$t
+       export THREADS
+       test_perf PERF_EXTRA "index-pack $t threads" '
+               rm -rf repo.git &&
+               git init --bare repo.git &&
+               GIT_DIR=repo.git GIT_FORCE_THREADS=1 \
+               git index-pack --threads=$THREADS --stdin <$PACK
+       '
+done
 
 test_perf 'index-pack default number of threads' '
        rm -rf repo.git &&
index 13e389367a4e091c59d52b1e2567f3ca6cb121fb..821581a88548a38ec9c0542f50ef54bbc8815b4b 100644 (file)
@@ -245,3 +245,5 @@ test_at_end_hook_ () {
 test_export () {
        export "$@"
 }
+
+test_lazy_prereq PERF_EXTRA 'test_bool_env GIT_PERF_EXTRA false'
index 2ff176cd5d954cb1c83f062adbdb28a7e14d2668..923281af93981d5b6f67ace54f41849b44ecf0b1 100755 (executable)
@@ -891,10 +891,6 @@ test_expect_success 'test_atexit is run' "
        test_path_is_missing also-clean-atexit
 "
 
-test_expect_success 'test_oid setup' '
-       test_oid_init
-'
-
 test_expect_success 'test_oid provides sane info by default' '
        test_oid zero >actual &&
        grep "^00*\$" actual &&
@@ -928,6 +924,17 @@ test_expect_success 'test_oid can look up data for SHA-256' '
        test "$hexsz" -eq 64
 '
 
+test_expect_success 'test_oid can look up data for a specified algorithm' '
+       rawsz="$(test_oid --hash=sha1 rawsz)" &&
+       hexsz="$(test_oid --hash=sha1 hexsz)" &&
+       test "$rawsz" -eq 20 &&
+       test "$hexsz" -eq 40 &&
+       rawsz="$(test_oid --hash=sha256 rawsz)" &&
+       hexsz="$(test_oid --hash=sha256 hexsz)" &&
+       test "$rawsz" -eq 32 &&
+       test "$hexsz" -eq 64
+'
+
 test_expect_success 'test_bool_env' '
        (
                sane_unset envvar &&
@@ -1271,4 +1278,22 @@ test_expect_success 'very long name in the index handled sanely' '
        test $len = 4098
 '
 
+test_expect_success 'test_must_fail on a failing git command' '
+       test_must_fail git notacommand
+'
+
+test_expect_success 'test_must_fail on a failing git command with env' '
+       test_must_fail env var1=a var2=b git notacommand
+'
+
+test_expect_success 'test_must_fail rejects a non-git command' '
+       ! test_must_fail grep ^$ notafile 2>err &&
+       grep -F "test_must_fail: only '"'"'git'"'"' is allowed" err
+'
+
+test_expect_success 'test_must_fail rejects a non-git command with env' '
+       ! test_must_fail env var1=a var2=b grep ^$ notafile 2>err &&
+       grep -F "test_must_fail: only '"'"'git'"'"' is allowed" err
+'
+
 test_done
index 6d2467995e7afea65697d7540f2ef05cde54ae4b..50222a10c5b1c68d5509c7e4952bdde79bc1a86c 100755 (executable)
@@ -316,6 +316,19 @@ test_expect_success 'init with separate gitdir' '
        test_path_is_dir realgitdir/refs
 '
 
+test_expect_success 'explicit bare & --separate-git-dir incompatible' '
+       test_must_fail git init --bare --separate-git-dir goop.git bare.git 2>err &&
+       test_i18ngrep "mutually exclusive" err
+'
+
+test_expect_success 'implicit bare & --separate-git-dir incompatible' '
+       test_when_finished "rm -rf bare.git" &&
+       mkdir -p bare.git &&
+       test_must_fail env GIT_DIR=. \
+               git -C bare.git init --separate-git-dir goop.git 2>err &&
+       test_i18ngrep "incompatible" err
+'
+
 test_lazy_prereq GETCWD_IGNORES_PERMS '
        base=GETCWD_TEST_BASE_DIR &&
        mkdir -p $base/dir &&
@@ -441,6 +454,39 @@ test_expect_success 're-init from a linked worktree' '
        )
 '
 
+test_expect_success 'init honors GIT_DEFAULT_HASH' '
+       GIT_DEFAULT_HASH=sha1 git init sha1 &&
+       git -C sha1 rev-parse --show-object-format >actual &&
+       echo sha1 >expected &&
+       test_cmp expected actual &&
+       GIT_DEFAULT_HASH=sha256 git init sha256 &&
+       git -C sha256 rev-parse --show-object-format >actual &&
+       echo sha256 >expected &&
+       test_cmp expected actual
+'
+
+test_expect_success 'init honors --object-format' '
+       git init --object-format=sha1 explicit-sha1 &&
+       git -C explicit-sha1 rev-parse --show-object-format >actual &&
+       echo sha1 >expected &&
+       test_cmp expected actual &&
+       git init --object-format=sha256 explicit-sha256 &&
+       git -C explicit-sha256 rev-parse --show-object-format >actual &&
+       echo sha256 >expected &&
+       test_cmp expected actual
+'
+
+test_expect_success 'extensions.objectFormat is not allowed with repo version 0' '
+       git init --object-format=sha256 explicit-v0 &&
+       git -C explicit-v0 config core.repositoryformatversion 0 &&
+       test_must_fail git -C explicit-v0 rev-parse --show-object-format
+'
+
+test_expect_success 'init rejects attempts to initialize with different hash' '
+       test_must_fail git -C sha1 init --object-format=sha256 &&
+       test_must_fail git -C sha256 init --object-format=sha1
+'
+
 test_expect_success MINGW 'core.hidedotfiles = false' '
        git config --global core.hidedotfiles false &&
        rm -rf newdir &&
index f8178ee4e392fa5cfdbef07b0f42710ea68bc67b..14cafc138b7875013afeee01d74dbbeb2e56d495 100755 (executable)
@@ -44,7 +44,7 @@ Magic arguments
     --no-ambiguous        negative ambiguity
 
 Standard options
-    --abbrev[=<n>]        use <n> digits to display SHA-1s
+    --abbrev[=<n>]        use <n> digits to display object names
     -v, --verbose         be verbose
     -n, --dry-run         dry run
     -q, --quiet           be quiet
index 6aa0f313bddbc9df06d22d10c1cb59a8b92e8e89..a5ebdf9ff3cd79091de98c8aca7b27bfcda94c2c 100755 (executable)
@@ -42,7 +42,7 @@ test_expect_success 'convert shallow clone to partial clone' '
        test_cmp_config -C client 1 core.repositoryformatversion
 '
 
-test_expect_success 'convert to partial clone with noop extension' '
+test_expect_success SHA1 'convert to partial clone with noop extension' '
        rm -fr server client &&
        test_create_repo server &&
        test_commit -C server my_commit 1 &&
@@ -53,7 +53,7 @@ test_expect_success 'convert to partial clone with noop extension' '
        git -C client fetch --unshallow --filter="blob:none"
 '
 
-test_expect_success 'converting to partial clone fails with unrecognized extension' '
+test_expect_success SHA1 'converting to partial clone fails with unrecognized extension' '
        rm -fr server client &&
        test_create_repo server &&
        test_commit -C server my_commit 1 &&
index 43c4be1e5ef559d10ca276ef777a8fe7ba8a3971..2f501d2dc94a9e6380f6aaa1d79af0d84edc2850 100755 (executable)
@@ -140,8 +140,6 @@ test_expect_success '--batch-check without %(rest) considers whole line' '
        test_cmp expect actual
 '
 
-test_oid_init
-
 tree_sha1=$(git write-tree)
 tree_size=$(($(test_oid rawsz) + 13))
 tree_pretty_content="100644 blob $hello_sha1   hello"
index 6a56d1ca246f3437ab7f8dfd77d9eef9fe4b4144..61e89a8071c8a385d130c95cea5776314440e755 100755 (executable)
@@ -12,7 +12,6 @@ file_size () {
 }
 
 test_expect_success setup '
-       test_oid_init &&
        # clone does not allow us to pass core.bigfilethreshold to
        # new repos, so set core.bigfilethreshold globally
        git config --global core.bigfilethreshold 200k &&
index 7cd45fc13946b35af307c7735c7ecd8a1ae52563..84acfc48b6786a43d82f5185465c42f4417b9a02 100755 (executable)
@@ -369,7 +369,7 @@ test_expect_success 'sparse-checkout (init|set|disable) warns with unmerged stat
        git clone repo unmerged &&
 
        cat >input <<-EOF &&
-       0 0000000000000000000000000000000000000000      folder1/a
+       0 $ZERO_OID     folder1/a
        100644 $(git -C unmerged rev-parse HEAD:folder1/a) 1    folder1/a
        EOF
        git -C unmerged update-index --index-info <input &&
@@ -396,7 +396,7 @@ test_expect_success 'sparse-checkout reapply' '
        echo dirty >tweak/deep/deeper2/a &&
 
        cat >input <<-EOF &&
-       0 0000000000000000000000000000000000000000      folder1/a
+       0 $ZERO_OID     folder1/a
        100644 $(git -C tweak rev-parse HEAD:folder1/a) 1       folder1/a
        EOF
        git -C tweak update-index --index-info <input &&
index d60c042ce88b5306b8c32f6b3d928338f6720168..0acabb6d11b48aca54e73025965f4c4e6b561d34 100755 (executable)
@@ -87,6 +87,9 @@ allow 1
 allow 1 noop
 abort 1 no-such-extension
 allow 0 no-such-extension
+allow 0 noop
+abort 0 noop-v1
+allow 1 noop-v1
 EOF
 
 test_expect_success 'precious-objects allowed' '
index 27171f826129168aa1e52262e2b2a9b4ca327989..770e7be363cdaa0fbbfc52a03cbc195c0920aad1 100755 (executable)
@@ -160,10 +160,10 @@ test_expect_success 'core.logAllRefUpdates=always creates reflog by default' '
        git reflog exists $outside
 '
 
-test_expect_success 'core.logAllRefUpdates=always creates no reflog for ORIG_HEAD' '
+test_expect_success 'core.logAllRefUpdates=always creates reflog for ORIG_HEAD' '
        test_config core.logAllRefUpdates always &&
        git update-ref ORIG_HEAD $A &&
-       test_must_fail git reflog exists ORIG_HEAD
+       git reflog exists ORIG_HEAD
 '
 
 test_expect_success '--no-create-reflog overrides core.logAllRefUpdates=always' '
@@ -324,7 +324,7 @@ test_expect_success "create $m (logged by config)" '
 test_expect_success "update $m (logged by config)" '
        test_config core.logAllRefUpdates true &&
        GIT_COMMITTER_DATE="2005-05-26 23:33" \
-       git update-ref HEAD'" $B $A "'-m "Switch" &&
+       git update-ref HEAD $B $A -m "Switch" &&
        test $B = $(git show-ref -s --verify $m)
 '
 test_expect_success "set $m (logged by config)" '
@@ -475,57 +475,57 @@ test_expect_success 'git cat-file blob master@{2005-05-26 23:42}:F (expect OTHER
 
 test_expect_success 'given old value for missing pseudoref, do not create' '
        test_must_fail git update-ref PSEUDOREF $A $B 2>err &&
-       test_path_is_missing .git/PSEUDOREF &&
-       test_i18ngrep "could not read ref" err
+       test_must_fail git rev-parse PSEUDOREF &&
+       test_i18ngrep "unable to resolve reference" err
 '
 
 test_expect_success 'create pseudoref' '
        git update-ref PSEUDOREF $A &&
-       test $A = $(cat .git/PSEUDOREF)
+       test $A = $(git rev-parse PSEUDOREF)
 '
 
 test_expect_success 'overwrite pseudoref with no old value given' '
        git update-ref PSEUDOREF $B &&
-       test $B = $(cat .git/PSEUDOREF)
+       test $B = $(git rev-parse PSEUDOREF)
 '
 
 test_expect_success 'overwrite pseudoref with correct old value' '
        git update-ref PSEUDOREF $C $B &&
-       test $C = $(cat .git/PSEUDOREF)
+       test $C = $(git rev-parse PSEUDOREF)
 '
 
 test_expect_success 'do not overwrite pseudoref with wrong old value' '
        test_must_fail git update-ref PSEUDOREF $D $E 2>err &&
-       test $C = $(cat .git/PSEUDOREF) &&
-       test_i18ngrep "unexpected object ID" err
+       test $C = $(git rev-parse PSEUDOREF) &&
+       test_i18ngrep "cannot lock ref.*expected" err
 '
 
 test_expect_success 'delete pseudoref' '
        git update-ref -d PSEUDOREF &&
-       test_path_is_missing .git/PSEUDOREF
+       test_must_fail git rev-parse PSEUDOREF
 '
 
 test_expect_success 'do not delete pseudoref with wrong old value' '
        git update-ref PSEUDOREF $A &&
        test_must_fail git update-ref -d PSEUDOREF $B 2>err &&
-       test $A = $(cat .git/PSEUDOREF) &&
-       test_i18ngrep "unexpected object ID" err
+       test $A = $(git rev-parse PSEUDOREF) &&
+       test_i18ngrep "cannot lock ref.*expected" err
 '
 
 test_expect_success 'delete pseudoref with correct old value' '
        git update-ref -d PSEUDOREF $A &&
-       test_path_is_missing .git/PSEUDOREF
+       test_must_fail git rev-parse PSEUDOREF
 '
 
 test_expect_success 'create pseudoref with old OID zero' '
        git update-ref PSEUDOREF $A $Z &&
-       test $A = $(cat .git/PSEUDOREF)
+       test $A = $(git rev-parse PSEUDOREF)
 '
 
 test_expect_success 'do not overwrite pseudoref with old OID zero' '
        test_when_finished git update-ref -d PSEUDOREF &&
        test_must_fail git update-ref PSEUDOREF $B $Z 2>err &&
-       test $A = $(cat .git/PSEUDOREF) &&
+       test $A = $(git rev-parse PSEUDOREF) &&
        test_i18ngrep "already exists" err
 '
 
index 331899ddc4bd33805c83ebad8983233da7d67ec8..74af927fbaa7300ed3a20fb51fe32f8b5fcd1835 100755 (executable)
@@ -31,7 +31,10 @@ test_expect_success 'create_symref(FOO, refs/heads/master)' '
 test_expect_success 'delete_refs(FOO, refs/tags/new-tag)' '
        git rev-parse FOO -- &&
        git rev-parse refs/tags/new-tag -- &&
-       $RUN delete-refs 0 nothing FOO refs/tags/new-tag &&
+       m=$(git rev-parse master) &&
+       REF_NO_DEREF=1 &&
+       $RUN delete-refs $REF_NO_DEREF nothing FOO refs/tags/new-tag &&
+       test_must_fail git rev-parse --symbolic-full-name FOO &&
        test_must_fail git rev-parse FOO -- &&
        test_must_fail git rev-parse refs/tags/new-tag --
 '
index 76d9b744a64b1b67e4093c262b7d6de302e29ff6..730a43d9ddc2c051a954af10121763c32fbb299b 100755 (executable)
@@ -54,7 +54,6 @@ check_dont_have () {
 }
 
 test_expect_success setup '
-       test_oid_init &&
        mkdir -p A/B &&
        echo rat >C &&
        echo ox >A/D &&
index da58d867a56f57360c7090bced0911350bc5fef0..f6e741c6c055a4e62fdbb16f50eedc7dcd4b383d 100755 (executable)
@@ -7,6 +7,7 @@ test_description='reference transaction hooks'
 test_expect_success setup '
        mkdir -p .git/hooks &&
        test_commit PRE &&
+       PRE_OID=$(git rev-parse PRE) &&
        test_commit POST &&
        POST_OID=$(git rev-parse POST)
 '
@@ -106,4 +107,30 @@ test_expect_success 'hook gets all queued updates in aborted state' '
        test_cmp expect actual
 '
 
+test_expect_success 'interleaving hook calls succeed' '
+       test_when_finished "rm -r target-repo.git" &&
+
+       git init --bare target-repo.git &&
+
+       write_script target-repo.git/hooks/reference-transaction <<-\EOF &&
+               echo $0 "$@" >>actual
+       EOF
+
+       write_script target-repo.git/hooks/update <<-\EOF &&
+               echo $0 "$@" >>actual
+       EOF
+
+       cat >expect <<-EOF &&
+               hooks/update refs/tags/PRE $ZERO_OID $PRE_OID
+               hooks/reference-transaction prepared
+               hooks/reference-transaction committed
+               hooks/update refs/tags/POST $ZERO_OID $POST_OID
+               hooks/reference-transaction prepared
+               hooks/reference-transaction committed
+       EOF
+
+       git push ./target-repo.git PRE POST &&
+       test_cmp expect target-repo.git/actual
+'
+
 test_done
index 344a2aad82f96d04aec38aa1a221d2649e97d491..b17f5c21fbce789c9a9bdd42f2f337b24675e099 100755 (executable)
@@ -9,7 +9,6 @@ test_description='git fsck random collection of tests
 . ./test-lib.sh
 
 test_expect_success setup '
-       test_oid_init &&
        git config gc.auto 0 &&
        git config i18n.commitencoding ISO-8859-1 &&
        test_commit A fileA one &&
@@ -714,7 +713,7 @@ test_expect_success 'fsck fails on corrupt packfile' '
        # at least one of which is not zero, so setting the first byte to 0 is
        # sufficient.)
        chmod a+w .git/objects/pack/pack-$pack.pack &&
-       printf '\0' | dd of=.git/objects/pack/pack-$pack.pack bs=1 conv=notrunc seek=12 &&
+       printf "\0" | dd of=.git/objects/pack/pack-$pack.pack bs=1 conv=notrunc seek=12 &&
 
        test_when_finished "rm -f .git/objects/pack/pack-$pack.*" &&
        remove_object $hsh &&
index 603019b54167eb1b2050349dcca45af74a56031b..408b97d5af9551f91a86e70c6c37b912719bfd15 100755 (executable)
@@ -59,7 +59,6 @@ test_rev_parse () {
 ROOT=$(pwd)
 
 test_expect_success 'setup' '
-       test_oid_init &&
        mkdir -p sub/dir work &&
        cp -R .git repo.git
 '
index f213aa8053807882e7312a5b9cb8efd252dfae35..dfc0d96d8a8a834743781a08a8ea1c5f9dd63bda 100755 (executable)
@@ -137,7 +137,7 @@ test_expect_success 'merge my-side@{u} records the correct name' '
        git branch -t new my-side@{u} &&
        git merge -s ours new@{u} &&
        git show -s --pretty=tformat:%s >actual &&
-       echo "Merge remote-tracking branch ${SQ}origin/side${SQ} into master" >expect &&
+       echo "Merge remote-tracking branch ${SQ}origin/side${SQ}" >expect &&
        test_cmp expect actual
 )
 '
index 76330cb5ab79ab0ddfd97e0c06a8f4fb3a74d6c6..fa9e0987063bd409592f45b5f71f67478a2f9f25 100755 (executable)
@@ -44,4 +44,16 @@ test_expect_success '--no-overlay --theirs with D/F conflict deletes file' '
        test_path_is_missing file1
 '
 
+test_expect_success 'wildcard pathspec matches file in subdirectory' '
+       git reset --hard &&
+       mkdir subdir &&
+       test_commit file3-1 subdir/file3 &&
+       test_commit file3-2 subdir/file3 &&
+
+       git checkout --no-overlay file3-1 "*file3" &&
+       echo file3-1 >expect &&
+       test_path_is_file subdir/file3 &&
+       test_cmp expect subdir/file3
+'
+
 test_done
index 0d47946e8a9b06f044542e373f3de477e53e3261..b48345bf95f4a34df369d385e74e49d94be96e5f 100755 (executable)
@@ -9,18 +9,21 @@ test_tick
 test_expect_success setup '
        test_commit file0 &&
 
+       mkdir dir1 &&
+       echo 1 >dir1/file &&
        echo 1 >fileA.t &&
        echo 1 >fileB.t &&
        echo 1 >fileC.t &&
        echo 1 >fileD.t &&
-       git add fileA.t fileB.t fileC.t fileD.t &&
+       git add dir1 fileA.t fileB.t fileC.t fileD.t &&
        git commit -m "files 1" &&
 
+       echo 2 >dir1/file &&
        echo 2 >fileA.t &&
        echo 2 >fileB.t &&
        echo 2 >fileC.t &&
        echo 2 >fileD.t &&
-       git add fileA.t fileB.t fileC.t fileD.t &&
+       git add dir1 fileA.t fileB.t fileC.t fileD.t &&
        git commit -m "files 2" &&
 
        git tag checkpoint
@@ -31,7 +34,7 @@ restore_checkpoint () {
 }
 
 verify_expect () {
-       git status --porcelain --untracked-files=no -- fileA.t fileB.t fileC.t fileD.t >actual &&
+       git status --porcelain --untracked-files=no -- dir1 fileA.t fileB.t fileC.t fileD.t >actual &&
        test_cmp expect actual
 }
 
@@ -161,4 +164,14 @@ test_expect_success 'error conditions' '
        test_i18ngrep -e "you must specify path(s) to restore" err
 '
 
+test_expect_success 'wildcard pathspec matches file in subdirectory' '
+       restore_checkpoint &&
+
+       echo "*file" | git restore --pathspec-from-file=- --source=HEAD^1 &&
+       cat >expect <<-\EOF &&
+        M dir1/file
+       EOF
+       verify_expect
+'
+
 test_done
index ffdfb16f580571a50e542b8ddb50915db8ad0584..740ce56eab5c78b18a85834e9dc9c091d195c2d1 100755 (executable)
@@ -152,7 +152,7 @@ test_expect_success 'ls-files -o --directory with mix dir/file pathspecs' '
        )
 '
 
-test_expect_success 'ls-files --o --directory with glob filetype match' '
+test_expect_success 'ls-files -o --directory with glob filetype match' '
        (
                cd nested &&
 
@@ -168,7 +168,7 @@ test_expect_success 'ls-files --o --directory with glob filetype match' '
        )
 '
 
-test_expect_success 'ls-files --o --directory with mix of tracked states' '
+test_expect_success 'ls-files -o --directory with mix of tracked states' '
        (
                cd nested &&
 
@@ -184,7 +184,7 @@ test_expect_success 'ls-files --o --directory with mix of tracked states' '
        )
 '
 
-test_expect_success 'ls-files --o --directory with glob filetype match only' '
+test_expect_success 'ls-files -o --directory with glob filetype match only' '
        (
                cd nested &&
 
@@ -198,7 +198,7 @@ test_expect_success 'ls-files --o --directory with glob filetype match only' '
        )
 '
 
-test_expect_success 'ls-files --o --directory to get immediate paths under one dir only' '
+test_expect_success 'ls-files -o --directory to get immediate paths under one dir only' '
        (
                cd nested &&
 
@@ -212,4 +212,20 @@ test_expect_success 'ls-files --o --directory to get immediate paths under one d
        )
 '
 
+test_expect_success 'ls-files -o avoids listing untracked non-matching gitdir' '
+       test_when_finished "rm -rf nested/untracked/deep/empty" &&
+       (
+               cd nested &&
+
+               git init untracked/deep/empty &&
+               git ls-files --others "untracked/*.c" >actual &&
+
+               cat <<-EOF >expect &&
+               untracked/deep/foo.c
+               EOF
+
+               test_cmp expect actual
+       )
+'
+
 test_done
index 3b4753e1b479bdc9ecddb5a08565e056e9b10b14..94c1b02251c28e68778d8a5c4f1298ec1a84dc52 100755 (executable)
@@ -7,7 +7,7 @@ test_description='Test that adding/removing many notes triggers automatic fanout
 path_has_fanout() {
        path=$1 &&
        fanout=$2 &&
-       after_last_slash=$((40 - $fanout * 2)) &&
+       after_last_slash=$(($(test_oid hexsz) - $fanout * 2)) &&
        echo $path | grep -q "^\([0-9a-f]\{2\}/\)\{$fanout\}[0-9a-f]\{$after_last_slash\}$"
 }
 
index 790e292966b273ec4f915331d7a7bacab91781b8..d69c84c6401c07fc0da32ac2cc20965c8dd6c796 100755 (executable)
@@ -22,7 +22,6 @@ test_expect_success setup '
        # Copy notes to remote-notes
        git fetch . refs/notes/*:refs/remote-notes/origin/* &&
 
-       test_oid_init &&
        test_oid_cache <<-EOF
        hash4a sha1:5e93d24084d32e1cb61f7070505b9d2530cca987
        hash3a sha1:8366731eeee53787d2bdf8fc1eff7d94757e8da0
index 4a7d21f898f7361ffcdf988b2458e52089b758ba..07a1617351dad9729b1b440422fced90a01cc25f 100755 (executable)
@@ -256,7 +256,7 @@ test_expect_success 'stop on conflicting pick' '
        D
        =======
        G
-       >>>>>>> $commit... G
+       >>>>>>> $commit (G)
        EOF
        git tag new-branch1 &&
        test_must_fail git rebase -i master &&
@@ -1250,7 +1250,7 @@ test_expect_success 'rebase -i error on commits with \ in message' '
        test_expect_code 1 grep  "      emp" error
 '
 
-test_expect_success SHA1 'short SHA-1 setup' '
+test_expect_success 'short commit ID setup' '
        test_when_finished "git checkout master" &&
        git checkout --orphan collide &&
        git rm -rf . &&
@@ -1262,23 +1262,54 @@ test_expect_success SHA1 'short SHA-1 setup' '
        )
 '
 
-test_expect_success SHA1 'short SHA-1 collide' '
+if test -n "$GIT_TEST_FIND_COLLIDER"
+then
+       author="$(unset test_tick; test_tick; git var GIT_AUTHOR_IDENT)"
+       committer="$(unset test_tick; test_tick; git var GIT_COMMITTER_IDENT)"
+       blob="$(git rev-parse collide2:collide)"
+       from="$(git rev-parse collide1^0)"
+       repl="commit refs/heads/collider-&\\n"
+       repl="${repl}author $author\\ncommitter $committer\\n"
+       repl="${repl}data <<EOF\\ncollide2 &\\nEOF\\n"
+       repl="${repl}from $from\\nM 100644 $blob collide\\n"
+       test_seq 1 32768 | sed "s|.*|$repl|" >script &&
+       git fast-import <script &&
+       git pack-refs &&
+       git for-each-ref >refs &&
+       grep "^$(test_oid t3404_collision)" <refs >matches &&
+       cat matches &&
+       test_line_count -gt 2 matches || {
+               echo "Could not find a collider" >&2
+               exit 1
+       }
+fi
+
+test_expect_success 'short commit ID collide' '
+       test_oid_cache <<-EOF &&
+       # collision-related constants
+       t3404_collision sha1:6bcd
+       t3404_collision sha256:0161
+       t3404_collider  sha1:ac4f2ee
+       t3404_collider  sha256:16697
+       EOF
        test_when_finished "reset_rebase && git checkout master" &&
        git checkout collide &&
-       colliding_sha1=6bcda37 &&
-       test $colliding_sha1 = "$(git rev-parse HEAD | cut -c 1-7)" &&
+       colliding_id=$(test_oid t3404_collision) &&
+       hexsz=$(test_oid hexsz) &&
+       test $colliding_id = "$(git rev-parse HEAD | cut -c 1-4)" &&
+       test_config core.abbrev 4 &&
        (
                unset test_tick &&
                test_tick &&
                set_fake_editor &&
-               FAKE_COMMIT_MESSAGE="collide2 ac4f2ee" \
+               FAKE_COMMIT_MESSAGE="collide2 $(test_oid t3404_collider)" \
                FAKE_LINES="reword 1 break 2" git rebase -i HEAD~2 &&
-               test $colliding_sha1 = "$(git rev-parse HEAD | cut -c 1-7)" &&
-               grep "^pick $colliding_sha1 " \
+               test $colliding_id = "$(git rev-parse HEAD | cut -c 1-4)" &&
+               grep "^pick $colliding_id " \
                        .git/rebase-merge/git-rebase-todo.tmp &&
-               grep "^pick [0-9a-f]\{40\}" \
+               grep "^pick [0-9a-f]\{$hexsz\}" \
                        .git/rebase-merge/git-rebase-todo &&
-               grep "^pick [0-9a-f]\{40\}" \
+               grep "^pick [0-9a-f]\{$hexsz\}" \
                        .git/rebase-merge/git-rebase-todo.backup &&
                git rebase --continue
        ) &&
@@ -1760,6 +1791,12 @@ test_expect_success 'correct error message for commit --amend after empty pick'
        test_i18ngrep "middle of a rebase -- cannot amend." err
 '
 
+test_expect_success 'todo has correct onto hash' '
+       GIT_SEQUENCE_EDITOR=cat git rebase -i no-conflict-branch~4 no-conflict-branch >actual &&
+       onto=$(git rev-parse --short HEAD~4) &&
+       test_i18ngrep "^# Rebase ..* onto $onto" actual
+'
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
        test_editor_unchanged
index 6f0452c0eac516796e27c5689b2e091c2b21b8ce..a29eda87e9a1265bcddd300628bf43f4167e47e3 100755 (executable)
@@ -60,15 +60,16 @@ test_rebase_same_head_ () {
                fi &&
                oldhead=\$(git rev-parse HEAD) &&
                test_when_finished 'git reset --hard \$oldhead' &&
-               cp .git/logs/HEAD expect &&
+               git reflog HEAD >expect &&
                git rebase$flag $* >stdout &&
+               git reflog HEAD >actual &&
                if test $what = work
                then
                        old=\$(wc -l <expect) &&
-                       test_line_count '-gt' \$old .git/logs/HEAD
+                       test_line_count '-gt' \$old actual
                elif test $what = noop
                then
-                       test_cmp expect .git/logs/HEAD
+                       test_cmp expect actual
                fi &&
                newhead=\$(git rev-parse HEAD) &&
                if test $cmp = same
index f038f34b7c03b419b9341770a6924767a0b8e8d7..2b8d9cb38ed3e3c39dd386b767f88d13e06532af 100755 (executable)
@@ -55,4 +55,27 @@ test_expect_success \
      expr "$(echo $(git cherry master my-topic-branch) )" : "+ [^ ]* - .*"
 '
 
+test_expect_success 'cherry ignores whitespace' '
+       git switch --orphan=upstream-with-space &&
+       test_commit initial file &&
+       >expect &&
+       git switch --create=feature-without-space &&
+
+       # A spaceless file on the feature branch.  Expect a match upstream.
+       printf space >file &&
+       git add file &&
+       git commit -m"file without space" &&
+       git log --format="- %H" -1 >>expect &&
+
+       # A further change.  Should not match upstream.
+       test_commit change file &&
+       git log --format="+ %H" -1 >>expect &&
+
+       git switch upstream-with-space &&
+       # Same as the spaceless file, just with spaces and on upstream.
+       test_commit "file with space" file "s p a c e" file-with-space &&
+       git cherry upstream-with-space feature-without-space >actual &&
+       test_cmp expect actual
+'
+
 test_done
index 7c1da21df1493a501dc25e34c339c1bd5aecc2cf..3669dfb1bed5bee1130f672aace510dca020ae7c 100755 (executable)
@@ -47,7 +47,7 @@ test_expect_success 'cherry-pick --nonsense' '
        git diff --exit-code HEAD &&
        test_must_fail git cherry-pick --nonsense 2>msg &&
        git diff --exit-code HEAD "$pos" &&
-       test_i18ngrep '[Uu]sage:' msg
+       test_i18ngrep "[Uu]sage:" msg
 '
 
 test_expect_success 'revert --nonsense' '
@@ -56,7 +56,7 @@ test_expect_success 'revert --nonsense' '
        git diff --exit-code HEAD &&
        test_must_fail git revert --nonsense 2>msg &&
        git diff --exit-code HEAD "$pos" &&
-       test_i18ngrep '[Uu]sage:' msg
+       test_i18ngrep "[Uu]sage:" msg
 '
 
 test_expect_success 'cherry-pick after renaming branch' '
index 752bc43487196a4be33ff7df770384f331a68315..a21adcf0e43a6d6003e60809a3dc8f20772fef2e 100755 (executable)
@@ -283,12 +283,12 @@ test_expect_success 'failed cherry-pick describes conflict in work tree' '
        a
        =======
        c
-       >>>>>>> objid picked
+       >>>>>>> objid (picked)
        EOF
 
        test_must_fail git cherry-pick picked &&
 
-       sed "s/[a-f0-9]*\.\.\./objid/" foo >actual &&
+       sed "s/[a-f0-9]* (/objid (/" foo >actual &&
        test_cmp expected actual
 '
 
@@ -298,16 +298,16 @@ test_expect_success 'diff3 -m style' '
        cat <<-EOF >expected &&
        <<<<<<< HEAD
        a
-       ||||||| parent of objid picked
+       ||||||| parent of objid (picked)
        b
        =======
        c
-       >>>>>>> objid picked
+       >>>>>>> objid (picked)
        EOF
 
        test_must_fail git cherry-pick picked &&
 
-       sed "s/[a-f0-9]*\.\.\./objid/" foo >actual &&
+       sed "s/[a-f0-9]* (/objid (/" foo >actual &&
        test_cmp expected actual
 '
 
@@ -319,7 +319,7 @@ test_expect_success 'revert also handles conflicts sanely' '
        a
        =======
        b
-       >>>>>>> parent of objid picked
+       >>>>>>> parent of objid (picked)
        EOF
        {
                git checkout picked -- foo &&
@@ -345,7 +345,7 @@ test_expect_success 'revert also handles conflicts sanely' '
        test_must_fail git update-index --refresh -q &&
        test_must_fail git diff-index --exit-code HEAD &&
        test_cmp expected-stages actual-stages &&
-       sed "s/[a-f0-9]*\.\.\./objid/" foo >actual &&
+       sed "s/[a-f0-9]* (/objid (/" foo >actual &&
        test_cmp expected actual
 '
 
@@ -429,16 +429,16 @@ test_expect_success 'revert conflict, diff3 -m style' '
        cat <<-EOF >expected &&
        <<<<<<< HEAD
        a
-       ||||||| objid picked
+       ||||||| objid (picked)
        c
        =======
        b
-       >>>>>>> parent of objid picked
+       >>>>>>> parent of objid (picked)
        EOF
 
        test_must_fail git revert picked &&
 
-       sed "s/[a-f0-9]*\.\.\./objid/" foo >actual &&
+       sed "s/[a-f0-9]* (/objid (/" foo >actual &&
        test_cmp expected actual
 '
 
@@ -512,7 +512,7 @@ test_expect_success 'commit after failed cherry-pick adds -s at the right place'
        Signed-off-by: C O Mitter <committer@example.com>
        # Conflicts:
        EOF
-       grep -e "^# Conflicts:" -e '^Signed-off-by' .git/COMMIT_EDITMSG >actual &&
+       grep -e "^# Conflicts:" -e "^Signed-off-by" .git/COMMIT_EDITMSG >actual &&
        test_cmp expect actual &&
 
        cat <<-\EOF >expected &&
@@ -541,7 +541,7 @@ test_expect_success 'commit --amend -s places the sign-off at the right place' '
        Signed-off-by: C O Mitter <committer@example.com>
        Conflicts:
        EOF
-       grep -e "^Conflicts:" -e '^Signed-off-by' .git/COMMIT_EDITMSG >actual &&
+       grep -e "^Conflicts:" -e "^Signed-off-by" .git/COMMIT_EDITMSG >actual &&
        test_cmp expect actual
 '
 
index f2c0168941ad043f61a1e082799e75cefa3b5462..efec8d13b661826af434db6b891a404118301735 100755 (executable)
@@ -241,7 +241,6 @@ test_expect_success 'refresh index before checking if it is up-to-date' '
 '
 
 test_expect_success 'choking "git rm" should not let it die with cruft' '
-       test_oid_init &&
        git reset -q --hard &&
        test_when_finished "rm -f .git/index.lock && git reset -q --hard" &&
        i=0 &&
index 49decbac711386b497b19f22d16324422c0609b5..fb73a847cb9dba41081a2e8d9d34cd4ea1950268 100755 (executable)
@@ -31,7 +31,16 @@ diff_cmp () {
 # indicates a dumb terminal, so we set that variable, too.
 
 force_color () {
-       env GIT_PAGER_IN_USE=true TERM=vt100 "$@"
+       # The first element of $@ may be a shell function, as a result POSIX
+       # does not guarantee that "one-shot assignment" will not persist after
+       # the function call. Thus, we prevent these variables from escaping
+       # this function's context with this subshell.
+       (
+               GIT_PAGER_IN_USE=true &&
+               TERM=vt100 &&
+               export GIT_PAGER_IN_USE TERM &&
+               "$@"
+       )
 }
 
 test_expect_success 'setup (initial)' '
@@ -604,7 +613,7 @@ test_expect_success 'detect bogus diffFilter output' '
        echo content >test &&
        test_config interactive.diffFilter "sed 1d" &&
        printf y >y &&
-       test_must_fail force_color git add -p <y
+       force_color test_must_fail git add -p <y
 '
 
 test_expect_success 'diff.algorithm is passed to `git diff-files`' '
index 64dcc5ec289ee0b0d042f1ecefd237a1dddad2be..d696aa4e52e2baf474fe75424964a69a2023b8d3 100755 (executable)
@@ -23,7 +23,6 @@ check_verify_failure () {
 # first create a commit, so we have a valid object/type
 # for the tag.
 test_expect_success 'setup' '
-       test_oid_init &&
        echo Hello >A &&
        git update-index --add A &&
        git commit -m "Initial commit" &&
index cbcdd104647b242c552d39d4f0529298936f8450..6a9f010197c7ca60a859670abeb3a3df1950a09c 100755 (executable)
@@ -10,8 +10,6 @@ test_description='Test diff raw-output.
 
 . "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh
 
-test_oid_init
-
 test_oid_cache <<\EOF
 aa_1 sha1:ccba72ad3888a3520b39efcf780b9ee64167535d
 aa_1 sha256:9febfbf18197819b2735c45291f138525d2476d59470f98239647544586ba403
index f542d2929d2316fa8d858fc29c1bdfb5ef4c3c71..d18a80493c2274d19a6f779bd1c67c50b63a6290 100755 (executable)
@@ -14,8 +14,8 @@ test_expect_success 'setup reference tree' '
        git update-index --add COPYING rezrov &&
        tree=$(git write-tree) &&
        echo $tree &&
-       sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 &&
-       sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 &&
+       sed -e "s/HOWEVER/However/" <COPYING >COPYING.1 &&
+       sed -e "s/GPL/G.P.L/g" <COPYING >COPYING.2 &&
        origoid=$(git hash-object COPYING) &&
        oid1=$(git hash-object COPYING.1) &&
        oid2=$(git hash-object COPYING.2)
index e5ca359edfa6087f5833c2e77324b7f9960d06cb..65cc703c659b8941f1458e4f4b0b6d88dc5622d1 100755 (executable)
@@ -125,7 +125,9 @@ test_expect_success 'setup submodules' '
 test_expect_success 'diff-tree ignores trailing slash on submodule path' '
        git diff --name-only HEAD^ HEAD submod >expect &&
        git diff --name-only HEAD^ HEAD submod/ >actual &&
-       test_cmp expect actual
+       test_cmp expect actual &&
+       git diff --name-only HEAD^ HEAD -- submod/whatever >actual &&
+       test_must_be_empty actual
 '
 
 test_expect_success 'diff multiple wildcard pathspecs' '
index 43267d6024fb70110634314d664a885ea477053c..5c7b0122b4f194d327d488d4b5dd6b8ad28e7673 100755 (executable)
@@ -117,12 +117,12 @@ test_expect_success setup '
 
 : <<\EOF
 ! [initial] Initial
- * [master] Merge branch 'side' into master
+ * [master] Merge branch 'side'
   ! [rearrange] Rearranged lines in dir/sub
    ! [side] Side
 ----
   +  [rearrange] Rearranged lines in dir/sub
- -   [master] Merge branch 'side' into master
+ -   [master] Merge branch 'side'
  * + [side] Side
  *   [master^] Third
  *   [master~2] Second
@@ -130,27 +130,45 @@ test_expect_success setup '
 EOF
 
 process_diffs () {
-       _x04="[0-9a-f][0-9a-f][0-9a-f][0-9a-f]" &&
-       _x07="$_x05[0-9a-f][0-9a-f]" &&
-       sed -e "s/$OID_REGEX/$ZERO_OID/g" \
-           -e "s/From $_x40 /From $ZERO_OID /" \
-           -e "s/from $_x40)/from $ZERO_OID)/" \
-           -e "s/commit $_x40\$/commit $ZERO_OID/" \
-           -e "s/commit $_x40 (/commit $ZERO_OID (/" \
-           -e "s/$_x40 $_x40 $_x40/$ZERO_OID $ZERO_OID $ZERO_OID/" \
-           -e "s/$_x40 $_x40 /$ZERO_OID $ZERO_OID /" \
-           -e "s/^$_x40 $_x40$/$ZERO_OID $ZERO_OID/" \
-           -e "s/^$_x40 /$ZERO_OID /" \
-           -e "s/^$_x40$/$ZERO_OID/" \
-           -e "s/$_x07\.\.$_x07/fffffff..fffffff/g" \
-           -e "s/$_x07,$_x07\.\.$_x07/fffffff,fffffff..fffffff/g" \
-           -e "s/$_x07 $_x07 $_x07/fffffff fffffff fffffff/g" \
-           -e "s/$_x07 $_x07 /fffffff fffffff /g" \
-           -e "s/Merge: $_x07 $_x07/Merge: fffffff fffffff/g" \
-           -e "s/$_x07\.\.\./fffffff.../g" \
-           -e "s/ $_x04\.\.\./ ffff.../g" \
-           -e "s/ $_x04/ ffff/g" \
-           "$1"
+       perl -e '
+               my $oid_length = length($ARGV[0]);
+               my $x40 = "[0-9a-f]{40}";
+               my $xab = "[0-9a-f]{4,16}";
+               my $orx = "[0-9a-f]" x $oid_length;
+
+               sub munge_oid {
+                       my ($oid) = @_;
+                       my $x;
+
+                       return "" unless length $oid;
+
+                       if ($oid =~ /^(100644|100755|120000)$/) {
+                               return $oid;
+                       }
+
+                       if ($oid =~ /^0*$/) {
+                               $x = "0";
+                       } else {
+                               $x = "f";
+                       }
+
+                       if (length($oid) == 40) {
+                               return $x x $oid_length;
+                       } else {
+                               return $x x length($oid);
+                       }
+               }
+
+               while (<STDIN>) {
+                       s/($orx)/munge_oid($1)/ge;
+                       s/From ($x40)( |\))/"From " . munge_oid($1) . $2/ge;
+                       s/commit ($x40)($| \(from )($x40?)/"commit " .  munge_oid($1) . $2 . munge_oid($3)/ge;
+                       s/\b($x40)( |\.\.|$)/munge_oid($1) . $2/ge;
+                       s/^($x40)($| )/munge_oid($1) . $2/e;
+                       s/($xab)(\.\.|,| |\.\.\.|$)/munge_oid($1) . $2/ge;
+                       print;
+               }
+       ' "$ZERO_OID" <"$1"
 }
 
 V=$(git version | sed -e 's/^git version //' -e 's/\./\\./g')
@@ -221,6 +239,9 @@ diff-tree --root -r --abbrev=4 initial
 :noellipses diff-tree --root -r --abbrev=4 initial
 diff-tree -p initial
 diff-tree --root -p initial
+diff-tree --root -p --abbrev=10 initial
+diff-tree --root -p --full-index initial
+diff-tree --root -p --full-index --abbrev=10 initial
 diff-tree --patch-with-stat initial
 diff-tree --root --patch-with-stat initial
 diff-tree --patch-with-raw initial
@@ -297,6 +318,9 @@ log --root --patch-with-stat --summary master
 log --root -c --patch-with-stat --summary master
 # improved by Timo's patch
 log --root --cc --patch-with-stat --summary master
+log --no-diff-merges -p --first-parent master
+log --diff-merges=off -p --first-parent master
+log --first-parent --diff-merges=off -p master
 log -p --first-parent master
 log -m -p --first-parent master
 log -m -p master
diff --git a/t/t4013/diff.diff-tree_--root_-p_--abbrev=10_initial b/t/t4013/diff.diff-tree_--root_-p_--abbrev=10_initial
new file mode 100644 (file)
index 0000000..7518a90
--- /dev/null
@@ -0,0 +1,29 @@
+$ git diff-tree --root -p --abbrev=10 initial
+444ac553ac7612cc88969031b02b3767fb8a353a
+diff --git a/dir/sub b/dir/sub
+new file mode 100644
+index 0000000000..35d242ba79
+--- /dev/null
++++ b/dir/sub
+@@ -0,0 +1,2 @@
++A
++B
+diff --git a/file0 b/file0
+new file mode 100644
+index 0000000000..01e79c32a8
+--- /dev/null
++++ b/file0
+@@ -0,0 +1,3 @@
++1
++2
++3
+diff --git a/file2 b/file2
+new file mode 100644
+index 0000000000..01e79c32a8
+--- /dev/null
++++ b/file2
+@@ -0,0 +1,3 @@
++1
++2
++3
+$
diff --git a/t/t4013/diff.diff-tree_--root_-p_--full-index_--abbrev=10_initial b/t/t4013/diff.diff-tree_--root_-p_--full-index_--abbrev=10_initial
new file mode 100644 (file)
index 0000000..69f913f
--- /dev/null
@@ -0,0 +1,29 @@
+$ git diff-tree --root -p --full-index --abbrev=10 initial
+444ac553ac7612cc88969031b02b3767fb8a353a
+diff --git a/dir/sub b/dir/sub
+new file mode 100644
+index 0000000000000000000000000000000000000000..35d242ba79ae89ac695e26b3d4c27a8e6f028f9e
+--- /dev/null
++++ b/dir/sub
+@@ -0,0 +1,2 @@
++A
++B
+diff --git a/file0 b/file0
+new file mode 100644
+index 0000000000000000000000000000000000000000..01e79c32a8c99c557f0757da7cb6d65b3414466d
+--- /dev/null
++++ b/file0
+@@ -0,0 +1,3 @@
++1
++2
++3
+diff --git a/file2 b/file2
+new file mode 100644
+index 0000000000000000000000000000000000000000..01e79c32a8c99c557f0757da7cb6d65b3414466d
+--- /dev/null
++++ b/file2
+@@ -0,0 +1,3 @@
++1
++2
++3
+$
diff --git a/t/t4013/diff.diff-tree_--root_-p_--full-index_initial b/t/t4013/diff.diff-tree_--root_-p_--full-index_initial
new file mode 100644 (file)
index 0000000..1b0b671
--- /dev/null
@@ -0,0 +1,29 @@
+$ git diff-tree --root -p --full-index initial
+444ac553ac7612cc88969031b02b3767fb8a353a
+diff --git a/dir/sub b/dir/sub
+new file mode 100644
+index 0000000000000000000000000000000000000000..35d242ba79ae89ac695e26b3d4c27a8e6f028f9e
+--- /dev/null
++++ b/dir/sub
+@@ -0,0 +1,2 @@
++A
++B
+diff --git a/file0 b/file0
+new file mode 100644
+index 0000000000000000000000000000000000000000..01e79c32a8c99c557f0757da7cb6d65b3414466d
+--- /dev/null
++++ b/file0
+@@ -0,0 +1,3 @@
++1
++2
++3
+diff --git a/file2 b/file2
+new file mode 100644
+index 0000000000000000000000000000000000000000..01e79c32a8c99c557f0757da7cb6d65b3414466d
+--- /dev/null
++++ b/file2
+@@ -0,0 +1,3 @@
++1
++2
++3
+$
index c56783b9854f2e4734403444d09bcb36a24bc374..3f9b872eceb734cb1e7adbd53a4de0580b1cd524 100644 (file)
@@ -31,7 +31,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (refs/heads/side)
 Author: A U Thor <author@example.com>
index 1cbdc038f41c84cba220782ab10ae1857b9bc717..f5e20e1e14aaef179ac9570b0e16bc47077ff79d 100644 (file)
@@ -31,7 +31,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (side)
 Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_--diff-merges=off_-p_--first-parent_master b/t/t4013/diff.log_--diff-merges=off_-p_--first-parent_master
new file mode 100644 (file)
index 0000000..194e893
--- /dev/null
@@ -0,0 +1,78 @@
+$ git log --diff-merges=off -p --first-parent master
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+Merge: 9a6d494 c7a2ab9
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:04:00 2006 +0000
+
+    Merge branch 'side'
+
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:02:00 2006 +0000
+
+    Third
+
+diff --git a/dir/sub b/dir/sub
+index 8422d40..cead32e 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -2,3 +2,5 @@ A
+ B
+ C
+ D
++E
++F
+diff --git a/file1 b/file1
+new file mode 100644
+index 0000000..b1e6722
+--- /dev/null
++++ b/file1
+@@ -0,0 +1,3 @@
++A
++B
++C
+
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:01:00 2006 +0000
+
+    Second
+    
+    This is the second commit.
+
+diff --git a/dir/sub b/dir/sub
+index 35d242b..8422d40 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -1,2 +1,4 @@
+ A
+ B
++C
++D
+diff --git a/file0 b/file0
+index 01e79c3..b414108 100644
+--- a/file0
++++ b/file0
+@@ -1,3 +1,6 @@
+ 1
+ 2
+ 3
++4
++5
++6
+diff --git a/file2 b/file2
+deleted file mode 100644
+index 01e79c3..0000000
+--- a/file2
++++ /dev/null
+@@ -1,3 +0,0 @@
+-1
+-2
+-3
+
+commit 444ac553ac7612cc88969031b02b3767fb8a353a
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:00:00 2006 +0000
+
+    Initial
+$
diff --git a/t/t4013/diff.log_--first-parent_--diff-merges=off_-p_master b/t/t4013/diff.log_--first-parent_--diff-merges=off_-p_master
new file mode 100644 (file)
index 0000000..5d7461a
--- /dev/null
@@ -0,0 +1,78 @@
+$ git log --first-parent --diff-merges=off -p master
+commit 80e25ffa65bcdbe82ef654b4d06dbbde7945c37f
+Merge: 9a6d494 c7a2ab9
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:04:00 2006 +0000
+
+    Merge branch 'side'
+
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:02:00 2006 +0000
+
+    Third
+
+diff --git a/dir/sub b/dir/sub
+index 8422d40..cead32e 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -2,3 +2,5 @@ A
+ B
+ C
+ D
++E
++F
+diff --git a/file1 b/file1
+new file mode 100644
+index 0000000..b1e6722
+--- /dev/null
++++ b/file1
+@@ -0,0 +1,3 @@
++A
++B
++C
+
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:01:00 2006 +0000
+
+    Second
+    
+    This is the second commit.
+
+diff --git a/dir/sub b/dir/sub
+index 35d242b..8422d40 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -1,2 +1,4 @@
+ A
+ B
++C
++D
+diff --git a/file0 b/file0
+index 01e79c3..b414108 100644
+--- a/file0
++++ b/file0
+@@ -1,3 +1,6 @@
+ 1
+ 2
+ 3
++4
++5
++6
+diff --git a/file2 b/file2
+deleted file mode 100644
+index 01e79c3..0000000
+--- a/file2
++++ /dev/null
+@@ -1,3 +0,0 @@
+-1
+-2
+-3
+
+commit 444ac553ac7612cc88969031b02b3767fb8a353a
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:00:00 2006 +0000
+
+    Initial
+$
diff --git a/t/t4013/diff.log_--no-diff-merges_-p_--first-parent_master b/t/t4013/diff.log_--no-diff-merges_-p_--first-parent_master
new file mode 100644 (file)
index 0000000..5970022
--- /dev/null
@@ -0,0 +1,78 @@
+$ git log --no-diff-merges -p --first-parent master
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+Merge: 9a6d494 c7a2ab9
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:04:00 2006 +0000
+
+    Merge branch 'side'
+
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:02:00 2006 +0000
+
+    Third
+
+diff --git a/dir/sub b/dir/sub
+index 8422d40..cead32e 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -2,3 +2,5 @@ A
+ B
+ C
+ D
++E
++F
+diff --git a/file1 b/file1
+new file mode 100644
+index 0000000..b1e6722
+--- /dev/null
++++ b/file1
+@@ -0,0 +1,3 @@
++A
++B
++C
+
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:01:00 2006 +0000
+
+    Second
+    
+    This is the second commit.
+
+diff --git a/dir/sub b/dir/sub
+index 35d242b..8422d40 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -1,2 +1,4 @@
+ A
+ B
++C
++D
+diff --git a/file0 b/file0
+index 01e79c3..b414108 100644
+--- a/file0
++++ b/file0
+@@ -1,3 +1,6 @@
+ 1
+ 2
+ 3
++4
++5
++6
+diff --git a/file2 b/file2
+deleted file mode 100644
+index 01e79c3..0000000
+--- a/file2
++++ /dev/null
+@@ -1,3 +0,0 @@
+-1
+-2
+-3
+
+commit 444ac553ac7612cc88969031b02b3767fb8a353a
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:00:00 2006 +0000
+
+    Initial
+$
index f5b1b6516b90744b5d3270f19505bcd9bdeb7372..a18f1472a9a4b5b098a2c342a9f77fc68a3b6dc0 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
index af23803cdcd8f59936270fda5c93373616d45afd..ae425c4672200ad73cb2db228bd7385757673ee3 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
index 814098fbf875dfa2e33170e3e594ce485203a9cf..d5207cadf4483a7e63b6085a9007623c73b1a694 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
index b927fe4a98e43ce3fff8fdd8da4623026f49bb02..0fc1e8cd71fee38125e77487da29c12c5863a054 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
  dir/sub | 2 ++
  file0   | 3 +++
index 6db3cea32952fb83b6fe68d8f334a3430885be63..dffc09dde9e03179f48cea86e04aac34f1d30504 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
index 98e9c320c32dea3c152c70fa4ad4a240ad46f746..55aa98012dece9e96d1092f442b6235d420ca42f 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
index b61b1117ae58f7a33d8313a4bb11a4c797dadfe5..019d85f7de6c2d360ae2f9addd65bacd9bee318b 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
  dir/sub | 2 ++
  file0   | 3 +++
index 345bd9e8a905e1a987853e014bb4124c6342c4dc..b42c334439b71cdb391d832d498b90a22aad2656 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
index db56b1fe6b27613983b46d39d0b5bd29c59f9bdc..e8f46159da1e5ca68524f5657010d06667a9c94b 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
index bcadb50e26d000bcb02737ee234db03df7d0e9e2..7a0073f5296b19fde379a37b7441de29bcf07a42 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 diff --git a/dir/sub b/dir/sub
 index cead32e..992913c 100644
index 2acf43a9fbe113033cd46d526ff3a819f6b5d102..9ca62a01ed2bea737d66e08126f6c47ef3b768fe 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 diff --git a/dir/sub b/dir/sub
 index cead32e..992913c 100644
@@ -33,7 +33,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 diff --git a/dir/sub b/dir/sub
 index 7289e35..992913c 100644
index c6a5876d8000b7a1f71fcb927ec08964d0470985..28840ebea1e33a41402b392833093df2e92f8035 100644 (file)
@@ -4,7 +4,29 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
+
+diff --git a/dir/sub b/dir/sub
+index cead32e..992913c 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -4,3 +4,5 @@ C
+ D
+ E
+ F
++1
++2
+diff --git a/file0 b/file0
+index b414108..10a8a9f 100644
+--- a/file0
++++ b/file0
+@@ -4,3 +4,6 @@
+ 4
+ 5
+ 6
++A
++B
++C
 
 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
 Author: A U Thor <author@example.com>
index 1841cded94fdf7c33994b622d3bde5687bd020dd..bf1326dc36629096fc4e4102375c8a9c550391aa 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
index f8ec445eb3ee7cb642e85a73faaf97988ebc484b..a8f6ce5abd642e51672eb3e0ae5ea66a08aa74d2 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor <author@example.com>
index 94548f4598508f45e298e0ce07ef8146c6cfe256..3dcbe473a0d2a7ac0b7f4243b610cff756d44759 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 diff --git a/dir/sub b/dir/sub
 index cead32e..992913c 100644
index 1c46ed64fd65631929b064c7b6f16cb452f0c93f..81aba8da96c05d1b4717bc12b8bfd271d2bdc9bd 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 diff --combined dir/sub
 index cead32e,7289e35..992913c
index 7559fc22f804077bf4b733e2421b2078d02147e4..4ea2ee453d5e18bef87477cb8758e6fcaef0f011 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 diff --git a/dir/sub b/dir/sub
 index cead32e..992913c 100644
@@ -33,7 +33,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 diff --git a/dir/sub b/dir/sub
 index 7289e35..992913c 100644
index 57091c5d90d03981b82eff6d8a13ebbc9df14c64..fb08ce0e46d16d223269754295cc4a8dc4364268 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
 diff --cc dir/sub
 index cead32e,7289e35..992913c
index 5f13a71bb53d5ee31c97ce527d3e8744cde57169..30aae7817b952d1088c872453a6a38a681fcd946 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
  dir/sub | 2 ++
  file0   | 3 +++
index 8acb88267b2f520179042e83ba52ed635b82afcf..d1d32bd34c333411661355685368130faec79764 100644 (file)
@@ -4,7 +4,7 @@ Merge: 9a6d494 c7a2ab9
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:04:00 2006 +0000
 
-    Merge branch 'side' into master
+    Merge branch 'side'
 
  dir/sub | 2 ++
  file0   | 3 +++
diff --git a/t/t4018/fortran-block-data b/t/t4018/fortran-block-data
new file mode 100644 (file)
index 0000000..63d4e21
--- /dev/null
@@ -0,0 +1,5 @@
+       BLOCK DATA RIGHT
+       
+       COMMON /B/ C, ChangeMe
+       DATA C, ChangeMe  / 2.0, 6.0 / 
+       END 
diff --git a/t/t4018/fortran-comment b/t/t4018/fortran-comment
new file mode 100644 (file)
index 0000000..7b10d17
--- /dev/null
@@ -0,0 +1,13 @@
+      module a
+
+      contains
+
+      ! subroutine wrong
+      subroutine RIGHT
+      ! subroutine wrong
+
+      real ChangeMe
+
+      end subroutine RIGHT
+
+      end module a
diff --git a/t/t4018/fortran-comment-keyword b/t/t4018/fortran-comment-keyword
new file mode 100644 (file)
index 0000000..e9206a5
--- /dev/null
@@ -0,0 +1,14 @@
+      module a
+
+      contains
+
+      subroutine RIGHT (funcA, funcB)
+
+      real funcA  ! grid function a
+      real funcB  ! grid function b
+
+      real ChangeMe
+
+      end subroutine RIGHT
+
+      end module a
diff --git a/t/t4018/fortran-comment-legacy b/t/t4018/fortran-comment-legacy
new file mode 100644 (file)
index 0000000..53cd062
--- /dev/null
@@ -0,0 +1,13 @@
+      module a
+
+      contains
+
+C subroutine wrong
+      subroutine RIGHT
+C subroutine wrong
+
+      real ChangeMe
+
+      end subroutine RIGHT
+
+      end module a
diff --git a/t/t4018/fortran-comment-legacy-star b/t/t4018/fortran-comment-legacy-star
new file mode 100644 (file)
index 0000000..2cbcdc3
--- /dev/null
@@ -0,0 +1,13 @@
+      module a
+
+      contains
+
+* subroutine wrong
+      subroutine RIGHT
+* subroutine wrong
+
+      real ChangeMe
+
+      end subroutine RIGHT
+
+      end module a
diff --git a/t/t4018/fortran-external-function b/t/t4018/fortran-external-function
new file mode 100644 (file)
index 0000000..5a2d85d
--- /dev/null
@@ -0,0 +1,9 @@
+function RIGHT(a, b) result(c)
+
+integer, intent(in) :: ChangeMe
+integer, intent(in) :: b
+integer, intent(out) :: c
+
+c = a+b
+
+end function RIGHT
diff --git a/t/t4018/fortran-external-subroutine b/t/t4018/fortran-external-subroutine
new file mode 100644 (file)
index 0000000..4ce85fe
--- /dev/null
@@ -0,0 +1,5 @@
+subroutine RIGHT
+
+real ChangeMe
+
+end subroutine RIGHT
diff --git a/t/t4018/fortran-module b/t/t4018/fortran-module
new file mode 100644 (file)
index 0000000..c4b737d
--- /dev/null
@@ -0,0 +1,5 @@
+module RIGHT
+
+use ChangeMe
+
+end module RIGHT
diff --git a/t/t4018/fortran-module-procedure b/t/t4018/fortran-module-procedure
new file mode 100644 (file)
index 0000000..1ce6d85
--- /dev/null
@@ -0,0 +1,13 @@
+ module RIGHT
+
+   implicit none
+   private
+
+   interface letters  ! generic interface
+      module procedure aaaa, &
+                       bbbb, &
+                       ChangeMe, &
+                       dddd
+   end interface
+   
+end module RIGHT
diff --git a/t/t4018/fortran-program b/t/t4018/fortran-program
new file mode 100644 (file)
index 0000000..4616895
--- /dev/null
@@ -0,0 +1,5 @@
+program RIGHT
+
+call ChangeMe
+
+end program RIGHT
index e29deaf4a509523b00e6bf9ac5d2436957a1b022..d7145ccca4b8a66fb9af73b8554b9cf2bd7d9a73 100755 (executable)
@@ -6,7 +6,6 @@ test_description='difference in submodules'
 . "$TEST_DIRECTORY"/diff-lib.sh
 
 test_expect_success setup '
-       test_oid_init &&
        test_tick &&
        test_create_repo sub &&
        (
index fb145aa173ee4ea4c79bcb01336c433e16fa81e5..0c8fb39cedaa31f6f586895cd57a878158624f13 100755 (executable)
@@ -102,7 +102,7 @@ test_expect_success 'word diff with runs of whitespace' '
 '
 
 test_expect_success '--word-diff=porcelain' '
-       sed 's/#.*$//' >expect <<-EOF &&
+       sed "s/#.*$//" >expect <<-EOF &&
                diff --git a/pre b/post
                index $pre..$post 100644
                --- a/pre
index 32e3b0ee0b9d00516602934353d92da35e8b19f1..71ef4132d153b7be4b4f3d4ebfb1a85ee4bfa9ab 100755 (executable)
@@ -3,80 +3,55 @@
 # Copyright (c) 2005 Junio C Hamano
 #
 
-test_description='git apply boundary tests
+test_description='git apply boundary tests'
 
-'
 . ./test-lib.sh
 
 L="c d e f g h i j k l m n o p q r s t u v w x"
 
 test_expect_success setup '
-       for i in b '"$L"' y
-       do
-               echo $i
-       done >victim &&
+       test_write_lines b $L y >victim &&
        cat victim >original &&
        git update-index --add victim &&
 
        # add to the head
-       for i in a b '"$L"' y
-       do
-               echo $i
-       done >victim &&
+       test_write_lines a b $L y >victim &&
        cat victim >add-a-expect &&
        git diff victim >add-a-patch.with &&
        git diff --unified=0 >add-a-patch.without &&
 
        # insert at line two
-       for i in b a '"$L"' y
-       do
-               echo $i
-       done >victim &&
+       test_write_lines b a $L y >victim &&
        cat victim >insert-a-expect &&
        git diff victim >insert-a-patch.with &&
        git diff --unified=0 >insert-a-patch.without &&
 
        # modify at the head
-       for i in a '"$L"' y
-       do
-               echo $i
-       done >victim &&
+       test_write_lines a $L y >victim &&
        cat victim >mod-a-expect &&
        git diff victim >mod-a-patch.with &&
        git diff --unified=0 >mod-a-patch.without &&
 
        # remove from the head
-       for i in '"$L"' y
-       do
-               echo $i
-       done >victim &&
+       test_write_lines $L y >victim &&
        cat victim >del-a-expect &&
        git diff victim >del-a-patch.with &&
        git diff --unified=0 >del-a-patch.without &&
 
        # add to the tail
-       for i in b '"$L"' y z
-       do
-               echo $i
-       done >victim &&
+       test_write_lines b $L y z >victim &&
        cat victim >add-z-expect &&
        git diff victim >add-z-patch.with &&
        git diff --unified=0 >add-z-patch.without &&
 
        # modify at the tail
-       for i in b '"$L"' z
-       do
-               echo $i
-       done >victim &&
+       test_write_lines b $L z >victim &&
        cat victim >mod-z-expect &&
        git diff victim >mod-z-patch.with &&
        git diff --unified=0 >mod-z-patch.without &&
 
        # remove from the tail
-       for i in b '"$L"'
-       do
-               echo $i
-       done >victim &&
+       test_write_lines b $L >victim &&
        cat victim >del-z-expect &&
        git diff victim >del-z-patch.with &&
        git diff --unified=0 >del-z-patch.without
@@ -88,15 +63,15 @@ for with in with without
 do
        case "$with" in
        with) u= ;;
-       without) u='--unidiff-zero ' ;;
+       without) u=--unidiff-zero ;;
        esac
        for kind in add-a add-z insert-a mod-a mod-z del-a del-z
        do
                test_expect_success "apply $kind-patch $with context" '
                        cat original >victim &&
                        git update-index victim &&
-                       git apply --index '"$u$kind-patch.$with"' &&
-                       test_cmp '"$kind"'-expect victim
+                       git apply --index $u "$kind-patch.$with" &&
+                       test_cmp "$kind-expect" victim
                '
        done
 done
@@ -110,13 +85,12 @@ do
        test_expect_success "apply non-git $kind-patch without context" '
                cat original >victim &&
                git update-index victim &&
-               git apply --unidiff-zero --index '"$kind-ng.without"' &&
-               test_cmp '"$kind"'-expect victim
+               git apply --unidiff-zero --index "$kind-ng.without" &&
+               test_cmp "$kind-expect" victim
        '
 done
 
 test_expect_success 'two lines' '
-
        >file &&
        git add file &&
        echo aaa >file &&
@@ -125,11 +99,10 @@ test_expect_success 'two lines' '
        echo bbb >file &&
        git add file &&
        test_must_fail git apply --check patch
-
 '
 
 test_expect_success 'apply patch with 3 context lines matching at end' '
-       { echo a; echo b; echo c; echo d; } >file &&
+       test_write_lines a b c d >file &&
        git add file &&
        echo e >>file &&
        git diff >patch &&
index 99ed4cc54676de6d56a2caa6a8f38d2c834700f9..d1c16ba33c114477616d82d8e5d9fcbf53ed53ef 100755 (executable)
@@ -8,7 +8,6 @@ test_description='git apply submodule tests'
 . ./test-lib.sh
 
 test_expect_success setup '
-       test_oid_init &&
        cat > create-sm.patch <<EOF &&
 diff --git a/dir/sm b/dir/sm
 new file mode 160000
diff --git a/t/t4140-apply-ita.sh b/t/t4140-apply-ita.sh
new file mode 100755 (executable)
index 0000000..c614eaf
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+test_description='git apply of i-t-a file'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+       test_write_lines 1 2 3 4 5 >blueprint &&
+
+       cat blueprint >test-file &&
+       git add -N test-file &&
+       git diff >creation-patch &&
+       grep "new file mode 100644" creation-patch &&
+
+       rm -f test-file &&
+       git diff >deletion-patch &&
+       grep "deleted file mode 100644" deletion-patch
+'
+
+test_expect_success 'apply creation patch to ita path (--cached)' '
+       git rm -f test-file &&
+       cat blueprint >test-file &&
+       git add -N test-file &&
+
+       git apply --cached creation-patch &&
+       git cat-file blob :test-file >actual &&
+       test_cmp blueprint actual
+'
+
+test_expect_success 'apply creation patch to ita path (--index)' '
+       git rm -f test-file &&
+       cat blueprint >test-file &&
+       git add -N test-file &&
+       rm -f test-file &&
+
+       test_must_fail git apply --index creation-patch
+'
+
+test_expect_success 'apply deletion patch to ita path (--cached)' '
+       git rm -f test-file &&
+       cat blueprint >test-file &&
+       git add -N test-file &&
+
+       git apply --cached deletion-patch &&
+       test_must_fail git ls-files --stage --error-unmatch test-file
+'
+
+test_expect_success 'apply deletion patch to ita path (--index)' '
+       cat blueprint >test-file &&
+       git add -N test-file &&
+
+       test_must_fail git apply --index deletion-patch &&
+       git ls-files --stage --error-unmatch test-file
+'
+
+test_done
index bda4586a7951a234b50ffbb28cdd4d7df05e4c56..1da8ab120b37a01fa02fdf12c55c11e38ce4fd31 100755 (executable)
@@ -989,7 +989,7 @@ test_expect_success 'am -s unexpected trailer block' '
        Signed-off-by: J C H <j@c.h>
        EOF
        git commit -F msg &&
-       git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
+       git cat-file commit HEAD | sed -e "1,/^$/d" >original &&
        git format-patch --stdout -1 >patch &&
 
        git reset --hard HEAD^ &&
@@ -998,7 +998,7 @@ test_expect_success 'am -s unexpected trailer block' '
                cat original &&
                echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
        ) >expect &&
-       git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
+       git cat-file commit HEAD | sed -e "1,/^$/d" >actual &&
        test_cmp expect actual &&
 
        cat >msg <<-\EOF &&
@@ -1009,7 +1009,7 @@ test_expect_success 'am -s unexpected trailer block' '
        EOF
        git reset HEAD^ &&
        git commit -F msg file &&
-       git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
+       git cat-file commit HEAD | sed -e "1,/^$/d" >original &&
        git format-patch --stdout -1 >patch &&
 
        git reset --hard HEAD^ &&
@@ -1020,7 +1020,7 @@ test_expect_success 'am -s unexpected trailer block' '
                echo &&
                echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
        ) >expect &&
-       git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
+       git cat-file commit HEAD | sed -e "1,/^$/d" >actual &&
        test_cmp expect actual
 '
 
@@ -1133,4 +1133,20 @@ test_expect_success 'am and .gitattibutes' '
        )
 '
 
+test_expect_success 'apply binary blob in partial clone' '
+       printf "\\000" >binary &&
+       git add binary &&
+       git commit -m "binary blob" &&
+       git format-patch --stdout -m HEAD^ >patch &&
+
+       test_create_repo server &&
+       test_config -C server uploadpack.allowfilter 1 &&
+       test_config -C server uploadpack.allowanysha1inwant 1 &&
+       git clone --filter=blob:none "file://$(pwd)/server" client &&
+       test_when_finished "rm -rf client" &&
+
+       # Exercise to make sure that it works
+       git -C client am ../patch
+'
+
 test_done
index 831d424c4720924275b9071d4ad5edf8fc73734a..b12b43e9e980f3c1fcdd032685a25f600bde169b 100755 (executable)
@@ -25,7 +25,6 @@ test_description='git rerere
 . ./test-lib.sh
 
 test_expect_success 'setup' '
-       test_oid_init &&
        cat >a1 <<-\EOF &&
        Some title
        ==========
@@ -364,7 +363,7 @@ test_expect_success 'set up an unresolved merge' '
        git reset --hard &&
        git checkout version2 &&
        fifth=$(git rev-parse fifth) &&
-       echo "$fifth            branch 'fifth' of ." |
+       echo "$fifth            branch fifth of ." |
        git fmt-merge-msg >msg &&
        ancestor=$(git merge-base version2 fifth) &&
        test_must_fail git merge-recursive "$ancestor" -- HEAD fifth &&
index fd9af658af20a8fc7de4836c57c0dad455d59e2b..a0930599aaa5b18915792c68c3f84b4b184bb27c 100755 (executable)
@@ -483,7 +483,7 @@ test_expect_success 'set up merge history' '
 '
 
 cat > expect <<\EOF
-*   Merge branch 'side' into master
+*   Merge branch 'side'
 |\
 | * side-2
 | * side-1
@@ -502,7 +502,7 @@ test_expect_success 'log --graph with merge' '
 '
 
 cat > expect <<\EOF
-| | | *   Merge branch 'side' into master
+| | | *   Merge branch 'side'
 | | | |\
 | | | | * side-2
 | | | | * side-1
@@ -521,7 +521,7 @@ test_expect_success 'log --graph --line-prefix="| | | " with merge' '
 '
 
 cat > expect.colors <<\EOF
-*   Merge branch 'side' into master
+*   Merge branch 'side'
 <BLUE>|<RESET><CYAN>\<RESET>
 <BLUE>|<RESET> * side-2
 <BLUE>|<RESET> * side-1
@@ -555,7 +555,7 @@ cat > expect <<\EOF
 |\  Merge: A B
 | | Author: A U Thor <author@example.com>
 | |
-| |     Merge branch 'side' into master
+| |     Merge branch 'side'
 | |
 | * commit tags/side-2
 | | Author: A U Thor <author@example.com>
@@ -632,11 +632,11 @@ test_expect_success 'set up more tangled history' '
 '
 
 cat > expect <<\EOF
-*   Merge tag 'reach' into master
+*   Merge tag 'reach'
 |\
 | \
 |  \
-*-. \   Merge tags 'octopus-a' and 'octopus-b' into master
+*-. \   Merge tags 'octopus-a' and 'octopus-b'
 |\ \ \
 * | | | seventh
 | | * | octopus-b
@@ -646,14 +646,14 @@ cat > expect <<\EOF
 |/ /
 | * reach
 |/
-*   Merge branch 'tangle' into master
+*   Merge branch 'tangle'
 |\
 | *   Merge branch 'side' (early part) into tangle
 | |\
 | * \   Merge branch 'master' (early part) into tangle
 | |\ \
 | * | | tangle-a
-* | | |   Merge branch 'side' into master
+* | | |   Merge branch 'side'
 |\ \ \ \
 | * | | | side-2
 | | |_|/
@@ -735,16 +735,16 @@ test_expect_success 'log.decorate configuration' '
 
 test_expect_success 'decorate-refs with glob' '
        cat >expect.decorate <<-\EOF &&
-       Merge-tag-reach-into-master
-       Merge-tags-octopus-a-and-octopus-b-into-master
+       Merge-tag-reach
+       Merge-tags-octopus-a-and-octopus-b
        seventh
        octopus-b (octopus-b)
        octopus-a (octopus-a)
        reach
        EOF
        cat >expect.no-decorate <<-\EOF &&
-       Merge-tag-reach-into-master
-       Merge-tags-octopus-a-and-octopus-b-into-master
+       Merge-tag-reach
+       Merge-tags-octopus-a-and-octopus-b
        seventh
        octopus-b
        octopus-a
@@ -765,8 +765,8 @@ test_expect_success 'decorate-refs with glob' '
 
 test_expect_success 'decorate-refs without globs' '
        cat >expect.decorate <<-\EOF &&
-       Merge-tag-reach-into-master
-       Merge-tags-octopus-a-and-octopus-b-into-master
+       Merge-tag-reach
+       Merge-tags-octopus-a-and-octopus-b
        seventh
        octopus-b
        octopus-a
@@ -779,8 +779,8 @@ test_expect_success 'decorate-refs without globs' '
 
 test_expect_success 'multiple decorate-refs' '
        cat >expect.decorate <<-\EOF &&
-       Merge-tag-reach-into-master
-       Merge-tags-octopus-a-and-octopus-b-into-master
+       Merge-tag-reach
+       Merge-tags-octopus-a-and-octopus-b
        seventh
        octopus-b (octopus-b)
        octopus-a (octopus-a)
@@ -794,8 +794,8 @@ test_expect_success 'multiple decorate-refs' '
 
 test_expect_success 'decorate-refs-exclude with glob' '
        cat >expect.decorate <<-\EOF &&
-       Merge-tag-reach-into-master (HEAD -> master)
-       Merge-tags-octopus-a-and-octopus-b-into-master
+       Merge-tag-reach (HEAD -> master)
+       Merge-tags-octopus-a-and-octopus-b
        seventh (tag: seventh)
        octopus-b (tag: octopus-b)
        octopus-a (tag: octopus-a)
@@ -811,8 +811,8 @@ test_expect_success 'decorate-refs-exclude with glob' '
 
 test_expect_success 'decorate-refs-exclude without globs' '
        cat >expect.decorate <<-\EOF &&
-       Merge-tag-reach-into-master (HEAD -> master)
-       Merge-tags-octopus-a-and-octopus-b-into-master
+       Merge-tag-reach (HEAD -> master)
+       Merge-tags-octopus-a-and-octopus-b
        seventh (tag: seventh)
        octopus-b (tag: octopus-b, octopus-b)
        octopus-a (tag: octopus-a, octopus-a)
@@ -828,8 +828,8 @@ test_expect_success 'decorate-refs-exclude without globs' '
 
 test_expect_success 'multiple decorate-refs-exclude' '
        cat >expect.decorate <<-\EOF &&
-       Merge-tag-reach-into-master (HEAD -> master)
-       Merge-tags-octopus-a-and-octopus-b-into-master
+       Merge-tag-reach (HEAD -> master)
+       Merge-tags-octopus-a-and-octopus-b
        seventh (tag: seventh)
        octopus-b (tag: octopus-b)
        octopus-a (tag: octopus-a)
@@ -851,8 +851,8 @@ test_expect_success 'multiple decorate-refs-exclude' '
 
 test_expect_success 'decorate-refs and decorate-refs-exclude' '
        cat >expect.no-decorate <<-\EOF &&
-       Merge-tag-reach-into-master (master)
-       Merge-tags-octopus-a-and-octopus-b-into-master
+       Merge-tag-reach (master)
+       Merge-tags-octopus-a-and-octopus-b
        seventh
        octopus-b
        octopus-a
@@ -866,8 +866,8 @@ test_expect_success 'decorate-refs and decorate-refs-exclude' '
 
 test_expect_success 'deocrate-refs and log.excludeDecoration' '
        cat >expect.decorate <<-\EOF &&
-       Merge-tag-reach-into-master (master)
-       Merge-tags-octopus-a-and-octopus-b-into-master
+       Merge-tag-reach (master)
+       Merge-tags-octopus-a-and-octopus-b
        seventh
        octopus-b (octopus-b)
        octopus-a (octopus-a)
@@ -881,10 +881,10 @@ test_expect_success 'deocrate-refs and log.excludeDecoration' '
 
 test_expect_success 'decorate-refs-exclude and simplify-by-decoration' '
        cat >expect.decorate <<-\EOF &&
-       Merge-tag-reach-into-master (HEAD -> master)
+       Merge-tag-reach (HEAD -> master)
        reach (tag: reach, reach)
        seventh (tag: seventh)
-       Merge-branch-tangle-into-master
+       Merge-branch-tangle
        Merge-branch-side-early-part-into-tangle (tangle)
        tangle-a (tag: tangle-a)
        EOF
@@ -1068,7 +1068,7 @@ cat >expect <<\EOF
 |\  Merge: MERGE_PARENTS
 | | Author: A U Thor <author@example.com>
 | |
-| |     Merge branch 'tangle' into master
+| |     Merge branch 'tangle'
 | |
 | *   commit COMMIT_OBJECT_NAME
 | |\  Merge: MERGE_PARENTS
@@ -1102,7 +1102,7 @@ cat >expect <<\EOF
 |\ \ \ \  Merge: MERGE_PARENTS
 | | | | | Author: A U Thor <author@example.com>
 | | | | |
-| | | | |     Merge branch 'side' into master
+| | | | |     Merge branch 'side'
 | | | | |
 | * | | | commit COMMIT_OBJECT_NAME
 | | |_|/  Author: A U Thor <author@example.com>
@@ -1343,7 +1343,7 @@ cat >expect <<\EOF
 *** |\  Merge: MERGE_PARENTS
 *** | | Author: A U Thor <author@example.com>
 *** | |
-*** | |     Merge branch 'tangle' into master
+*** | |     Merge branch 'tangle'
 *** | |
 *** | *   commit COMMIT_OBJECT_NAME
 *** | |\  Merge: MERGE_PARENTS
@@ -1377,7 +1377,7 @@ cat >expect <<\EOF
 *** |\ \ \ \  Merge: MERGE_PARENTS
 *** | | | | | Author: A U Thor <author@example.com>
 *** | | | | |
-*** | | | | |     Merge branch 'side' into master
+*** | | | | |     Merge branch 'side'
 *** | | | | |
 *** | * | | | commit COMMIT_OBJECT_NAME
 *** | | |_|/  Author: A U Thor <author@example.com>
@@ -1540,8 +1540,8 @@ cat >expect <<-\EOF
 * reach
 |
 | A    reach.t
-* Merge branch 'tangle' into master
-*   Merge branch 'side' into master
+* Merge branch 'tangle'
+*   Merge branch 'side'
 |\
 | * side-2
 |
@@ -1562,8 +1562,8 @@ cat >expect <<-\EOF
 * reach
 |
 | reach.t
-* Merge branch 'tangle' into master
-*   Merge branch 'side' into master
+* Merge branch 'tangle'
+*   Merge branch 'side'
 |\
 | * side-2
 |
index e186c8325043920cd4bfb79ab4fa2ce021dc7ac4..2d1d7b5d1938a05daa6a98359a2dfd5e1be645e2 100755 (executable)
@@ -4,7 +4,6 @@ test_description='test log -L'
 . ./test-lib.sh
 
 test_expect_success 'setup (import history)' '
-       test_oid_init &&
        git fast-import < "$TEST_DIRECTORY"/t4211/history.export &&
        git reset --hard
 '
index c855bcd3e7134cc23bb5b597b7d90608b1f4c504..4bb9e9dbe28bf22d86d7e4ef8629d4f73328d815 100755 (executable)
@@ -30,12 +30,17 @@ test_expect_success 'setup test - repo, commits, commit graph, log outputs' '
        rm file_to_be_deleted &&
        git add . &&
        git commit -m "file removed" &&
-       git commit-graph write --reachable --changed-paths
+       git commit-graph write --reachable --changed-paths &&
+
+       test_oid_cache <<-EOF
+       oid_version sha1:1
+       oid_version sha256:2
+       EOF
 '
 graph_read_expect () {
        NUM_CHUNKS=5
        cat >expect <<- EOF
-       header: 43475048 1 1 $NUM_CHUNKS 0
+       header: 43475048 1 $(test_oid oid_version) $NUM_CHUNKS 0
        num_commits: $1
        chunks: oid_fanout oid_lookup commit_metadata bloom_indexes bloom_data
        EOF
@@ -60,7 +65,7 @@ setup () {
 
 test_bloom_filters_used () {
        log_args=$1
-       bloom_trace_prefix="statistics:{\"filter_not_present\":0,\"zero_length_filter\":0,\"maybe\""
+       bloom_trace_prefix="statistics:{\"filter_not_present\":0,\"maybe\""
        setup "$log_args" &&
        grep -q "$bloom_trace_prefix" "$TRASH_DIRECTORY/trace.perf" &&
        test_cmp log_wo_bloom log_w_bloom &&
@@ -112,6 +117,10 @@ test_expect_success 'git log -- multiple path specs does not use Bloom filters'
        test_bloom_filters_not_used "-- file4 A/file1"
 '
 
+test_expect_success 'git log -- "." pathspec at root does not use Bloom filters' '
+       test_bloom_filters_not_used "-- ."
+'
+
 test_expect_success 'git log with wildcard that resolves to a single path uses Bloom filters' '
        test_bloom_filters_used "-- *4" &&
        test_bloom_filters_used "-- *renamed"
@@ -126,7 +135,7 @@ test_expect_success 'setup - add commit-graph to the chain without Bloom filters
        test_commit c14 A/anotherFile2 &&
        test_commit c15 A/B/anotherFile2 &&
        test_commit c16 A/B/C/anotherFile2 &&
-       GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0 git commit-graph write --reachable --split &&
+       git commit-graph write --reachable --split --no-changed-paths &&
        test_line_count = 2 .git/objects/info/commit-graphs/commit-graph-chain
 '
 
@@ -142,7 +151,7 @@ test_expect_success 'setup - add commit-graph to the chain with Bloom filters' '
 
 test_bloom_filters_used_when_some_filters_are_missing () {
        log_args=$1
-       bloom_trace_prefix="statistics:{\"filter_not_present\":3,\"zero_length_filter\":0,\"maybe\":8,\"definitely_not\":6"
+       bloom_trace_prefix="statistics:{\"filter_not_present\":3,\"maybe\":6,\"definitely_not\":8"
        setup "$log_args" &&
        grep -q "$bloom_trace_prefix" "$TRASH_DIRECTORY/trace.perf" &&
        test_cmp log_wo_bloom log_w_bloom
@@ -152,4 +161,39 @@ test_expect_success 'Use Bloom filters if they exist in the latest but not all c
        test_bloom_filters_used_when_some_filters_are_missing "-- A/B"
 '
 
+test_expect_success 'persist filter settings' '
+       test_when_finished rm -rf .git/objects/info/commit-graph* &&
+       rm -rf .git/objects/info/commit-graph* &&
+       GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+               GIT_TRACE2_EVENT_NESTING=5 \
+               GIT_TEST_BLOOM_SETTINGS_NUM_HASHES=9 \
+               GIT_TEST_BLOOM_SETTINGS_BITS_PER_ENTRY=15 \
+               git commit-graph write --reachable --changed-paths &&
+       grep "{\"hash_version\":1,\"num_hashes\":9,\"bits_per_entry\":15}" trace2.txt &&
+       GIT_TRACE2_EVENT="$(pwd)/trace2-auto.txt" \
+               GIT_TRACE2_EVENT_NESTING=5 \
+               git commit-graph write --reachable --changed-paths &&
+       grep "{\"hash_version\":1,\"num_hashes\":9,\"bits_per_entry\":15}" trace2-auto.txt
+'
+
+test_expect_success 'correctly report changes over limit' '
+       git init 513changes &&
+       (
+               cd 513changes &&
+               for i in $(test_seq 1 513)
+               do
+                       echo $i >file$i.txt || return 1
+               done &&
+               git add . &&
+               git commit -m "files" &&
+               git commit-graph write --reachable --changed-paths &&
+               for i in $(test_seq 1 513)
+               do
+                       git -c core.commitGraph=false log -- file$i.txt >expect &&
+                       git log -- file$i.txt >actual &&
+                       test_cmp expect actual || return 1
+               done
+       )
+'
+
 test_done
index 746cdb626e293f840a9e3f910ec5d421a67fb9ca..3d6a93343adc6b14d096f6b42e5b9548bf1f0e55 100755 (executable)
@@ -12,8 +12,7 @@ TRASH=$(pwd)
 
 test_expect_success \
     'setup' \
-    'test_oid_init &&
-     rm -f .git/index* &&
+    'rm -f .git/index* &&
      perl -e "print \"a\" x 4096;" > a &&
      perl -e "print \"b\" x 4096;" > b &&
      perl -e "print \"c\" x 4096;" > c &&
@@ -497,4 +496,40 @@ test_expect_success 'make sure index-pack detects the SHA1 collision (large blob
        )
 '
 
+test_expect_success 'prefetch objects' '
+       rm -rf server client &&
+
+       git init server &&
+       test_config -C server uploadpack.allowanysha1inwant 1 &&
+       test_config -C server uploadpack.allowfilter 1 &&
+       test_config -C server protocol.version 2 &&
+
+       echo one >server/one &&
+       git -C server add one &&
+       git -C server commit -m one &&
+       git -C server branch one_branch &&
+
+       echo two_a >server/two_a &&
+       echo two_b >server/two_b &&
+       git -C server add two_a two_b &&
+       git -C server commit -m two &&
+
+       echo three >server/three &&
+       git -C server add three &&
+       git -C server commit -m three &&
+       git -C server branch three_branch &&
+
+       # Clone, fetch "two" with blobs excluded, and re-push it. This requires
+       # the client to have the blobs of "two" - verify that these are
+       # prefetched in one batch.
+       git clone --filter=blob:none --single-branch -b one_branch \
+               "file://$(pwd)/server" client &&
+       test_config -C client protocol.version 2 &&
+       TWO=$(git -C server rev-parse three_branch^) &&
+       git -C client fetch --filter=blob:none origin "$TWO" &&
+       GIT_TRACE_PACKET=$(pwd)/trace git -C client push origin "$TWO":refs/heads/two_branch &&
+       grep "git> done" trace >donelines &&
+       test_line_count = 1 donelines
+'
+
 test_done
index 8981c9b90ebe1512c22402dd32308f0415708f21..c92e553a2f87d59f73f2dc8bf52bd256713241db 100755 (executable)
@@ -7,7 +7,6 @@ test_description='pack index with 64-bit offsets and object CRC'
 . ./test-lib.sh
 
 test_expect_success 'setup' '
-       test_oid_init &&
        rawsz=$(test_oid rawsz) &&
        rm -rf .git &&
        git init &&
@@ -15,7 +14,7 @@ test_expect_success 'setup' '
        i=1 &&
        while test $i -le 100
        do
-               iii=$(printf '%03i' $i)
+               iii=$(printf "%03i" $i)
                test-tool genrandom "bar" 200 > wide_delta_$iii &&
                test-tool genrandom "baz $iii" 50 >> wide_delta_$iii &&
                test-tool genrandom "foo"$i 100 > deep_delta_$iii &&
index 6845c1f3c3a3acc4540e1340627240d90d7bb145..693b2411c89929b7cf3b765419c1f8db96554636 100755 (executable)
@@ -4,23 +4,27 @@ test_description='handling of duplicate objects in incoming packfiles'
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-pack.sh
 
-if ! test_have_prereq SHA1
-then
-       skip_all='not using SHA-1 for objects'
-       test_done
-fi
+test_expect_success 'setup' '
+       test_oid_cache <<-EOF
+       lo_oid sha1:e68fe8129b546b101aee9510c5328e7f21ca1d18
+       lo_oid sha256:471819e8c52bf11513f100b2810a8aa0622d5cd3d1c913758a071dd4b3bad8fe
+
+       missing_oid sha1:e69d000000000000000000000000000000000000
+       missing_oid sha256:4720000000000000000000000000000000000000000000000000000000000000
+       EOF
+'
 
 # The sha1s we have in our pack. It's important that these have the same
 # starting byte, so that they end up in the same fanout section of the index.
 # That lets us make sure we are exercising the binary search with both sets.
-LO_SHA1=e68fe8129b546b101aee9510c5328e7f21ca1d18
-HI_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
+LO_SHA1=$(test_oid lo_oid)
+HI_SHA1=$EMPTY_BLOB
 
 # And here's a "missing sha1" which will produce failed lookups. It must also
 # be in the same fanout section, and should be between the two (so that during
 # our binary search, we are sure to end up looking at one or the other of the
 # duplicate runs).
-MISSING_SHA1='e69d000000000000000000000000000000000000'
+MISSING_SHA1=$(test_oid missing_oid)
 
 # git will never intentionally create packfiles with
 # duplicate objects, so we have to construct them by hand.
index 2a4557efc2d6f3876d0b52f97267db643e81edab..535313e4dc8469ba9a4dc79eb75ae1f6e58cd2b0 100755 (executable)
@@ -45,7 +45,6 @@ extended_table () {
 }
 
 test_expect_success 'setup' '
-       test_oid_init &&
        test_oid_cache <<-EOF
        oid000 sha1:1485
        oid000 sha256:4222
index 26f332d6a31fcecfe8723a6c603ab224462c9ec8..2ed0c1544da120c10db3afedb656429f12a45613 100755 (executable)
@@ -11,7 +11,11 @@ test_expect_success 'setup full repo' '
        git init &&
        git config core.commitGraph true &&
        objdir=".git/objects" &&
-       test_oid_init
+
+       test_oid_cache <<-EOF
+       oid_version sha1:1
+       oid_version sha256:2
+       EOF
 '
 
 test_expect_success POSIXPERM 'tweak umask for modebit tests' '
@@ -78,7 +82,7 @@ graph_read_expect() {
                NUM_CHUNKS=$((3 + $(echo "$2" | wc -w)))
        fi
        cat >expect <<- EOF
-       header: 43475048 1 1 $NUM_CHUNKS 0
+       header: 43475048 1 $(test_oid oid_version) $NUM_CHUNKS 0
        num_commits: $1
        chunks: oid_fanout oid_lookup commit_metadata$OPTIONAL
        EOF
@@ -413,6 +417,35 @@ test_expect_success 'replace-objects invalidates commit-graph' '
        )
 '
 
+test_expect_success 'warn on improper hash version' '
+       git init --object-format=sha1 sha1 &&
+       (
+               cd sha1 &&
+               test_commit 1 &&
+               git commit-graph write --reachable &&
+               mv .git/objects/info/commit-graph ../cg-sha1
+       ) &&
+       git init --object-format=sha256 sha256 &&
+       (
+               cd sha256 &&
+               test_commit 1 &&
+               git commit-graph write --reachable &&
+               mv .git/objects/info/commit-graph ../cg-sha256
+       ) &&
+       (
+               cd sha1 &&
+               mv ../cg-sha256 .git/objects/info/commit-graph &&
+               git log -1 2>err &&
+               test_i18ngrep "commit-graph hash version 2 does not match version 1" err
+       ) &&
+       (
+               cd sha256 &&
+               mv ../cg-sha1 .git/objects/info/commit-graph &&
+               git log -1 2>err &&
+               test_i18ngrep "commit-graph hash version 1 does not match version 2" err
+       )
+'
+
 # the verify tests below expect the commit-graph to contain
 # exactly the commits reachable from the commits/8 branch.
 # If the file changes the set of commits in the list, then the
@@ -476,7 +509,7 @@ corrupt_graph_verify() {
                cp $objdir/info/commit-graph commit-graph-pre-write-test
        fi &&
        git status --short &&
-       GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD=true git commit-graph write &&
+       GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE=true git commit-graph write &&
        chmod u+w $objdir/info/commit-graph &&
        git commit-graph verify
 }
@@ -529,7 +562,7 @@ test_expect_success 'detect bad hash version' '
 '
 
 test_expect_success 'detect low chunk count' '
-       corrupt_graph_and_verify $GRAPH_BYTE_CHUNK_COUNT "\02" \
+       corrupt_graph_and_verify $GRAPH_BYTE_CHUNK_COUNT "\01" \
                "missing the .* chunk"
 '
 
@@ -615,7 +648,8 @@ test_expect_success 'detect invalid checksum hash' '
 
 test_expect_success 'detect incorrect chunk count' '
        corrupt_graph_and_verify $GRAPH_BYTE_CHUNK_COUNT "\377" \
-               "chunk lookup table entry missing" $GRAPH_CHUNK_LOOKUP_OFFSET
+               "commit-graph file is too small to hold [0-9]* chunks" \
+               $GRAPH_CHUNK_LOOKUP_OFFSET
 '
 
 test_expect_success 'git fsck (checks commit-graph)' '
index 7214cab36c0f74ef4c731a189b2490c14a2fa6e4..43b1b5b2af6e978f5dc84543f5be1707941a2d38 100755 (executable)
@@ -5,6 +5,8 @@ test_description='multi-pack-indexes'
 
 objdir=.git/objects
 
+HASH_LEN=$(test_oid rawsz)
+
 midx_read_expect () {
        NUM_PACKS=$1
        NUM_OBJECTS=$2
@@ -13,7 +15,7 @@ midx_read_expect () {
        EXTRA_CHUNKS="$5"
        {
                cat <<-EOF &&
-               header: 4d494458 1 $NUM_CHUNKS $NUM_PACKS
+               header: 4d494458 1 $HASH_LEN $NUM_CHUNKS $NUM_PACKS
                chunks: pack-names oid-fanout oid-lookup object-offsets$EXTRA_CHUNKS
                num_objects: $NUM_OBJECTS
                packs:
@@ -29,7 +31,6 @@ midx_read_expect () {
 }
 
 test_expect_success 'setup' '
-       test_oid_init &&
        test_oid_cache <<-EOF
        idxoff sha1:2999
        idxoff sha256:3739
@@ -47,7 +48,7 @@ test_expect_success "don't write midx with no packs" '
        test_path_is_missing pack/multi-pack-index
 '
 
-test_expect_success "Warn if a midx contains no oid" '
+test_expect_success SHA1 'warn if a midx contains no oid' '
        cp "$TEST_DIRECTORY"/t5319/no-objects.midx $objdir/pack/multi-pack-index &&
        test_must_fail git multi-pack-index verify &&
        rm $objdir/pack/multi-pack-index
@@ -199,6 +200,40 @@ test_expect_success 'write midx with twelve packs' '
 
 compare_results_with_midx "twelve packs"
 
+test_expect_success 'warn on improper hash version' '
+       git init --object-format=sha1 sha1 &&
+       (
+               cd sha1 &&
+               git config core.multiPackIndex true &&
+               test_commit 1 &&
+               git repack -a &&
+               git multi-pack-index write &&
+               mv .git/objects/pack/multi-pack-index ../mpi-sha1
+       ) &&
+       git init --object-format=sha256 sha256 &&
+       (
+               cd sha256 &&
+               git config core.multiPackIndex true &&
+               test_commit 1 &&
+               git repack -a &&
+               git multi-pack-index write &&
+               mv .git/objects/pack/multi-pack-index ../mpi-sha256
+       ) &&
+       (
+               cd sha1 &&
+               mv ../mpi-sha256 .git/objects/pack/multi-pack-index &&
+               git log -1 2>err &&
+               test_i18ngrep "multi-pack-index hash version 2 does not match version 1" err
+       ) &&
+       (
+               cd sha256 &&
+               mv ../mpi-sha1 .git/objects/pack/multi-pack-index &&
+               git log -1 2>err &&
+               test_i18ngrep "multi-pack-index hash version 1 does not match version 2" err
+       )
+'
+
+
 test_expect_success 'verify multi-pack-index success' '
        git multi-pack-index verify --object-dir=$objdir
 '
@@ -244,7 +279,6 @@ test_expect_success 'verify bad signature' '
                "multi-pack-index signature"
 '
 
-HASH_LEN=$(test_oid rawsz)
 NUM_OBJECTS=74
 MIDX_BYTE_VERSION=4
 MIDX_BYTE_OID_VERSION=5
@@ -273,7 +307,7 @@ test_expect_success 'verify bad version' '
 '
 
 test_expect_success 'verify bad OID version' '
-       corrupt_midx_and_verify $MIDX_BYTE_OID_VERSION "\02" $objdir \
+       corrupt_midx_and_verify $MIDX_BYTE_OID_VERSION "\03" $objdir \
                "hash version"
 '
 
@@ -643,6 +677,7 @@ test_expect_success 'expire respects .keep files' '
 '
 
 test_expect_success 'repack --batch-size=0 repacks everything' '
+       cp -r dup dup2 &&
        (
                cd dup &&
                rm .git/objects/pack/*.keep &&
@@ -662,4 +697,21 @@ test_expect_success 'repack --batch-size=0 repacks everything' '
        )
 '
 
+test_expect_success 'repack --batch-size=<large> repacks everything' '
+       (
+               cd dup2 &&
+               rm .git/objects/pack/*.keep &&
+               ls .git/objects/pack/*idx >idx-list &&
+               test_line_count = 2 idx-list &&
+               git multi-pack-index repack --batch-size=2000000 &&
+               ls .git/objects/pack/*idx >idx-list &&
+               test_line_count = 3 idx-list &&
+               test-tool read-midx .git/objects | grep idx >midx-list &&
+               test_line_count = 3 midx-list &&
+               git multi-pack-index expire &&
+               ls -al .git/objects/pack/*idx >idx-list &&
+               test_line_count = 1 idx-list
+       )
+'
+
 test_done
index 269d0964a3e0b51bceffe0362f45f5c0a8bd229c..18216463c7db99e965833788ccd990f1e8515397 100755 (executable)
@@ -12,13 +12,15 @@ test_expect_success 'setup repo' '
        git config gc.writeCommitGraph false &&
        infodir=".git/objects/info" &&
        graphdir="$infodir/commit-graphs" &&
-       test_oid_init &&
        test_oid_cache <<-EOM
        shallow sha1:1760
        shallow sha256:2064
 
        base sha1:1376
        base sha256:1496
+
+       oid_version sha1:1
+       oid_version sha256:2
        EOM
 '
 
@@ -29,7 +31,7 @@ graph_read_expect() {
                NUM_BASE=$2
        fi
        cat >expect <<- EOF
-       header: 43475048 1 1 3 $NUM_BASE
+       header: 43475048 1 $(test_oid oid_version) 3 $NUM_BASE
        num_commits: $1
        chunks: oid_fanout oid_lookup commit_metadata
        EOF
@@ -399,7 +401,7 @@ test_expect_success ULIMIT_FILE_DESCRIPTORS 'handles file descriptor exhaustion'
                for i in $(test_seq 64)
                do
                        test_commit $i &&
-                       test_might_fail run_with_limited_open_files git commit-graph write \
+                       run_with_limited_open_files test_might_fail git commit-graph write \
                                --split=no-merge --reachable || return 1
                done
        )
index a32efe2b6cdd84690bdb5193609105204ff1dd39..1a16ac4c0dba9dde67230e15151c327ba9c916ed 100755 (executable)
@@ -4,7 +4,6 @@ test_description='fetch/receive strict mode'
 . ./test-lib.sh
 
 test_expect_success 'setup and inject "corrupt or missing" object' '
-       test_oid_init &&
        echo hello >greetings &&
        git add greetings &&
        git commit -m greetings &&
index a66dbe0bde0df2851c3736d193707ec7c36bd429..2a1abe91f0fd34b7929aa636ab43542c6e45ea54 100755 (executable)
@@ -213,7 +213,7 @@ test_expect_success 'fetch tags when there is no tags' '
 test_expect_success 'fetch following tags' '
 
        cd "$D" &&
-       git tag -a -m 'annotated' anno HEAD &&
+       git tag -a -m "annotated" anno HEAD &&
        git tag light HEAD &&
 
        mkdir four &&
@@ -281,15 +281,19 @@ test_expect_success 'create bundle 1' '
        cd "$D" &&
        echo >file updated again by origin &&
        git commit -a -m "tip" &&
-       git bundle create bundle1 master^..master
+       git bundle create --version=3 bundle1 master^..master
 '
 
 test_expect_success 'header of bundle looks right' '
-       head -n 4 "$D"/bundle1 &&
-       head -n 1 "$D"/bundle1 | grep "^#" &&
-       head -n 2 "$D"/bundle1 | grep "^-$OID_REGEX " &&
-       head -n 3 "$D"/bundle1 | grep "^$OID_REGEX " &&
-       head -n 4 "$D"/bundle1 | grep "^$"
+       cat >expect <<-EOF &&
+       # v3 git bundle
+       @object-format=$(test_oid algo)
+       -OID updated by origin
+       OID refs/heads/master
+
+       EOF
+       sed -e "s/$OID_REGEX/OID/g" -e "5q" "$D"/bundle1 >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success 'create bundle 2' '
@@ -331,7 +335,7 @@ test_expect_success 'bundle does not prerequisite objects' '
 test_expect_success 'bundle should be able to create a full history' '
 
        cd "$D" &&
-       git tag -a -m '1.0' v1.0 master &&
+       git tag -a -m "1.0" v1.0 master &&
        git bundle create bundle4 v1.0
 
 '
@@ -539,13 +543,24 @@ test_expect_success 'fetch into the current branch with --update-head-ok' '
 
 '
 
-test_expect_success 'fetch --dry-run' '
-
+test_expect_success 'fetch --dry-run does not touch FETCH_HEAD' '
        rm -f .git/FETCH_HEAD &&
        git fetch --dry-run . &&
        ! test -f .git/FETCH_HEAD
 '
 
+test_expect_success '--no-write-fetch-head does not touch FETCH_HEAD' '
+       rm -f .git/FETCH_HEAD &&
+       git fetch --no-write-fetch-head . &&
+       ! test -f .git/FETCH_HEAD
+'
+
+test_expect_success '--write-fetch-head gets defeated by --dry-run' '
+       rm -f .git/FETCH_HEAD &&
+       git fetch --dry-run --write-fetch-head . &&
+       ! test -f .git/FETCH_HEAD
+'
+
 test_expect_success "should be able to fetch with duplicate refspecs" '
        mkdir dups &&
        (
@@ -797,7 +812,7 @@ test_configured_prune true  true  unset unset pruned pruned \
        "--prune origin refs/tags/*:refs/tags/* +refs/heads/*:refs/remotes/origin/*"
 
 # --prune-tags on its own does nothing, needs --prune as well, same
-# for for fetch.pruneTags without fetch.prune
+# for fetch.pruneTags without fetch.prune
 test_configured_prune unset unset unset unset kept kept     "--prune-tags"
 test_configured_prune unset unset true unset  kept kept     ""
 test_configured_prune unset unset unset true  kept kept     ""
index 159afa7ac81396e1d9915335f030cd0fcc8b7b3f..db1a381cd91c3470b7007b747e3b3a82f4da162f 100755 (executable)
@@ -85,6 +85,13 @@ test_expect_success 'git pull --cleanup errors early on invalid argument' '
        test -s err)
 '
 
+test_expect_success 'git pull --no-write-fetch-head fails' '
+       mkdir clonedwfh &&
+       (cd clonedwfh && git init &&
+       test_expect_code 129 git pull --no-write-fetch-head "../parent" >out 2>err &&
+       test_must_be_empty out &&
+       test_i18ngrep "no-write-fetch-head" err)
+'
 
 test_expect_success 'git pull --force' '
        mkdir clonedoldstyle &&
index 4ce9a9f7041112e49061acf14e0a51076ba770d2..205a2631e7f807a72259b27eb689a0b18439d7f9 100755 (executable)
@@ -14,7 +14,6 @@ corrupt_repo () {
 }
 
 test_expect_success 'setup and corrupt repository' '
-       test_oid_init &&
        echo file >file &&
        git add file &&
        git rev-parse :file &&
index c0d02dee893fc5466c36ce105b5a029ae66c7845..82aa99ae870e4064db0e335b43233ddd2b0e7173 100755 (executable)
@@ -9,10 +9,12 @@ start_httpd
 commit() {
        echo "$1" >tracked &&
        git add tracked &&
+       test_tick &&
        git commit -m "$1"
 }
 
 test_expect_success 'setup shallow clone' '
+       test_tick=1500000000 &&
        commit 1 &&
        commit 2 &&
        commit 3 &&
@@ -48,7 +50,6 @@ EOF
 test_expect_success 'no shallow lines after receiving ACK ready' '
        (
                cd shallow &&
-               test_tick &&
                for i in $(test_seq 15)
                do
                        git checkout --orphan unrelated$i &&
@@ -66,6 +67,7 @@ test_expect_success 'no shallow lines after receiving ACK ready' '
        (
                cd clone &&
                git checkout --orphan newnew &&
+               test_tick=1400000000 &&
                test_commit new-too &&
                # NEEDSWORK: If the overspecification of the expected result is reduced, we
                # might be able to run this test in all protocol versions.
index 463d0f12e5bfcaf79dd5972ecc6fc410a706e148..187454f5dd93f412075a9744a33585744455107f 100755 (executable)
@@ -479,6 +479,21 @@ test_expect_success 'clone/fetch scrubs password from reflogs' '
        ! grep "$HTTPD_URL_USER_PASS" reflog
 '
 
+test_expect_success 'Non-ASCII branch name can be used with --force-with-lease' '
+       cd "$ROOT_PATH" &&
+       git clone "$HTTPD_URL_USER_PASS/smart/test_repo.git" non-ascii &&
+       cd non-ascii &&
+       git checkout -b rama-de-árbol &&
+       test_commit F &&
+       git push --force-with-lease origin rama-de-árbol &&
+       git ls-remote origin refs/heads/rama-de-árbol >actual &&
+       git ls-remote . refs/heads/rama-de-árbol >expect &&
+       test_cmp expect actual &&
+       git push --delete --force-with-lease origin rama-de-árbol &&
+       git ls-remote origin refs/heads/rama-de-árbol >actual &&
+       test_must_be_empty actual
+'
+
 test_expect_success 'colorize errors/hints' '
        cd "$ROOT_PATH"/test_repo_clone &&
        test_must_fail git -c color.transport=always -c color.advice=always \
index 81975ad8f9ebcbe22d5066da228e333e2cd613df..7622981cbf25941260f5a7f21bd60f84cf8797f8 100755 (executable)
@@ -81,7 +81,7 @@ test_expect_success 'fetch --set-upstream http://nosuchdomain.example.com fails
 
 test_expect_success 'fetch --set-upstream with valid URL sets upstream to URL' '
        clear_config other other2 &&
-       url="file://'"$PWD"'" &&
+       url="file://$PWD" &&
        git fetch --set-upstream "$url" &&
        check_config master "$url" HEAD &&
        check_config_missing other &&
@@ -158,7 +158,7 @@ test_expect_success 'pull --set-upstream upstream with more than one branch does
 test_expect_success 'pull --set-upstream with valid URL sets upstream to URL' '
        clear_config master other other2 &&
        git checkout master &&
-       url="file://'"$PWD"'" &&
+       url="file://$PWD" &&
        git pull --set-upstream "$url" &&
        check_config master "$url" HEAD &&
        check_config_missing other &&
@@ -168,7 +168,7 @@ test_expect_success 'pull --set-upstream with valid URL sets upstream to URL' '
 test_expect_success 'pull --set-upstream with valid URL and branch sets branch' '
        clear_config master other other2 &&
        git checkout master &&
-       url="file://'"$PWD"'" &&
+       url="file://$PWD" &&
        git pull --set-upstream "$url" master &&
        check_config master "$url" refs/heads/master &&
        check_config_missing other &&
index c6ec625497db44eb6a04d8b6a91e3cf99fe86a02..e5d3d15ba8dddaf98eeabcc909a726c77224afab 100755 (executable)
@@ -46,7 +46,6 @@ ssize_b100dots() {
 }
 
 test_expect_success 'setup' '
-       test_oid_init &&
        HTTP_CONTENT_ENCODING="identity" &&
        export HTTP_CONTENT_ENCODING &&
        git config http.receivepack true &&
index 84ea2a3eb707a7405d7fc3c5267f8bfff06abd18..eb9a093e25fadce8f8e6964e1e4b208256419cad 100755 (executable)
@@ -271,7 +271,9 @@ test_expect_success 'fetch from gitfile parent' '
 
 test_expect_success 'clone separate gitdir where target already exists' '
        rm -rf dst &&
-       test_must_fail git clone --separate-git-dir realgitdir src dst
+       echo foo=bar >>realgitdir/config &&
+       test_must_fail git clone --separate-git-dir realgitdir src dst &&
+       grep foo=bar realgitdir/config
 '
 
 test_expect_success 'clone --reference from original' '
index 6d5a977fcba60f70d2a7329eba4c70e7ac66e925..26985f4b44945f6680bfe2f65fb23d2c89407b6c 100755 (executable)
@@ -4,6 +4,10 @@ test_description='some bundle related tests'
 . ./test-lib.sh
 
 test_expect_success 'setup' '
+       test_oid_cache <<-EOF &&
+       version sha1:2
+       version sha256:3
+       EOF
        test_commit initial &&
        test_tick &&
        git tag -m tag tag &&
@@ -94,4 +98,31 @@ test_expect_success 'fetch SHA-1 from bundle' '
        git fetch --no-tags foo/tip.bundle "$(cat hash)"
 '
 
+test_expect_success 'git bundle uses expected default format' '
+       git bundle create bundle HEAD^.. &&
+       head -n1 bundle | grep "^# v$(test_oid version) git bundle$"
+'
+
+test_expect_success 'git bundle v3 has expected contents' '
+       git branch side HEAD &&
+       git bundle create --version=3 bundle HEAD^..side &&
+       head -n2 bundle >actual &&
+       cat >expect <<-EOF &&
+       # v3 git bundle
+       @object-format=$(test_oid algo)
+       EOF
+       test_cmp expect actual &&
+       git bundle verify bundle
+'
+
+test_expect_success 'git bundle v3 rejects unknown capabilities' '
+       cat >new <<-EOF &&
+       # v3 git bundle
+       @object-format=$(test_oid algo)
+       @unknown=silly
+       EOF
+       test_must_fail git bundle verify new 2>output &&
+       test_i18ngrep "unknown capability .unknown=silly." output
+'
+
 test_done
index 8a27452a51159b51922ff64fffab4b801a20b9db..5a01466db4837e1f80aac7236cd3a71e5aaee03d 100755 (executable)
@@ -163,6 +163,22 @@ test_expect_success 'manual prefetch of missing objects' '
        test_line_count = 0 observed.oids
 '
 
+test_expect_success 'partial clone with transfer.fsckobjects=1 works with submodules' '
+       test_create_repo submodule &&
+       test_commit -C submodule mycommit &&
+
+       test_create_repo src_with_sub &&
+       test_config -C src_with_sub uploadpack.allowfilter 1 &&
+       test_config -C src_with_sub uploadpack.allowanysha1inwant 1 &&
+
+       git -C src_with_sub submodule add "file://$(pwd)/submodule" mysub &&
+       git -C src_with_sub commit -m "commit with submodule" &&
+
+       git -c transfer.fsckobjects=1 \
+               clone --filter="blob:none" "file://$(pwd)/src_with_sub" dst &&
+       test_when_finished rm -rf dst
+'
+
 test_expect_success 'partial clone with transfer.fsckobjects=1 uses index-pack --fsck-objects' '
        git init src &&
        test_commit -C src x &&
@@ -235,6 +251,39 @@ test_expect_success 'implicitly construct combine: filter with repeated flags' '
        test_cmp unique_types.expected unique_types.actual
 '
 
+test_expect_success 'upload-pack fails banned object filters' '
+       test_config -C srv.bare uploadpackfilter.blob:none.allow false &&
+       test_must_fail ok=sigpipe git clone --no-checkout --filter=blob:none \
+               "file://$(pwd)/srv.bare" pc3 2>err &&
+       test_i18ngrep "filter '\''blob:none'\'' not supported" err
+'
+
+test_expect_success 'upload-pack fails banned combine object filters' '
+       test_config -C srv.bare uploadpackfilter.allow false &&
+       test_config -C srv.bare uploadpackfilter.combine.allow true &&
+       test_config -C srv.bare uploadpackfilter.tree.allow true &&
+       test_config -C srv.bare uploadpackfilter.blob:none.allow false &&
+       test_must_fail ok=sigpipe git clone --no-checkout --filter=tree:1 \
+               --filter=blob:none "file://$(pwd)/srv.bare" pc3 2>err &&
+       test_i18ngrep "filter '\''blob:none'\'' not supported" err
+'
+
+test_expect_success 'upload-pack fails banned object filters with fallback' '
+       test_config -C srv.bare uploadpackfilter.allow false &&
+       test_must_fail ok=sigpipe git clone --no-checkout --filter=blob:none \
+               "file://$(pwd)/srv.bare" pc3 2>err &&
+       test_i18ngrep "filter '\''blob:none'\'' not supported" err
+'
+
+test_expect_success 'upload-pack limits tree depth filters' '
+       test_config -C srv.bare uploadpackfilter.allow false &&
+       test_config -C srv.bare uploadpackfilter.tree.allow true &&
+       test_config -C srv.bare uploadpackfilter.tree.maxDepth 0 &&
+       test_must_fail ok=sigpipe git clone --no-checkout --filter=tree:1 \
+               "file://$(pwd)/srv.bare" pc3 2>err &&
+       test_i18ngrep "tree filter allows max depth 0, but got 1" err
+'
+
 test_expect_success 'partial clone fetches blobs pointed to by refs even if normally filtered out' '
        rm -rf src dst &&
        git init src &&
@@ -422,6 +471,44 @@ test_expect_success 'single-branch tag following respects partial clone' '
        test_must_fail git -C single rev-parse --verify refs/tags/C
 '
 
+test_expect_success 'fetch from a partial clone, protocol v0' '
+       rm -rf server client trace &&
+
+       # Pretend that the server is a partial clone
+       git init server &&
+       git -C server remote add a_remote "file://$(pwd)/" &&
+       test_config -C server core.repositoryformatversion 1 &&
+       test_config -C server extensions.partialclone a_remote &&
+       test_config -C server protocol.version 0 &&
+       test_commit -C server foo &&
+
+       # Fetch from the server
+       git init client &&
+       test_config -C client protocol.version 0 &&
+       test_commit -C client bar &&
+       GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch "file://$(pwd)/server" &&
+       ! grep "version 2" trace
+'
+
+test_expect_success 'fetch from a partial clone, protocol v2' '
+       rm -rf server client trace &&
+
+       # Pretend that the server is a partial clone
+       git init server &&
+       git -C server remote add a_remote "file://$(pwd)/" &&
+       test_config -C server core.repositoryformatversion 1 &&
+       test_config -C server extensions.partialclone a_remote &&
+       test_config -C server protocol.version 2 &&
+       test_commit -C server foo &&
+
+       # Fetch from the server
+       git init client &&
+       test_config -C client protocol.version 2 &&
+       test_commit -C client bar &&
+       GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch "file://$(pwd)/server" &&
+       grep "version 2" trace
+'
+
 . "$TEST_DIRECTORY"/lib-httpd.sh
 start_httpd
 
index 1b54c35b01792f85e791f6d4614f25d543c47dfd..5a60fbe3edb3b00ad61995ab7dee309777d6ba3e 100755 (executable)
@@ -13,7 +13,6 @@ start_git_daemon --export-all --enable=receive-pack
 daemon_parent=$GIT_DAEMON_DOCUMENT_ROOT_PATH/parent
 
 test_expect_success 'create repo to be served by git-daemon' '
-       test_oid_init &&
        git init "$daemon_parent" &&
        test_commit -C "$daemon_parent" one
 '
@@ -829,7 +828,7 @@ test_expect_success 'part of packfile response provided as URI' '
        # Ensure that my-blob and other-blob are in separate packfiles.
        for idx in http_child/.git/objects/pack/*.idx
        do
-               git verify-pack --verbose $idx >out &&
+               git verify-pack --object-format=$(test_oid algo) --verbose $idx >out &&
                {
                        grep "^[0-9a-f]\{16,\} " out || :
                } >out.objectlist &&
index 748282f058cbb996e1ecd694f861851d56365267..d9ecf0f4a95e2ef2bb43ee7816ee83a5c23b0b03 100755 (executable)
@@ -43,7 +43,6 @@ write_command () {
 #             \ | /
 #               a
 test_expect_success 'setup repository' '
-       test_oid_init &&
        test_commit a &&
        git checkout -b o/foo &&
        test_commit b &&
index 3dc1ad8f719926140ce31a9528c8f870977484b1..fc4d55dcb2e28d34b9a971f59872d30dfc87afcd 100755 (executable)
@@ -8,6 +8,7 @@ test_expect_success setup '
        echo content1 >wanted_file &&
        echo content2 >unwanted_file &&
        git add wanted_file unwanted_file &&
+       test_tick &&
        git commit -m one
 '
 
@@ -21,6 +22,7 @@ test_expect_success 'rev-list --objects with pathspecs and deeper paths' '
        mkdir foo &&
        >foo/file &&
        git add foo/file &&
+       test_tick &&
        git commit -m two &&
 
        git rev-list --objects HEAD -- foo >output &&
@@ -69,6 +71,7 @@ test_expect_success '--no-object-names and --object-names are last-one-wins' '
 '
 
 test_expect_success 'rev-list A..B and rev-list ^A B are the same' '
+       test_tick &&
        git commit --allow-empty -m another &&
        git tag -a -m "annotated" v1.0 &&
        git rev-list --objects ^v1.0^ v1.0 >expect &&
@@ -84,10 +87,10 @@ test_expect_success 'propagate uninteresting flag down correctly' '
 test_expect_success 'symleft flag bit is propagated down from tag' '
        git log --format="%m %s" --left-right v1.0...master >actual &&
        cat >expect <<-\EOF &&
-       > two
-       > one
        < another
        < that
+       > two
+       > one
        EOF
        test_cmp expect actual
 '
@@ -125,8 +128,8 @@ test_expect_success 'rev-list can negate index objects' '
        test_cmp expect actual
 '
 
-test_expect_success '--bisect and --first-parent can not be combined' '
-       test_must_fail git rev-list --bisect --first-parent HEAD
+test_expect_success '--bisect and --first-parent can be combined' '
+       git rev-list --bisect --first-parent HEAD
 '
 
 test_expect_success '--header shows a NUL after each commit' '
index a6614080388353c828fdd3894c093ef03f71511d..b95a0212adff71632d0b91cf96432b276c86a44c 100755 (executable)
@@ -263,4 +263,49 @@ test_expect_success 'rev-parse --bisect can default to good/bad refs' '
        test_cmp expect.sorted actual.sorted
 '
 
+test_output_expect_success '--bisect --first-parent' 'git rev-list --bisect --first-parent E ^F' <<EOF
+e4
+EOF
+
+test_output_expect_success '--first-parent' 'git rev-list --first-parent E ^F' <<EOF
+E
+e1
+e2
+e3
+e4
+e5
+e6
+e7
+e8
+EOF
+
+test_output_expect_success '--bisect-vars --first-parent' 'git rev-list --bisect-vars --first-parent E ^F' <<EOF
+bisect_rev='e5'
+bisect_nr=4
+bisect_good=4
+bisect_bad=3
+bisect_all=9
+bisect_steps=2
+EOF
+
+test_expect_success '--bisect-all --first-parent' '
+       cat >expect.unsorted <<-EOF &&
+       $(git rev-parse E) (tag: E, dist=0)
+       $(git rev-parse e1) (tag: e1, dist=1)
+       $(git rev-parse e2) (tag: e2, dist=2)
+       $(git rev-parse e3) (tag: e3, dist=3)
+       $(git rev-parse e4) (tag: e4, dist=4)
+       $(git rev-parse e5) (tag: e5, dist=4)
+       $(git rev-parse e6) (tag: e6, dist=3)
+       $(git rev-parse e7) (tag: e7, dist=2)
+       $(git rev-parse e8) (tag: e8, dist=1)
+       EOF
+
+       # expect results to be ordered by distance (descending),
+       # commit hash (ascending)
+       sort -k4,4r -k1,1 expect.unsorted >expect &&
+       git rev-list --bisect-all --first-parent E ^F >actual &&
+       test_cmp expect actual
+'
+
 test_done
index 7e82e43a634a1fa0546b13769afe69d342c5fe62..bc95da8a5f72c1b9a9e523f82ce4404f92679d5e 100755 (executable)
@@ -32,7 +32,6 @@ changed_iso88591=$(echo "$changed" | iconv -f utf-8 -t $test_encoding)
 truncate_count=20
 
 test_expect_success 'setup' '
-       test_oid_init &&
        : >foo &&
        git add foo &&
        git config i18n.commitEncoding $test_encoding &&
index 36d9b2b2e485ffa8a794e61229dedc8c7d47ea46..b886529e5963ff9855e070747e8d010151c55c67 100755 (executable)
@@ -243,32 +243,30 @@ test_expect_success 'bisect skip: with commit both bad and skipped' '
 '
 
 # We want to automatically find the commit that
-# introduced "Another" into hello.
-test_expect_success \
-    '"git bisect run" simple case' \
-    'echo "#"\!"/bin/sh" > test_script.sh &&
-     echo "grep Another hello > /dev/null" >> test_script.sh &&
-     echo "test \$? -ne 0" >> test_script.sh &&
-     chmod +x test_script.sh &&
-     git bisect start &&
-     git bisect good $HASH1 &&
-     git bisect bad $HASH4 &&
-     git bisect run ./test_script.sh > my_bisect_log.txt &&
-     grep "$HASH3 is the first bad commit" my_bisect_log.txt &&
-     git bisect reset'
+# added "Another" into hello.
+test_expect_success '"git bisect run" simple case' '
+       write_script test_script.sh <<-\EOF &&
+       ! grep Another hello >/dev/null
+       EOF
+       git bisect start &&
+       git bisect good $HASH1 &&
+       git bisect bad $HASH4 &&
+       git bisect run ./test_script.sh >my_bisect_log.txt &&
+       grep "$HASH3 is the first bad commit" my_bisect_log.txt &&
+       git bisect reset
+'
 
 # We want to automatically find the commit that
-# introduced "Ciao" into hello.
-test_expect_success \
-    '"git bisect run" with more complex "git bisect start"' \
-    'echo "#"\!"/bin/sh" > test_script.sh &&
-     echo "grep Ciao hello > /dev/null" >> test_script.sh &&
-     echo "test \$? -ne 0" >> test_script.sh &&
-     chmod +x test_script.sh &&
-     git bisect start $HASH4 $HASH1 &&
-     git bisect run ./test_script.sh > my_bisect_log.txt &&
-     grep "$HASH4 is the first bad commit" my_bisect_log.txt &&
-     git bisect reset'
+# added "Ciao" into hello.
+test_expect_success '"git bisect run" with more complex "git bisect start"' '
+       write_script test_script.sh <<-\EOF &&
+       ! grep Ciao hello >/dev/null
+       EOF
+       git bisect start $HASH4 $HASH1 &&
+       git bisect run ./test_script.sh >my_bisect_log.txt &&
+       grep "$HASH4 is the first bad commit" my_bisect_log.txt &&
+       git bisect reset
+'
 
 # $HASH1 is good, $HASH5 is bad, we skip $HASH3
 # but $HASH4 is good,
@@ -295,24 +293,17 @@ HASH6=
 test_expect_success 'bisect run & skip: cannot tell between 2' '
        add_line_into_file "6: Yet a line." hello &&
        HASH6=$(git rev-parse --verify HEAD) &&
-       echo "#"\!"/bin/sh" > test_script.sh &&
-       echo "sed -ne \\\$p hello | grep Ciao > /dev/null && exit 125" >> test_script.sh &&
-       echo "grep line hello > /dev/null" >> test_script.sh &&
-       echo "test \$? -ne 0" >> test_script.sh &&
-       chmod +x test_script.sh &&
+       write_script test_script.sh <<-\EOF &&
+       sed -ne \$p hello | grep Ciao >/dev/null && exit 125
+       ! grep line hello >/dev/null
+       EOF
        git bisect start $HASH6 $HASH1 &&
-       if git bisect run ./test_script.sh > my_bisect_log.txt
-       then
-               echo Oops, should have failed.
-               false
-       else
-               test $? -eq 2 &&
-               grep "first bad commit could be any of" my_bisect_log.txt &&
-               ! grep $HASH3 my_bisect_log.txt &&
-               ! grep $HASH6 my_bisect_log.txt &&
-               grep $HASH4 my_bisect_log.txt &&
-               grep $HASH5 my_bisect_log.txt
-       fi
+       test_expect_code 2 git bisect run ./test_script.sh >my_bisect_log.txt &&
+       grep "first bad commit could be any of" my_bisect_log.txt &&
+       ! grep $HASH3 my_bisect_log.txt &&
+       ! grep $HASH6 my_bisect_log.txt &&
+       grep $HASH4 my_bisect_log.txt &&
+       grep $HASH5 my_bisect_log.txt
 '
 
 HASH7=
@@ -320,14 +311,13 @@ test_expect_success 'bisect run & skip: find first bad' '
        git bisect reset &&
        add_line_into_file "7: Should be the last line." hello &&
        HASH7=$(git rev-parse --verify HEAD) &&
-       echo "#"\!"/bin/sh" > test_script.sh &&
-       echo "sed -ne \\\$p hello | grep Ciao > /dev/null && exit 125" >> test_script.sh &&
-       echo "sed -ne \\\$p hello | grep day > /dev/null && exit 125" >> test_script.sh &&
-       echo "grep Yet hello > /dev/null" >> test_script.sh &&
-       echo "test \$? -ne 0" >> test_script.sh &&
-       chmod +x test_script.sh &&
+       write_script test_script.sh <<-\EOF &&
+       sed -ne \$p hello | grep Ciao >/dev/null && exit 125
+       sed -ne \$p hello | grep day >/dev/null && exit 125
+       ! grep Yet hello >/dev/null
+       EOF
        git bisect start $HASH7 $HASH1 &&
-       git bisect run ./test_script.sh > my_bisect_log.txt &&
+       git bisect run ./test_script.sh >my_bisect_log.txt &&
        grep "$HASH6 is the first bad commit" my_bisect_log.txt
 '
 
@@ -458,6 +448,24 @@ test_expect_success 'many merge bases creation' '
        grep "$SIDE_HASH5" merge_bases.txt
 '
 
+# We want to automatically find the merge that
+# added "line" into hello.
+test_expect_success '"git bisect run --first-parent" simple case' '
+       git rev-list --first-parent $B_HASH ^$HASH4 >first_parent_chain.txt &&
+       write_script test_script.sh <<-\EOF &&
+       grep $(git rev-parse HEAD) first_parent_chain.txt || exit -1
+       ! grep line hello >/dev/null
+       EOF
+       git bisect start --first-parent &&
+       test_path_is_file ".git/BISECT_FIRST_PARENT" &&
+       git bisect good $HASH4 &&
+       git bisect bad $B_HASH &&
+       git bisect run ./test_script.sh >my_bisect_log.txt &&
+       grep "$B_HASH is the first bad commit" my_bisect_log.txt &&
+       git bisect reset &&
+       test_path_is_missing .git/BISECT_FIRST_PARENT
+'
+
 test_expect_success 'good merge bases when good and bad are siblings' '
        git bisect start "$B_HASH" "$A_HASH" > my_bisect_log.txt &&
        test_i18ngrep "merge base must be tested" my_bisect_log.txt &&
index b2bb0a7f61814fc0f07899ef9c138374e7b81140..e934bc239c534d5da532c28d520732475859b665 100755 (executable)
@@ -22,7 +22,7 @@ test_expect_success 'setup a commit history with trees, blobs' '
 
 test_expect_success 'rev-list --in-commit-order' '
        git rev-list --in-commit-order --objects HEAD >actual.raw &&
-       cut -c 1-40 >actual <actual.raw &&
+       cut -d" " -f1 >actual <actual.raw &&
 
        git cat-file --batch-check="%(objectname)" >expect.raw <<-\EOF &&
                HEAD^{commit}
@@ -49,7 +49,7 @@ test_expect_success 'rev-list --in-commit-order' '
 
 test_expect_success 'rev-list lists blobs and trees after commits' '
        git rev-list --objects HEAD >actual.raw &&
-       cut -c 1-40 >actual <actual.raw &&
+       cut -d" " -f1 >actual <actual.raw &&
 
        git cat-file --batch-check="%(objectname)" >expect.raw <<-\EOF &&
                HEAD^{commit}
index 7683e4a1142a6ee31a1f1fd51b774b19fc2c7401..7531262a5e33d8a650879bf3316251a1062d1dc3 100755 (executable)
@@ -34,7 +34,7 @@ test_expect_success 'setup' '
 '
 
 test_expect_success 'start is valid' '
-       git rev-parse start | grep "^[0-9a-f]\{40\}$"
+       git rev-parse start | grep "^$OID_REGEX$"
 '
 
 test_expect_success 'start^0' '
index 2b3fd498d0742874bf9e71ed9b4982f3921b66c8..7d549748ef3015aade772944603e7b8efe20137b 100755 (executable)
@@ -79,7 +79,7 @@ test_expect_success GPG 'set up a signed tag' '
 '
 
 test_expect_success 'message for merging local branch' '
-       echo "Merge branch ${apos}left${apos} into master" >expected &&
+       echo "Merge branch ${apos}left${apos}" >expected &&
 
        git checkout master &&
        git fetch . left &&
@@ -107,7 +107,7 @@ test_expect_success GPG 'message for merging local tag signed by unknown key' '
 '
 
 test_expect_success 'message for merging external branch' '
-       echo "Merge branch ${apos}left${apos} of $(pwd) into master" >expected &&
+       echo "Merge branch ${apos}left${apos} of $(pwd)" >expected &&
 
        git checkout master &&
        git fetch "$(pwd)" left &&
@@ -118,7 +118,7 @@ test_expect_success 'message for merging external branch' '
 
 test_expect_success '[merge] summary/log configuration' '
        cat >expected <<-EOF &&
-       Merge branch ${apos}left${apos} into master
+       Merge branch ${apos}left${apos}
 
        # By Another Author (3) and A U Thor (2)
        # Via Another Committer
@@ -160,7 +160,7 @@ test_expect_success 'setup FETCH_HEAD' '
 
 test_expect_success 'merge.log=3 limits shortlog length' '
        cat >expected <<-EOF &&
-       Merge branch ${apos}left${apos} into master
+       Merge branch ${apos}left${apos}
 
        # By Another Author (3) and A U Thor (2)
        # Via Another Committer
@@ -177,7 +177,7 @@ test_expect_success 'merge.log=3 limits shortlog length' '
 
 test_expect_success 'merge.log=5 shows all 5 commits' '
        cat >expected <<-EOF &&
-       Merge branch ${apos}left${apos} into master
+       Merge branch ${apos}left${apos}
 
        # By Another Author (3) and A U Thor (2)
        # Via Another Committer
@@ -195,7 +195,7 @@ test_expect_success 'merge.log=5 shows all 5 commits' '
 
 test_expect_success '--log=5 with custom comment character' '
        cat >expected <<-EOF &&
-       Merge branch ${apos}left${apos} into master
+       Merge branch ${apos}left${apos}
 
        x By Another Author (3) and A U Thor (2)
        x Via Another Committer
@@ -212,14 +212,14 @@ test_expect_success '--log=5 with custom comment character' '
 '
 
 test_expect_success 'merge.log=0 disables shortlog' '
-       echo "Merge branch ${apos}left${apos} into master" >expected &&
+       echo "Merge branch ${apos}left${apos}" >expected &&
        git -c merge.log=0 fmt-merge-msg <.git/FETCH_HEAD >actual &&
        test_cmp expected actual
 '
 
 test_expect_success '--log=3 limits shortlog length' '
        cat >expected <<-EOF &&
-       Merge branch ${apos}left${apos} into master
+       Merge branch ${apos}left${apos}
 
        # By Another Author (3) and A U Thor (2)
        # Via Another Committer
@@ -236,7 +236,7 @@ test_expect_success '--log=3 limits shortlog length' '
 
 test_expect_success '--log=5 shows all 5 commits' '
        cat >expected <<-EOF &&
-       Merge branch ${apos}left${apos} into master
+       Merge branch ${apos}left${apos}
 
        # By Another Author (3) and A U Thor (2)
        # Via Another Committer
@@ -253,13 +253,13 @@ test_expect_success '--log=5 shows all 5 commits' '
 '
 
 test_expect_success '--no-log disables shortlog' '
-       echo "Merge branch ${apos}left${apos} into master" >expected &&
+       echo "Merge branch ${apos}left${apos}" >expected &&
        git fmt-merge-msg --no-log <.git/FETCH_HEAD >actual &&
        test_cmp expected actual
 '
 
 test_expect_success '--log=0 disables shortlog' '
-       echo "Merge branch ${apos}left${apos} into master" >expected &&
+       echo "Merge branch ${apos}left${apos}" >expected &&
        git fmt-merge-msg --no-log <.git/FETCH_HEAD >actual &&
        test_cmp expected actual
 '
@@ -300,7 +300,7 @@ test_expect_success 'fmt-merge-msg -m' '
 
 test_expect_success 'setup: expected shortlog for two branches' '
        cat >expected <<-EOF
-       Merge branches ${apos}left${apos} and ${apos}right${apos} into master
+       Merge branches ${apos}left${apos} and ${apos}right${apos}
 
        # By Another Author (3) and A U Thor (2)
        # Via Another Committer
@@ -397,7 +397,7 @@ test_expect_success 'merge-msg with nothing to merge' '
 
 test_expect_success 'merge-msg tag' '
        cat >expected <<-EOF &&
-       Merge tag ${apos}tag-r3${apos} into master
+       Merge tag ${apos}tag-r3${apos}
 
        * tag ${apos}tag-r3${apos}:
          Right #3
@@ -418,7 +418,7 @@ test_expect_success 'merge-msg tag' '
 
 test_expect_success 'merge-msg two tags' '
        cat >expected <<-EOF &&
-       Merge tags ${apos}tag-r3${apos} and ${apos}tag-l5${apos} into master
+       Merge tags ${apos}tag-r3${apos} and ${apos}tag-l5${apos}
 
        * tag ${apos}tag-r3${apos}:
          Right #3
@@ -448,7 +448,7 @@ test_expect_success 'merge-msg two tags' '
 
 test_expect_success 'merge-msg tag and branch' '
        cat >expected <<-EOF &&
-       Merge branch ${apos}left${apos}, tag ${apos}tag-r3${apos} into master
+       Merge branch ${apos}left${apos}, tag ${apos}tag-r3${apos}
 
        * tag ${apos}tag-r3${apos}:
          Right #3
@@ -479,7 +479,7 @@ test_expect_success 'merge-msg tag and branch' '
 test_expect_success 'merge-msg lots of commits' '
        {
                cat <<-EOF &&
-               Merge branch ${apos}long${apos} into master
+               Merge branch ${apos}long${apos}
 
                * long: (35 commits)
                EOF
@@ -516,7 +516,7 @@ test_expect_success 'merge-msg with "merging" an annotated tag' '
        git fmt-merge-msg <.git/FETCH_HEAD >actual &&
        {
                cat <<-\EOF
-               Merge tag '\''annote'\'' into master
+               Merge tag '\''annote'\''
 
                An annotated one
 
@@ -531,7 +531,7 @@ test_expect_success 'merge-msg with "merging" an annotated tag' '
        git merge --no-commit --no-ff $annote &&
        {
                cat <<-EOF
-               Merge tag '\''$annote'\'' into master
+               Merge tag '\''$annote'\''
 
                An annotated one
 
@@ -542,4 +542,24 @@ test_expect_success 'merge-msg with "merging" an annotated tag' '
        test_cmp expected .git/MERGE_MSG
 '
 
+test_expect_success 'merge.suppressDest configuration' '
+       git checkout -B side master &&
+       git commit --allow-empty -m "One step ahead" &&
+       git checkout master &&
+       git fetch . side &&
+
+       git -c merge.suppressDest="" fmt-merge-msg <.git/FETCH_HEAD >full.1 &&
+       head -n1 full.1 >actual &&
+       grep -e "Merge branch .side. into master" actual &&
+
+       git -c merge.suppressDest="mast" fmt-merge-msg <.git/FETCH_HEAD >full.2 &&
+       head -n1 full.2 >actual &&
+       grep -e "Merge branch .side. into master$" actual &&
+
+       git -c merge.suppressDest="ma??er" fmt-merge-msg <.git/FETCH_HEAD >full.3 &&
+       head -n1 full.3 >actual &&
+       grep -e "Merge branch .side." actual &&
+       ! grep -e " into master$" actual
+'
+
 test_done
index da59fadc5d8f915cbb60cd426c58becb04e7c42a..58adee7d18ced9b18924cdd33e17bbc6368b9a9a 100755 (executable)
@@ -52,6 +52,25 @@ test_atom() {
                sanitize_pgp <actual >actual.clean &&
                test_cmp expected actual.clean
        "
+       # Automatically test "contents:size" atom after testing "contents"
+       if test "$2" = "contents"
+       then
+               case $(git cat-file -t "$ref") in
+               tag)
+                       # We cannot use $3 as it expects sanitize_pgp to run
+                       expect=$(git cat-file tag $ref | tail -n +6 | wc -c) ;;
+               tree | blob)
+                       expect='' ;;
+               commit)
+                       expect=$(printf '%s' "$3" | wc -c) ;;
+               esac
+               # Leave $expect unquoted to lose possible leading whitespaces
+               echo $expect >expected
+               test_expect_${4:-success} $PREREQ "basic atom: $1 contents:size" '
+                       git for-each-ref --format="%(contents:size)" "$ref" >actual &&
+                       test_cmp expected actual
+               '
+       fi
 }
 
 hexlen=$(test_oid hexsz)
@@ -650,6 +669,25 @@ test_atom refs/tags/signed-long contents "subject line
 body contents
 $sig"
 
+test_expect_success 'set up refs pointing to tree and blob' '
+       git update-ref refs/mytrees/first refs/heads/master^{tree} &&
+       git update-ref refs/myblobs/first refs/heads/master:one
+'
+
+test_atom refs/mytrees/first subject ""
+test_atom refs/mytrees/first contents:subject ""
+test_atom refs/mytrees/first body ""
+test_atom refs/mytrees/first contents:body ""
+test_atom refs/mytrees/first contents:signature ""
+test_atom refs/mytrees/first contents ""
+
+test_atom refs/myblobs/first subject ""
+test_atom refs/myblobs/first contents:subject ""
+test_atom refs/myblobs/first body ""
+test_atom refs/myblobs/first contents:body ""
+test_atom refs/myblobs/first contents:signature ""
+test_atom refs/myblobs/first contents ""
+
 test_expect_success 'set up multiple-sort tags' '
        for when in 100000 200000
        do
@@ -738,61 +776,40 @@ test_expect_success 'set up trailers for next test' '
 '
 
 test_expect_success '%(trailers:unfold) unfolds trailers' '
-       git for-each-ref --format="%(trailers:unfold)" refs/heads/master >actual &&
        {
                unfold <trailers
                echo
        } >expect &&
+       git for-each-ref --format="%(trailers:unfold)" refs/heads/master >actual &&
+       test_cmp expect actual &&
+       git for-each-ref --format="%(contents:trailers:unfold)" refs/heads/master >actual &&
        test_cmp expect actual
 '
 
 test_expect_success '%(trailers:only) shows only "key: value" trailers' '
-       git for-each-ref --format="%(trailers:only)" refs/heads/master >actual &&
        {
                grep -v patch.description <trailers &&
                echo
        } >expect &&
+       git for-each-ref --format="%(trailers:only)" refs/heads/master >actual &&
+       test_cmp expect actual &&
+       git for-each-ref --format="%(contents:trailers:only)" refs/heads/master >actual &&
        test_cmp expect actual
 '
 
 test_expect_success '%(trailers:only) and %(trailers:unfold) work together' '
-       git for-each-ref --format="%(trailers:only,unfold)" refs/heads/master >actual &&
-       git for-each-ref --format="%(trailers:unfold,only)" refs/heads/master >reverse &&
-       test_cmp actual reverse &&
        {
                grep -v patch.description <trailers | unfold &&
                echo
        } >expect &&
-       test_cmp expect actual
-'
-
-test_expect_success '%(contents:trailers:unfold) unfolds trailers' '
-       git for-each-ref --format="%(contents:trailers:unfold)" refs/heads/master >actual &&
-       {
-               unfold <trailers
-               echo
-       } >expect &&
-       test_cmp expect actual
-'
-
-test_expect_success '%(contents:trailers:only) shows only "key: value" trailers' '
-       git for-each-ref --format="%(contents:trailers:only)" refs/heads/master >actual &&
-       {
-               grep -v patch.description <trailers &&
-               echo
-       } >expect &&
-       test_cmp expect actual
-'
-
-test_expect_success '%(contents:trailers:only) and %(contents:trailers:unfold) work together' '
+       git for-each-ref --format="%(trailers:only,unfold)" refs/heads/master >actual &&
+       test_cmp expect actual &&
+       git for-each-ref --format="%(trailers:unfold,only)" refs/heads/master >actual &&
+       test_cmp actual actual &&
        git for-each-ref --format="%(contents:trailers:only,unfold)" refs/heads/master >actual &&
-       git for-each-ref --format="%(contents:trailers:unfold,only)" refs/heads/master >reverse &&
-       test_cmp actual reverse &&
-       {
-               grep -v patch.description <trailers | unfold &&
-               echo
-       } >expect &&
-       test_cmp expect actual
+       test_cmp expect actual &&
+       git for-each-ref --format="%(contents:trailers:unfold,only)" refs/heads/master >actual &&
+       test_cmp actual actual
 '
 
 test_expect_success '%(trailers) rejects unknown trailers arguments' '
@@ -801,15 +818,16 @@ test_expect_success '%(trailers) rejects unknown trailers arguments' '
        fatal: unknown %(trailers) argument: unsupported
        EOF
        test_must_fail git for-each-ref --format="%(trailers:unsupported)" 2>actual &&
+       test_i18ncmp expect actual &&
+       test_must_fail git for-each-ref --format="%(contents:trailers:unsupported)" 2>actual &&
        test_i18ncmp expect actual
 '
 
-test_expect_success '%(contents:trailers) rejects unknown trailers arguments' '
-       # error message cannot be checked under i18n
+test_expect_success 'if arguments, %(contents:trailers) shows error if colon is missing' '
        cat >expect <<-EOF &&
-       fatal: unknown %(trailers) argument: unsupported
+       fatal: unrecognized %(contents) argument: trailersonly
        EOF
-       test_must_fail git for-each-ref --format="%(contents:trailers:unsupported)" 2>actual &&
+       test_must_fail git for-each-ref --format="%(contents:trailersonly)" 2>actual &&
        test_i18ncmp expect actual
 '
 
index 49cc65bb58dd2b81de8f6eebd39ed1649752709d..809854fc0ce98e16d8d4faa1ae22715134293c84 100755 (executable)
@@ -5,9 +5,9 @@ test_description='for-each-ref errors for broken refs'
 . ./test-lib.sh
 
 ZEROS=$ZERO_OID
-MISSING=abababababababababababababababababababab
 
 test_expect_success setup '
+       MISSING=$(test_oid deadbeef) &&
        git commit --allow-empty -m "Initial" &&
        git tag testtag &&
        git for-each-ref >full-list &&
similarity index 100%
rename from t/t6020-merge-df.sh
rename to t/t6400-merge-df.sh
similarity index 100%
rename from t/t6023-merge-file.sh
rename to t/t6403-merge-file.sh
similarity index 98%
rename from t/t6026-merge-attr.sh
rename to t/t6406-merge-attr.sh
index 5900358ce9c0b7605a23266d9179bedba5ad32e6..76a55f838c4ac03cfba678c0f188f67d4f724e6a 100755 (executable)
@@ -122,7 +122,7 @@ test_expect_success 'custom merge backend' '
        o=$(git unpack-file master^:text) &&
        a=$(git unpack-file side^:text) &&
        b=$(git unpack-file master:text) &&
-       sh -c "./custom-merge $o $a $b 0 'text'" &&
+       sh -c "./custom-merge $o $a $b 0 text" &&
        sed -e 1,3d $a >check-2 &&
        cmp check-1 check-2 &&
        rm -f $o $a $b
@@ -149,7 +149,7 @@ test_expect_success 'custom merge backend' '
        o=$(git unpack-file master^:text) &&
        a=$(git unpack-file anchor:text) &&
        b=$(git unpack-file master:text) &&
-       sh -c "./custom-merge $o $a $b 0 'text'" &&
+       sh -c "./custom-merge $o $a $b 0 text" &&
        sed -e 1,3d $a >check-2 &&
        cmp check-1 check-2 &&
        sed -e 1,3d -e 4q $a >check-3 &&
similarity index 100%
rename from t/t6033-merge-crlf.sh
rename to t/t6413-merge-crlf.sh
similarity index 99%
rename from t/t6036-recursive-corner-cases.sh
rename to t/t6416-recursive-corner-cases.sh
index b3bf4626178681cd1acb8dc0e7a70d20dcd95cfb..fd98989b1476e4e1e35893350981d3a1f25a37fa 100755 (executable)
@@ -452,7 +452,7 @@ test_expect_success 'git detects conflict merging criss-cross+modify/delete, rev
 #
 # So choice 5 at least provides some kind of conflict for the original case,
 # and can merge cleanly as expected with D1 and E3.  It also made things just
-# slightly funny for merging D1 and e$, where E4 is defined as:
+# slightly funny for merging D1 and E4, where E4 is defined as:
 #   Commit E4: Merge B & C, modifying 'a' and renaming to 'a2', and deleting 'a/'
 # in this case, we'll get a rename/rename(1to2) conflict because a~$UNIQUE
 # gets renamed to 'a' in D1 and to 'a2' in E4.  But that's better than having
@@ -1144,7 +1144,7 @@ test_expect_failure 'check symlink add/add' '
                test_must_fail git merge -s recursive E^0 &&
 
                git ls-files -s >out &&
-               test_line_count = 2 out &&
+               test_line_count = 3 out &&
                git ls-files -u >out &&
                test_line_count = 2 out &&
                git ls-files -o >out &&
similarity index 88%
rename from t/t6038-merge-text-auto.sh
rename to t/t6418-merge-text-auto.sh
index 5e8d5fa50c9a6a548e5f2fdb11186c165519d06f..30983d18b1bad5ff25f38317839493ac65bf71f5 100755 (executable)
@@ -158,7 +158,7 @@ test_expect_success 'Detect LF/CRLF conflict from addition of text=auto' '
        compare_files expected file.fuzzy
 '
 
-test_expect_failure 'checkout -m after setting text=auto' '
+test_expect_success 'checkout -m after setting text=auto' '
        cat <<-\EOF >expected &&
        first line
        same line
@@ -168,12 +168,12 @@ test_expect_failure 'checkout -m after setting text=auto' '
        git rm -fr . &&
        rm -f .gitattributes &&
        git reset --hard initial &&
-       git checkout a -- . &&
+       git restore --source=a -- . &&
        git checkout -m b &&
-       compare_files expected file
+       git diff --no-index --ignore-cr-at-eol expected file
 '
 
-test_expect_failure 'checkout -m addition of text=auto' '
+test_expect_success 'checkout -m addition of text=auto' '
        cat <<-\EOF >expected &&
        first line
        same line
@@ -183,23 +183,9 @@ test_expect_failure 'checkout -m addition of text=auto' '
        git rm -fr . &&
        rm -f .gitattributes file &&
        git reset --hard initial &&
-       git checkout b -- . &&
+       git restore --source=b -- . &&
        git checkout -m a &&
-       compare_files expected file
-'
-
-test_expect_failure 'cherry-pick patch from after text=auto was added' '
-       append_cr <<-\EOF >expected &&
-       first line
-       same line
-       EOF
-
-       git config merge.renormalize true &&
-       git rm -fr . &&
-       git reset --hard b &&
-       test_must_fail git cherry-pick a >err 2>&1 &&
-       grep "[Nn]othing added" err &&
-       compare_files expected file
+       git diff --no-index --ignore-cr-at-eol expected file
 '
 
 test_expect_success 'Test delete/normalize conflict' '
@@ -211,7 +197,8 @@ test_expect_success 'Test delete/normalize conflict' '
        git commit -m "remove file" &&
        git checkout master &&
        git reset --hard a^ &&
-       git merge side
+       git merge side &&
+       test_path_is_missing file
 '
 
 test_done
similarity index 94%
rename from t/t6042-merge-rename-corner-cases.sh
rename to t/t6422-merge-rename-corner-cases.sh
index f163893ff97125c7750b9bd11c273ae8b738436c..3375eaf4e76daa23c0a9e65fd6b7e060cc04f601 100755 (executable)
@@ -457,7 +457,7 @@ test_expect_success 'handle rename-with-content-merge vs. add' '
                git checkout A^0 &&
 
                test_must_fail git merge -s recursive B^0 >out &&
-               test_i18ngrep "CONFLICT (rename/add)" out &&
+               test_i18ngrep "CONFLICT (.*/add)" out &&
 
                git ls-files -s >out &&
                test_line_count = 2 out &&
@@ -503,7 +503,7 @@ test_expect_success 'handle rename-with-content-merge vs. add, merge other way'
                git checkout B^0 &&
 
                test_must_fail git merge -s recursive A^0 >out &&
-               test_i18ngrep "CONFLICT (rename/add)" out &&
+               test_i18ngrep "CONFLICT (.*/add)" out &&
 
                git ls-files -s >out &&
                test_line_count = 2 out &&
@@ -583,7 +583,7 @@ test_expect_success 'handle rename/rename (2to1) conflict correctly' '
                git checkout B^0 &&
 
                test_must_fail git merge -s recursive C^0 >out &&
-               test_i18ngrep "CONFLICT (rename/rename)" out &&
+               test_i18ngrep "CONFLICT (\(.*\)/\1)" out &&
 
                git ls-files -s >out &&
                test_line_count = 2 out &&
@@ -886,12 +886,17 @@ test_expect_failure 'rad-check: rename/add/delete conflict' '
                git checkout B^0 &&
                test_must_fail git merge -s recursive A^0 >out 2>err &&
 
-               # Not sure whether the output should contain just one
-               # "CONFLICT (rename/add/delete)" line, or if it should break
-               # it into a pair of "CONFLICT (rename/delete)" and
-               # "CONFLICT (rename/add)"; allow for either.
-               test_i18ngrep "CONFLICT (rename.*add)" out &&
-               test_i18ngrep "CONFLICT (rename.*delete)" out &&
+               # Instead of requiring the output to contain one combined line
+               #   CONFLICT (rename/add/delete)
+               # or perhaps two lines:
+               #   CONFLICT (rename/add): new file collides with rename target
+               #   CONFLICT (rename/delete): rename source removed on other side
+               # and instead of requiring "rename/add" instead of "add/add",
+               # be flexible in the type of console output message(s) reported
+               # for this particular case; we will be more stringent about the
+               # contents of the index and working directory.
+               test_i18ngrep "CONFLICT (.*/add)" out &&
+               test_i18ngrep "CONFLICT (rename.*/delete)" out &&
                test_must_be_empty err &&
 
                git ls-files -s >file_count &&
@@ -899,14 +904,14 @@ test_expect_failure 'rad-check: rename/add/delete conflict' '
                git ls-files -u >file_count &&
                test_line_count = 2 file_count &&
                git ls-files -o >file_count &&
-               test_line_count = 2 file_count &&
+               test_line_count = 3 file_count &&
 
                git rev-parse >actual \
                        :2:bar :3:bar &&
                git rev-parse >expect \
                        B:bar  A:bar  &&
 
-               test_cmp file_is_missing foo &&
+               test_path_is_missing foo &&
                # bar should have two-way merged contents of the different
                # versions of bar; check that content from both sides is
                # present.
@@ -954,11 +959,17 @@ test_expect_failure 'rrdd-check: rename/rename(2to1)/delete/delete conflict' '
                git checkout A^0 &&
                test_must_fail git merge -s recursive B^0 >out 2>err &&
 
-               # Not sure whether the output should contain just one
-               # "CONFLICT (rename/rename/delete/delete)" line, or if it
-               # should break it into three: "CONFLICT (rename/rename)" and
-               # two "CONFLICT (rename/delete)" lines; allow for either.
-               test_i18ngrep "CONFLICT (rename/rename)" out &&
+               # Instead of requiring the output to contain one combined line
+               #   CONFLICT (rename/rename/delete/delete)
+               # or perhaps two lines:
+               #   CONFLICT (rename/rename): ...
+               #   CONFLICT (rename/delete): info about pair 1
+               #   CONFLICT (rename/delete): info about pair 2
+               # and instead of requiring "rename/rename" instead of "add/add",
+               # be flexible in the type of console output message(s) reported
+               # for this particular case; we will be more stringent about the
+               # contents of the index and working directory.
+               test_i18ngrep "CONFLICT (\(.*\)/\1)" out &&
                test_i18ngrep "CONFLICT (rename.*delete)" out &&
                test_must_be_empty err &&
 
@@ -967,15 +978,15 @@ test_expect_failure 'rrdd-check: rename/rename(2to1)/delete/delete conflict' '
                git ls-files -u >file_count &&
                test_line_count = 2 file_count &&
                git ls-files -o >file_count &&
-               test_line_count = 2 file_count &&
+               test_line_count = 3 file_count &&
 
                git rev-parse >actual \
                        :2:baz :3:baz &&
                git rev-parse >expect \
                        O:foo  O:bar  &&
 
-               test_cmp file_is_missing foo &&
-               test_cmp file_is_missing bar &&
+               test_path_is_missing foo &&
+               test_path_is_missing bar &&
                # baz should have two-way merged contents of the original
                # contents of foo and bar; check that content from both sides
                # is present.
@@ -1042,25 +1053,25 @@ test_expect_failure 'mod6-check: chains of rename/rename(1to2) and rename/rename
                test_must_be_empty err &&
 
                git ls-files -s >file_count &&
-               test_line_count = 6 file_count &&
+               test_line_count = 9 file_count &&
                git ls-files -u >file_count &&
-               test_line_count = 6 file_count &&
+               test_line_count = 9 file_count &&
                git ls-files -o >file_count &&
                test_line_count = 3 file_count &&
 
                test_seq 10 20 >merged-one &&
                test_seq 51 60 >merged-five &&
                # Determine what the merge of three would give us.
-               test_seq 30 40 >three-side-A &&
+               test_seq 31 39 >three-base &&
+               test_seq 31 40 >three-side-A &&
                test_seq 31 39 >three-side-B &&
-               echo forty >three-side-B &&
-               >empty &&
+               echo forty >>three-side-B &&
                test_must_fail git merge-file \
-                       -L "HEAD" \
+                       -L "HEAD:four" \
                        -L "" \
-                       -L "B^0" \
-                       three-side-A empty three-side-B &&
-               sed -e "s/^\([<=>]\)/\1\1\1/" three-side-A >merged-three &&
+                       -L "B^0:two" \
+                       three-side-A three-base three-side-B &&
+               sed -e "s/^\([<=>]\)/\1\1/" three-side-A >merged-three &&
 
                # Verify the index is as expected
                git rev-parse >actual         \
@@ -1075,6 +1086,7 @@ test_expect_failure 'mod6-check: chains of rename/rename(1to2) and rename/rename
 
                git cat-file -p :2:two >expect &&
                git cat-file -p :3:two >other &&
+               >empty &&
                test_must_fail git merge-file    \
                        -L "HEAD"  -L ""  -L "B^0" \
                        expect     empty  other &&
similarity index 98%
rename from t/t6043-merge-rename-directories.sh
rename to t/t6423-merge-rename-directories.sh
index 83792c5ef1f5ebbdd49bb1455b262ef9d01145f9..f7ecbb886d6191c4bb2e8c1da8b23e0a1e22d47d 100755 (executable)
@@ -275,7 +275,7 @@ test_expect_success '1d: Directory renames cause a rename/rename(2to1) conflict'
                git checkout A^0 &&
 
                test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
-               test_i18ngrep "CONFLICT (rename/rename)" out &&
+               test_i18ngrep "CONFLICT (\(.*\)/\1)" out &&
 
                git ls-files -s >out &&
                test_line_count = 8 out &&
@@ -1686,7 +1686,7 @@ test_expect_success '7b: rename/rename(2to1), but only due to transitive rename'
                git checkout A^0 &&
 
                test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
-               test_i18ngrep "CONFLICT (rename/rename)" out &&
+               test_i18ngrep "CONFLICT (\(.*\)/\1)" out &&
 
                git ls-files -s >out &&
                test_line_count = 4 out &&
@@ -2260,24 +2260,23 @@ test_expect_success '8d: rename/delete...or not?' '
 #   Commit B: w/{b,c}, z/d
 #
 # Possible Resolutions:
-#   w/o dir-rename detection: z/d, CONFLICT(z/b -> y/b vs. w/b),
-#                                  CONFLICT(z/c -> y/c vs. w/c)
-#   Currently expected:       y/d, CONFLICT(z/b -> y/b vs. w/b),
-#                                  CONFLICT(z/c -> y/c vs. w/c)
-#   Optimal:                  ??
+#   if z not considered renamed: z/d, CONFLICT(z/b -> y/b vs. w/b),
+#                                     CONFLICT(z/c -> y/c vs. w/c)
+#   if z->y rename considered:   y/d, CONFLICT(z/b -> y/b vs. w/b),
+#                                     CONFLICT(z/c -> y/c vs. w/c)
+#   Optimal:                     ??
 #
 # Notes: In commit A, directory z got renamed to y.  In commit B, directory z
 #        did NOT get renamed; the directory is still present; instead it is
 #        considered to have just renamed a subset of paths in directory z
-#        elsewhere.  Therefore, the directory rename done in commit A to z/
-#        applies to z/d and maps it to y/d.
+#        elsewhere.  However, this is much like testcase 6b (where commit B
+#        moves all the original paths out of z/ but opted to keep d
+#        within z/).  This makes it hard to judge where d should end up.
 #
 #        It's possible that users would get confused about this, but what
-#        should we do instead?  Silently leaving at z/d seems just as bad or
-#        maybe even worse.  Perhaps we could print a big warning about z/d
-#        and how we're moving to y/d in this case, but when I started thinking
-#        about the ramifications of doing that, I didn't know how to rule out
-#        that opening other weird edge and corner cases so I just punted.
+#        should we do instead?  It's not at all clear to me whether z/d or
+#        y/d or something else is a better resolution here, and other cases
+#        start getting really tricky, so I just picked one.
 
 test_setup_8e () {
        test_create_repo 8e &&
@@ -2844,6 +2843,14 @@ test_expect_success '9f: Renamed directory that only contained immediate subdirs
 #   Commit A: priority/{alpha,bravo}/$more_files
 #   Commit B: goal/{a,b}/$more_files, goal/c
 #   Expected: priority/{alpha,bravo}/$more_files, priority/c
+# We currently fail this test because the directory renames we detect are
+#   goal/a/ -> priority/alpha/
+#   goal/b/ -> priority/bravo/
+# We do not detect
+#   goal/   -> priority/
+# because of no files found within goal/, and the fact that "a" != "alpha"
+# and "b" != "bravo".  But I'm not sure it's really a failure given that
+# viewpoint...
 
 test_setup_9g () {
        test_create_repo 9g &&
@@ -2880,6 +2887,7 @@ test_setup_9g () {
 }
 
 test_expect_failure '9g: Renamed directory that only contained immediate subdirs, immediate subdirs renamed' '
+       test_setup_9g &&
        (
                cd 9g &&
 
@@ -3362,6 +3370,7 @@ test_setup_10e () {
 }
 
 test_expect_failure '10e: Does git complain about untracked file that is not really in the way?' '
+       test_setup_10e &&
        (
                cd 10e &&
 
@@ -4403,7 +4412,7 @@ test_expect_success '13b(info): messages for transitive rename with conflicted c
 #   Commit O: z/{b,c},   x/{d,e}
 #   Commit A: y/{b,c,d}, x/e
 #   Commit B: z/{b,c,d}, x/e
-#   Expected: y/{b,c,d}, with info or conflict messages for d (
+#   Expected: y/{b,c,d}, x/e, with info or conflict messages for d
 #             A: renamed x/d -> z/d; B: renamed z/ -> y/ AND renamed x/d to y/d
 #             One could argue A had partial knowledge of what was done with
 #             d and B had full knowledge, but that's a slippery slope as
similarity index 72%
rename from t/t6045-merge-rename-delete.sh
rename to t/t6425-merge-rename-delete.sh
index 5d33577d2f79f3ef1248d0090028ab350b6b9ea3..f79d021590215f63b5699d985c4e058b98bb03a7 100755 (executable)
@@ -17,7 +17,8 @@ test_expect_success 'rename/delete' '
        git commit -m "delete" &&
 
        test_must_fail git merge --strategy=recursive rename >output &&
-       test_i18ngrep "CONFLICT (rename/delete): A deleted in HEAD and renamed to B in rename. Version rename of B left in tree." output
+       test_i18ngrep "CONFLICT (rename/delete): A.* renamed .*to B.* in rename" output &&
+       test_i18ngrep "CONFLICT (rename/delete): A.*deleted in HEAD." output
 '
 
 test_done
similarity index 99%
rename from t/t6046-merge-skip-unneeded-updates.sh
rename to t/t6426-merge-skip-unneeded-updates.sh
index 1ddc9e6626b8a369fbc15dd74aaf845d53be91e9..699813671c8c1fb5e1624c46415b44711d44a89f 100755 (executable)
@@ -374,7 +374,7 @@ test_expect_success '2c: Modify b & add c VS rename b->c' '
                export GIT_MERGE_VERBOSITY &&
                test_must_fail git merge -s recursive B^0 >out 2>err &&
 
-               test_i18ngrep "CONFLICT (rename/add): Rename b->c" out &&
+               test_i18ngrep "CONFLICT (.*/add):" out &&
                test_must_be_empty err &&
 
                # Make sure c WAS updated
@@ -661,7 +661,7 @@ test_setup_4a () {
 }
 
 # NOTE: For as long as we continue using unpack_trees() without index_only
-#   set to true, it will error out on a case like this claiming the the locally
+#   set to true, it will error out on a case like this claiming that the locally
 #   modified file would be overwritten by the merge.  Getting this testcase
 #   correct requires doing the merge in-memory first, then realizing that no
 #   updates to the file are necessary, and thus that we can just leave the path
similarity index 99%
rename from t/t7405-submodule-merge.sh
rename to t/t6437-submodule-merge.sh
index aa33978ed2868e1585b4acdf87cdba2907597f45..6a1e5f82324877a774fba03e5657654510de994f 100755 (executable)
@@ -195,7 +195,7 @@ test_expect_success 'git submodule status should display the merge conflict prop
        url = $TRASH_DIRECTORY/sub
 EOF
        cat >expect <<EOF &&
-U0000000000000000000000000000000000000000 sub
+U$ZERO_OID sub
 EOF
        git submodule status > actual &&
        test_cmp expect actual &&
@@ -214,7 +214,7 @@ test_expect_success 'git submodule status should display the merge conflict prop
        url = $TRASH_DIRECTORY/sub
 EOF
        cat >expect <<EOF &&
-U0000000000000000000000000000000000000000 sub
+U$ZERO_OID sub
 EOF
        git submodule status > actual &&
        test_cmp expect actual &&
index 0a69a6711768c8fac564481d0cdbddf19a0d2e8c..4a3b8f48ac638d05759377524c0e9566e36e94a9 100755 (executable)
@@ -10,7 +10,24 @@ test_expect_success 'setup' '
        # do not let the amount of physical memory affects gc
        # behavior, make sure we always pack everything to one pack by
        # default
-       git config gc.bigPackThreshold 2g
+       git config gc.bigPackThreshold 2g &&
+
+       # These are simply values which, when hashed as a blob with a newline,
+       # produce a hash where the first byte is 0x17 in their respective
+       # algorithms.
+       test_oid_cache <<-EOF
+       obj1 sha1:263
+       obj1 sha256:34
+
+       obj2 sha1:410
+       obj2 sha256:174
+
+       obj3 sha1:523
+       obj3 sha256:313
+
+       obj4 sha1:790
+       obj4 sha256:481
+       EOF
 '
 
 test_expect_success 'gc empty repository' '
@@ -85,13 +102,13 @@ test_expect_success 'auto gc with too many loose objects does not attempt to cre
        # We need to create two object whose sha1s start with 17
        # since this is what git gc counts.  As it happens, these
        # two blobs will do so.
-       test_commit 263 &&
-       test_commit 410 &&
+       test_commit "$(test_oid obj1)" &&
+       test_commit "$(test_oid obj2)" &&
        # Our first gc will create a pack; our second will create a second pack
        git gc --auto &&
        ls .git/objects/pack | sort >existing_packs &&
-       test_commit 523 &&
-       test_commit 790 &&
+       test_commit "$(test_oid obj3)" &&
+       test_commit "$(test_oid obj4)" &&
 
        git gc --auto 2>err &&
        test_i18ngrep ! "^warning:" err &&
index f30b4849b64ea8bd79a82117333b0f7f225def63..8a3bb4105bf9412b730158ebb55ed268e749a812 100755 (executable)
@@ -128,9 +128,9 @@ for repack in '' true; do
 done
 
 test_expect_success 'do not complain about existing broken links (commit)' '
-       cat >broken-commit <<-\EOF &&
-       tree 0000000000000000000000000000000000000001
-       parent 0000000000000000000000000000000000000002
+       cat >broken-commit <<-EOF &&
+       tree $(test_oid 001)
+       parent $(test_oid 002)
        author whatever <whatever@example.com> 1234 -0000
        committer whatever <whatever@example.com> 1234 -0000
 
@@ -143,8 +143,8 @@ test_expect_success 'do not complain about existing broken links (commit)' '
 '
 
 test_expect_success 'do not complain about existing broken links (tree)' '
-       cat >broken-tree <<-\EOF &&
-       100644 blob 0000000000000000000000000000000000000003    foo
+       cat >broken-tree <<-EOF &&
+       100644 blob $(test_oid 003)     foo
        EOF
        tree=$(git mktree --missing <broken-tree) &&
        git gc -q 2>stderr &&
@@ -153,8 +153,8 @@ test_expect_success 'do not complain about existing broken links (tree)' '
 '
 
 test_expect_success 'do not complain about existing broken links (tag)' '
-       cat >broken-tag <<-\EOF &&
-       object 0000000000000000000000000000000000000004
+       cat >broken-tag <<-EOF &&
+       object $(test_oid 004)
        type commit
        tag broken
        tagger whatever <whatever@example.com> 1234 -0000
index 36b50d0b4c1255408d57b4e8b583cfcd41ce9c0d..63d5f41a1247839412b9c6022fb3f4a07c4e6b0e 100755 (executable)
@@ -177,7 +177,7 @@ test_expect_success "Sergey Vlasov's test case" '
        date >ab.c &&
        date >ab/d &&
        git add ab.c ab &&
-       git commit -m 'initial' &&
+       git commit -m "initial" &&
        git mv ab a
 '
 
@@ -248,6 +248,23 @@ test_expect_success 'git mv should not change sha1 of moved cache entry' '
 
 rm -f dirty dirty2
 
+# NB: This test is about the error message
+# as well as the failure.
+test_expect_success 'git mv error on conflicted file' '
+       rm -fr .git &&
+       git init &&
+       >conflict &&
+       test_when_finished "rm -f conflict" &&
+       cfhash=$(git hash-object -w conflict) &&
+       q_to_tab <<-EOF | git update-index --index-info &&
+       0 $cfhash 0Qconflict
+       100644 $cfhash 1Qconflict
+       EOF
+
+       test_must_fail git mv conflict newname 2>actual &&
+       test_i18ngrep "conflicted" actual
+'
+
 test_expect_success 'git mv should overwrite symlink to a file' '
 
        rm -fr .git &&
index e23de7d0b5a4da29effb1e59426f857fed0e91e0..36477cb1f4470055726cc89d1e69af5f60d88bd2 100755 (executable)
@@ -463,10 +463,11 @@ test_expect_success 'rewrite submodule with another content' '
 '
 
 test_expect_success 'replace submodule revision' '
+       invalid=$(test_oid numeric) &&
        git reset --hard original &&
        git filter-branch -f --tree-filter \
            "if git ls-files --error-unmatch -- submod > /dev/null 2>&1
-            then git update-index --cacheinfo 160000 0123456789012345678901234567890123456789 submod
+            then git update-index --cacheinfo 160000 $invalid submod
             fi" HEAD &&
        test $orig_head != $(git show-ref --hash --head HEAD)
 '
index e4cf5484f97a570da8225ca501d3b395e13604e3..2f9bea9793cec8b2900c35b3add315b67192a882 100755 (executable)
@@ -30,6 +30,31 @@ test_expect_success 'same with gitignore starting with BOM' '
        test_cmp expected actual
 '
 
+test_expect_success 'status untracked files --ignored with pathspec (no match)' '
+       git status --porcelain --ignored -- untracked/i >actual &&
+       test_must_be_empty actual &&
+       git status --porcelain --ignored -- untracked/u >actual &&
+       test_must_be_empty actual
+'
+
+test_expect_success 'status untracked files --ignored with pathspec (literal match)' '
+       git status --porcelain --ignored -- untracked/ignored >actual &&
+       echo "!! untracked/ignored" >expected &&
+       test_cmp expected actual &&
+       git status --porcelain --ignored -- untracked/uncommitted >actual &&
+       echo "?? untracked/uncommitted" >expected &&
+       test_cmp expected actual
+'
+
+test_expect_success 'status untracked files --ignored with pathspec (glob match)' '
+       git status --porcelain --ignored -- untracked/i\* >actual &&
+       echo "!! untracked/ignored" >expected &&
+       test_cmp expected actual &&
+       git status --porcelain --ignored -- untracked/u\* >actual &&
+       echo "?? untracked/uncommitted" >expected &&
+       test_cmp expected actual
+'
+
 cat >expected <<\EOF
 ?? .gitignore
 ?? actual
index 428cff9cf3f5bfc6947dcb84df4c53ce3b14037b..a682a3d826e9dedcf3a08df7a510f6973a42bb8b 100755 (executable)
@@ -75,14 +75,24 @@ test_expect_success 'setup' '
        touch one two three done/one dtwo/two dthree/three &&
        git add one two done/one &&
        : >.git/info/exclude &&
-       git update-index --untracked-cache
+       git update-index --untracked-cache &&
+       test_oid_cache <<-EOF
+       root sha1:e6fcc8f2ee31bae321d66afd183fcb7237afae6e
+       root sha256:b90c672088c015b9c83876e919da311bad4cd39639fb139f988af6a11493b974
+
+       exclude sha1:13263c0978fb9fad16b2d580fb800b6d811c3ff0
+       exclude sha256:fe4aaa1bbbbce4cb8f73426748a14c5ad6026b26f90505a0bf2494b165a5b76c
+
+       done sha1:1946f0437f90c5005533cbe1736a6451ca301714
+       done sha256:7f079501d79f665b3acc50f5e0e9e94509084d5032ac20113a37dd5029b757cc
+       EOF
 '
 
 test_expect_success 'untracked cache is empty' '
        test-tool dump-untracked-cache >../actual &&
        cat >../expect-empty <<EOF &&
-info/exclude 0000000000000000000000000000000000000000
-core.excludesfile 0000000000000000000000000000000000000000
+info/exclude $ZERO_OID
+core.excludesfile $ZERO_OID
 exclude_per_dir .gitignore
 flags 00000006
 EOF
@@ -100,17 +110,17 @@ EOF
 
 cat >../dump.expect <<EOF &&
 info/exclude $EMPTY_BLOB
-core.excludesfile 0000000000000000000000000000000000000000
+core.excludesfile $ZERO_OID
 exclude_per_dir .gitignore
 flags 00000006
-/ 0000000000000000000000000000000000000000 recurse valid
+/ $ZERO_OID recurse valid
 dthree/
 dtwo/
 three
-/done/ 0000000000000000000000000000000000000000 recurse valid
-/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
+/done/ $ZERO_OID recurse valid
+/dthree/ $ZERO_OID recurse check_only valid
 three
-/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
+/dtwo/ $ZERO_OID recurse check_only valid
 two
 EOF
 
@@ -190,18 +200,18 @@ test_expect_success 'verify untracked cache dump' '
        test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
 info/exclude $EMPTY_BLOB
-core.excludesfile 0000000000000000000000000000000000000000
+core.excludesfile $ZERO_OID
 exclude_per_dir .gitignore
 flags 00000006
-/ 0000000000000000000000000000000000000000 recurse valid
+/ $ZERO_OID recurse valid
 dthree/
 dtwo/
 four
 three
-/done/ 0000000000000000000000000000000000000000 recurse valid
-/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
+/done/ $ZERO_OID recurse valid
+/dthree/ $ZERO_OID recurse check_only valid
 three
-/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
+/dtwo/ $ZERO_OID recurse check_only valid
 two
 EOF
        test_cmp ../expect ../actual
@@ -239,18 +249,18 @@ test_expect_success 'verify untracked cache dump' '
        test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
 info/exclude $EMPTY_BLOB
-core.excludesfile 0000000000000000000000000000000000000000
+core.excludesfile $ZERO_OID
 exclude_per_dir .gitignore
 flags 00000006
-/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
+/ $(test_oid root) recurse valid
 .gitignore
 dthree/
 dtwo/
 three
-/done/ 0000000000000000000000000000000000000000 recurse valid
-/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
+/done/ $ZERO_OID recurse valid
+/dthree/ $ZERO_OID recurse check_only valid
 three
-/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
+/dtwo/ $ZERO_OID recurse check_only valid
 two
 EOF
        test_cmp ../expect ../actual
@@ -284,16 +294,16 @@ EOF
 test_expect_success 'verify untracked cache dump' '
        test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
-info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
-core.excludesfile 0000000000000000000000000000000000000000
+info/exclude $(test_oid exclude)
+core.excludesfile $ZERO_OID
 exclude_per_dir .gitignore
 flags 00000006
-/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
+/ $(test_oid root) recurse valid
 .gitignore
 dtwo/
-/done/ 0000000000000000000000000000000000000000 recurse valid
-/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
-/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
+/done/ $ZERO_OID recurse valid
+/dthree/ $ZERO_OID recurse check_only valid
+/dtwo/ $ZERO_OID recurse check_only valid
 two
 EOF
        test_cmp ../expect ../actual
@@ -303,14 +313,14 @@ test_expect_success 'move two from tracked to untracked' '
        git rm --cached two &&
        test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
-info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
-core.excludesfile 0000000000000000000000000000000000000000
+info/exclude $(test_oid exclude)
+core.excludesfile $ZERO_OID
 exclude_per_dir .gitignore
 flags 00000006
-/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse
-/done/ 0000000000000000000000000000000000000000 recurse valid
-/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
-/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
+/ $(test_oid root) recurse
+/done/ $ZERO_OID recurse valid
+/dthree/ $ZERO_OID recurse check_only valid
+/dtwo/ $ZERO_OID recurse check_only valid
 two
 EOF
        test_cmp ../expect ../actual
@@ -342,17 +352,17 @@ EOF
 test_expect_success 'verify untracked cache dump' '
        test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
-info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
-core.excludesfile 0000000000000000000000000000000000000000
+info/exclude $(test_oid exclude)
+core.excludesfile $ZERO_OID
 exclude_per_dir .gitignore
 flags 00000006
-/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
+/ $(test_oid root) recurse valid
 .gitignore
 dtwo/
 two
-/done/ 0000000000000000000000000000000000000000 recurse valid
-/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
-/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
+/done/ $ZERO_OID recurse valid
+/dthree/ $ZERO_OID recurse check_only valid
+/dtwo/ $ZERO_OID recurse check_only valid
 two
 EOF
        test_cmp ../expect ../actual
@@ -362,14 +372,14 @@ test_expect_success 'move two from untracked to tracked' '
        git add two &&
        test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
-info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
-core.excludesfile 0000000000000000000000000000000000000000
+info/exclude $(test_oid exclude)
+core.excludesfile $ZERO_OID
 exclude_per_dir .gitignore
 flags 00000006
-/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse
-/done/ 0000000000000000000000000000000000000000 recurse valid
-/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
-/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
+/ $(test_oid root) recurse
+/done/ $ZERO_OID recurse valid
+/dthree/ $ZERO_OID recurse check_only valid
+/dtwo/ $ZERO_OID recurse check_only valid
 two
 EOF
        test_cmp ../expect ../actual
@@ -401,16 +411,16 @@ EOF
 test_expect_success 'verify untracked cache dump' '
        test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
-info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
-core.excludesfile 0000000000000000000000000000000000000000
+info/exclude $(test_oid exclude)
+core.excludesfile $ZERO_OID
 exclude_per_dir .gitignore
 flags 00000006
-/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
+/ $(test_oid root) recurse valid
 .gitignore
 dtwo/
-/done/ 0000000000000000000000000000000000000000 recurse valid
-/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
-/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
+/done/ $ZERO_OID recurse valid
+/dthree/ $ZERO_OID recurse check_only valid
+/dtwo/ $ZERO_OID recurse check_only valid
 two
 EOF
        test_cmp ../expect ../actual
@@ -447,16 +457,16 @@ EOF
 test_expect_success 'untracked cache correct after commit' '
        test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
-info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
-core.excludesfile 0000000000000000000000000000000000000000
+info/exclude $(test_oid exclude)
+core.excludesfile $ZERO_OID
 exclude_per_dir .gitignore
 flags 00000006
-/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
+/ $(test_oid root) recurse valid
 .gitignore
 dtwo/
-/done/ 0000000000000000000000000000000000000000 recurse valid
-/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
-/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
+/done/ $ZERO_OID recurse valid
+/dthree/ $ZERO_OID recurse check_only valid
+/dtwo/ $ZERO_OID recurse check_only valid
 two
 EOF
        test_cmp ../expect ../actual
@@ -508,17 +518,17 @@ EOF
 test_expect_success 'untracked cache correct after status' '
        test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
-info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
-core.excludesfile 0000000000000000000000000000000000000000
+info/exclude $(test_oid exclude)
+core.excludesfile $ZERO_OID
 exclude_per_dir .gitignore
 flags 00000006
-/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
+/ $(test_oid root) recurse valid
 .gitignore
 dtwo/
-/done/ 1946f0437f90c5005533cbe1736a6451ca301714 recurse valid
+/done/ $(test_oid done) recurse valid
 five
-/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
-/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
+/dthree/ $ZERO_OID recurse check_only valid
+/dtwo/ $ZERO_OID recurse check_only valid
 two
 EOF
        test_cmp ../expect ../actual
@@ -580,22 +590,22 @@ EOF
 test_expect_success 'verify untracked cache dump (sparse/subdirs)' '
        test-tool dump-untracked-cache >../actual &&
        cat >../expect-from-test-dump <<EOF &&
-info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
-core.excludesfile 0000000000000000000000000000000000000000
+info/exclude $(test_oid exclude)
+core.excludesfile $ZERO_OID
 exclude_per_dir .gitignore
 flags 00000006
-/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
+/ $(test_oid root) recurse valid
 .gitignore
 dtwo/
-/done/ 1946f0437f90c5005533cbe1736a6451ca301714 recurse valid
+/done/ $(test_oid done) recurse valid
 five
 sub/
-/done/sub/ 0000000000000000000000000000000000000000 recurse check_only valid
+/done/sub/ $ZERO_OID recurse check_only valid
 sub/
-/done/sub/sub/ 0000000000000000000000000000000000000000 recurse check_only valid
+/done/sub/sub/ $ZERO_OID recurse check_only valid
 file
-/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
-/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
+/dthree/ $ZERO_OID recurse check_only valid
+/dtwo/ $ZERO_OID recurse check_only valid
 two
 EOF
        test_cmp ../expect-from-test-dump ../actual
@@ -806,8 +816,8 @@ test_expect_success '"status" after file replacement should be clean with UC=tru
        test-tool dump-untracked-cache >../actual &&
        grep -F "recurse valid" ../actual >../actual.grep &&
        cat >../expect.grep <<EOF &&
-/ 0000000000000000000000000000000000000000 recurse valid
-/two/ 0000000000000000000000000000000000000000 recurse valid
+/ $ZERO_OID recurse valid
+/two/ $ZERO_OID recurse valid
 EOF
        status_is_clean &&
        test_cmp ../expect.grep ../actual.grep
index 97be0d968dbcedba226b39862faddd23da39d863..22161b3b2d5f7c42d827580802b00f97882b875f 100755 (executable)
@@ -37,17 +37,23 @@ test_expect_success 'creating initial files and commits' '
 
        echo "2nd line 1st file" >>first &&
        git commit -a -m "modify 1st file" &&
+       head5p2=$(git rev-parse --verify HEAD) &&
+       head5p2f=$(git rev-parse --short HEAD:first) &&
 
        git rm first &&
        git mv second secondfile &&
        git commit -a -m "remove 1st and rename 2nd" &&
+       head5p1=$(git rev-parse --verify HEAD) &&
+       head5p1s=$(git rev-parse --short HEAD:secondfile) &&
 
        echo "1st line 2nd file" >secondfile &&
        echo "2nd line 2nd file" >>secondfile &&
        # "git commit -m" would break MinGW, as Windows refuse to pass
        # $test_encoding encoded parameter to git.
        commit_msg $test_encoding | git -c "i18n.commitEncoding=$test_encoding" commit -a -F - &&
-       head5=$(git rev-parse --verify HEAD)
+       head5=$(git rev-parse --verify HEAD) &&
+       head5s=$(git rev-parse --short HEAD:secondfile) &&
+       head5sl=$(git rev-parse HEAD:secondfile)
 '
 # git log --pretty=oneline # to see those SHA1 involved
 
@@ -94,7 +100,7 @@ test_expect_success 'giving a non existing revision should fail' '
 
 test_expect_success 'reset --soft with unmerged index should fail' '
        touch .git/MERGE_HEAD &&
-       echo "100644 44c5b5884550c17758737edcced463447b91d42b 1 un" |
+       echo "100644 $head5sl 1 un" |
                git update-index --index-info &&
        test_must_fail git reset --soft HEAD &&
        rm .git/MERGE_HEAD &&
@@ -192,7 +198,7 @@ test_expect_success \
 >.diff_expect
 cat >.cached_expect <<EOF
 diff --git a/secondfile b/secondfile
-index 1bbba79..44c5b58 100644
+index $head5p1s..$head5s 100644
 --- a/secondfile
 +++ b/secondfile
 @@ -1 +1,2 @@
@@ -207,7 +213,7 @@ secondfile:
 EOF
 test_expect_success '--soft reset only should show changes in diff --cached' '
        git reset --soft HEAD^ &&
-       check_changes d1a4bc3abce4829628ae2dcb0d60ef3d1a78b1c4 &&
+       check_changes $head5p1 &&
        test "$(git rev-parse ORIG_HEAD)" = \
                        $head5
 '
@@ -242,7 +248,7 @@ EOF
 test_expect_success \
        '--hard reset should change the files and undo commits permanently' '
        git reset --hard HEAD~2 &&
-       check_changes ddaefe00f1da16864591c61fdc7adb5d7cd6b74e &&
+       check_changes $head5p2 &&
        test "$(git rev-parse ORIG_HEAD)" = \
                        $head4
 '
@@ -251,7 +257,7 @@ test_expect_success \
 cat >.cached_expect <<EOF
 diff --git a/first b/first
 deleted file mode 100644
-index 8206c22..0000000
+index $head5p2f..0000000
 --- a/first
 +++ /dev/null
 @@ -1,2 +0,0 @@
@@ -259,14 +265,14 @@ index 8206c22..0000000
 -2nd line 1st file
 diff --git a/second b/second
 deleted file mode 100644
-index 1bbba79..0000000
+index $head5p1s..0000000
 --- a/second
 +++ /dev/null
 @@ -1 +0,0 @@
 -2nd file
 diff --git a/secondfile b/secondfile
 new file mode 100644
-index 0000000..44c5b58
+index 0000000..$head5s
 --- /dev/null
 +++ b/secondfile
 @@ -0,0 +1,2 @@
@@ -286,13 +292,13 @@ test_expect_success \
        echo "1st line 2nd file" >secondfile &&
        echo "2nd line 2nd file" >>secondfile &&
        git add secondfile &&
-       check_changes ddaefe00f1da16864591c61fdc7adb5d7cd6b74e
+       check_changes $head5p2
 '
 
 cat >.diff_expect <<EOF
 diff --git a/first b/first
 deleted file mode 100644
-index 8206c22..0000000
+index $head5p2f..0000000
 --- a/first
 +++ /dev/null
 @@ -1,2 +0,0 @@
@@ -300,7 +306,7 @@ index 8206c22..0000000
 -2nd line 1st file
 diff --git a/second b/second
 deleted file mode 100644
-index 1bbba79..0000000
+index $head5p1s..0000000
 --- a/second
 +++ /dev/null
 @@ -1 +0,0 @@
@@ -314,9 +320,8 @@ secondfile:
 EOF
 test_expect_success '--mixed reset to HEAD should unadd the files' '
        git reset &&
-       check_changes ddaefe00f1da16864591c61fdc7adb5d7cd6b74e &&
-       test "$(git rev-parse ORIG_HEAD)" = \
-                       ddaefe00f1da16864591c61fdc7adb5d7cd6b74e
+       check_changes $head5p2 &&
+       test "$(git rev-parse ORIG_HEAD)" = $head5p2
 '
 
 >.diff_expect
@@ -328,7 +333,7 @@ secondfile:
 EOF
 test_expect_success 'redoing the last two commits should succeed' '
        git add secondfile &&
-       git reset --hard ddaefe00f1da16864591c61fdc7adb5d7cd6b74e &&
+       git reset --hard $head5p2 &&
 
        git rm first &&
        git mv second secondfile &&
@@ -389,47 +394,55 @@ test_expect_success \
        check_changes $head5
 '
 
-cat > expect << EOF
-diff --git a/file1 b/file1
-index d00491f..7ed6ff8 100644
---- a/file1
-+++ b/file1
-@@ -1 +1 @@
--1
-+5
-diff --git a/file2 b/file2
-deleted file mode 100644
-index 0cfbf08..0000000
---- a/file2
-+++ /dev/null
-@@ -1 +0,0 @@
--2
-EOF
-cat > cached_expect << EOF
-diff --git a/file4 b/file4
-new file mode 100644
-index 0000000..b8626c4
---- /dev/null
-+++ b/file4
-@@ -0,0 +1 @@
-+4
-EOF
 test_expect_success 'test --mixed <paths>' '
        echo 1 > file1 &&
        echo 2 > file2 &&
        git add file1 file2 &&
        test_tick &&
        git commit -m files &&
+       before1=$(git rev-parse --short HEAD:file1) &&
+       before2=$(git rev-parse --short HEAD:file2) &&
        git rm file2 &&
        echo 3 > file3 &&
        echo 4 > file4 &&
        echo 5 > file1 &&
+       after1=$(git rev-parse --short $(git hash-object file1)) &&
+       after4=$(git rev-parse --short $(git hash-object file4)) &&
        git add file1 file3 file4 &&
        git reset HEAD -- file1 file2 file3 &&
        test_must_fail git diff --quiet &&
        git diff > output &&
+
+       cat > expect <<-EOF &&
+       diff --git a/file1 b/file1
+       index $before1..$after1 100644
+       --- a/file1
+       +++ b/file1
+       @@ -1 +1 @@
+       -1
+       +5
+       diff --git a/file2 b/file2
+       deleted file mode 100644
+       index $before2..0000000
+       --- a/file2
+       +++ /dev/null
+       @@ -1 +0,0 @@
+       -2
+       EOF
+
        test_cmp expect output &&
        git diff --cached > output &&
+
+       cat > cached_expect <<-EOF &&
+       diff --git a/file4 b/file4
+       new file mode 100644
+       index 0000000..$after4
+       --- /dev/null
+       +++ b/file4
+       @@ -0,0 +1 @@
+       +4
+       EOF
+
        test_cmp cached_expect output
 '
 
index cad3a9de9efc21339d82b4532d5af482e3446bc9..15ccb14f7e26faa41ba07d7901e498a0f75f726d 100755 (executable)
@@ -22,7 +22,12 @@ restore_checkpoint () {
 
 verify_expect () {
        git status --porcelain -- fileA.t fileB.t fileC.t fileD.t >actual &&
-       test_cmp expect actual
+       if test "x$1" = 'x!'
+       then
+               ! test_cmp expect actual
+       else
+               test_cmp expect actual
+       fi
 }
 
 test_expect_success '--pathspec-from-file from stdin' '
@@ -131,7 +136,7 @@ test_expect_success 'quotes not compatible with --pathspec-file-nul' '
        cat >expect <<-\EOF &&
         D fileA.t
        EOF
-       test_must_fail verify_expect
+       verify_expect !
 '
 
 test_expect_success 'only touches what was listed' '
index b696bae5f534e82609f8dd0d27e6f9abb85cd7cc..4d62b9b00fa919c2ec29872438d7a170a5605ee3 100755 (executable)
@@ -230,9 +230,10 @@ test_expect_success 'switch to another branch while carrying a deletion' '
 test_expect_success 'checkout to detach HEAD (with advice declined)' '
 
        git config advice.detachedHead false &&
+       rev=$(git rev-parse --short renamer^) &&
        git checkout -f renamer && git clean -f &&
        git checkout renamer^ 2>messages &&
-       test_i18ngrep "HEAD is now at 7329388" messages &&
+       test_i18ngrep "HEAD is now at $rev" messages &&
        test_line_count = 1 messages &&
        H=$(git rev-parse --verify HEAD) &&
        M=$(git show-ref -s --verify refs/heads/master) &&
@@ -248,9 +249,10 @@ test_expect_success 'checkout to detach HEAD (with advice declined)' '
 
 test_expect_success 'checkout to detach HEAD' '
        git config advice.detachedHead true &&
+       rev=$(git rev-parse --short renamer^) &&
        git checkout -f renamer && git clean -f &&
        GIT_TEST_GETTEXT_POISON=false git checkout renamer^ 2>messages &&
-       grep "HEAD is now at 7329388" messages &&
+       grep "HEAD is now at $rev" messages &&
        test_line_count -gt 1 messages &&
        H=$(git rev-parse --verify HEAD) &&
        M=$(git show-ref -s --verify refs/heads/master) &&
index 956e17abb3d7d5fb480c84c977067837c6baca61..fec7e0299dec2614cad243c2520423fe56ce6605 100755 (executable)
@@ -1231,7 +1231,7 @@ test_expect_success 'submodule helper list is not confused by common prefixes' '
        git submodule add /dir1/b dir1/b &&
        git submodule add /dir2/b dir2/b &&
        git commit -m "first submodule commit" &&
-       git submodule--helper list dir1/b |cut -c51- >actual &&
+       git submodule--helper list dir1/b | cut -f 2 >actual &&
        echo "dir1/b" >expect &&
        test_cmp expect actual
 '
@@ -1260,7 +1260,7 @@ test_expect_success 'submodule update --init with a specification' '
        pwd=$(pwd) &&
        git clone file://"$pwd"/multisuper multisuper_clone &&
        git -C multisuper_clone submodule update --init . ":(exclude)sub0" &&
-       git -C multisuper_clone submodule status |cut -c 1,43- >actual &&
+       git -C multisuper_clone submodule status | sed "s/$OID_REGEX //" >actual &&
        test_cmp expect actual
 '
 
@@ -1271,7 +1271,7 @@ test_expect_success 'submodule update --init with submodule.active set' '
        git -C multisuper_clone config submodule.active "." &&
        git -C multisuper_clone config --add submodule.active ":(exclude)sub0" &&
        git -C multisuper_clone submodule update --init &&
-       git -C multisuper_clone submodule status |cut -c 1,43- >actual &&
+       git -C multisuper_clone submodule status | sed "s/$OID_REGEX //" >actual &&
        test_cmp expect actual
 '
 
@@ -1290,7 +1290,7 @@ test_expect_success 'submodule update and setting submodule.<name>.active' '
        -sub3
        EOF
        git -C multisuper_clone submodule update &&
-       git -C multisuper_clone submodule status |cut -c 1,43- >actual &&
+       git -C multisuper_clone submodule status | sed "s/$OID_REGEX //" >actual &&
        test_cmp expect actual
 '
 
@@ -1307,12 +1307,12 @@ test_expect_success 'clone active submodule without submodule url set' '
                git submodule update &&
                git submodule status >actual_raw &&
 
-               cut -c 1,43- actual_raw >actual &&
+               cut -d" " -f3- actual_raw >actual &&
                cat >expect <<-\EOF &&
-                sub0 (test2)
-                sub1 (test2)
-                sub2 (test2)
-                sub3 (test2)
+               sub0 (test2)
+               sub1 (test2)
+               sub2 (test2)
+               sub3 (test2)
                EOF
                test_cmp expect actual
        )
@@ -1328,7 +1328,7 @@ test_expect_success 'clone --recurse-submodules with a pathspec works' '
        EOF
 
        git clone --recurse-submodules="sub0" multisuper multisuper_clone &&
-       git -C multisuper_clone submodule status |cut -c1,43- >actual &&
+       git -C multisuper_clone submodule status | sed "s/$OID_REGEX //" >actual &&
        test_cmp expected actual
 '
 
@@ -1345,7 +1345,7 @@ test_expect_success 'clone with multiple --recurse-submodules options' '
                  --recurse-submodules=":(exclude)sub0" \
                  --recurse-submodules=":(exclude)sub2" \
                  multisuper multisuper_clone &&
-       git -C multisuper_clone submodule status |cut -c1,43- >actual &&
+       git -C multisuper_clone submodule status | sed "s/$OID_REGEX //" >actual &&
        test_cmp expect actual
 '
 
@@ -1373,7 +1373,7 @@ test_expect_success 'clone and subsequent updates correctly auto-initialize subm
                  --recurse-submodules=":(exclude)sub4" \
                  multisuper multisuper_clone &&
 
-       git -C multisuper_clone submodule status |cut -c1,43- >actual &&
+       git -C multisuper_clone submodule status | sed "s/$OID_REGEX //" >actual &&
        test_cmp expect actual &&
 
        git -C multisuper submodule add ../sub1 sub4 &&
@@ -1382,7 +1382,7 @@ test_expect_success 'clone and subsequent updates correctly auto-initialize subm
        # obtain the new superproject
        git -C multisuper_clone pull &&
        git -C multisuper_clone submodule update --init &&
-       git -C multisuper_clone submodule status |cut -c1,43- >actual &&
+       git -C multisuper_clone submodule status | sed "s/$OID_REGEX //" >actual &&
        test_cmp expect2 actual
 '
 
index 08629a6e702999a2af0deccd6558a01a9d881c3f..3fcb44767f51052f637683a34cbb8a2f21c777cc 100755 (executable)
@@ -22,6 +22,10 @@ sanitize_output () {
        mv output2 output
 }
 
+sanitize_diff () {
+       sed -e "/^index [0-9a-f,]*\.\.[0-9a-f]*/d" "$1"
+}
+
 
 test_expect_success 'setup' '
        test_create_repo_with_commit sub &&
@@ -269,7 +273,6 @@ short_sha1_merge_sub1=$(cd sub1 && git rev-parse --short HEAD)
 short_sha1_merge_sub2=$(cd sub2 && git rev-parse --short HEAD)
 cat >diff_expect <<\EOF
 diff --cc .gitmodules
-index badaa4c,44f999a..0000000
 --- a/.gitmodules
 +++ b/.gitmodules
 @@@ -1,3 -1,3 +1,9 @@@
@@ -286,7 +289,6 @@ EOF
 
 cat >diff_submodule_expect <<\EOF
 diff --cc .gitmodules
-index badaa4c,44f999a..0000000
 --- a/.gitmodules
 +++ b/.gitmodules
 @@@ -1,3 -1,3 +1,9 @@@
@@ -306,7 +308,8 @@ test_expect_success 'diff with merge conflict in .gitmodules' '
                cd super &&
                git diff >../diff_actual 2>&1
        ) &&
-       test_cmp diff_expect diff_actual
+       sanitize_diff diff_actual >diff_sanitized &&
+       test_cmp diff_expect diff_sanitized
 '
 
 test_expect_success 'diff --submodule with merge conflict in .gitmodules' '
@@ -314,7 +317,8 @@ test_expect_success 'diff --submodule with merge conflict in .gitmodules' '
                cd super &&
                git diff --submodule >../diff_submodule_actual 2>&1
        ) &&
-       test_cmp diff_submodule_expect diff_submodule_actual
+       sanitize_diff diff_submodule_actual >diff_sanitized &&
+       test_cmp diff_submodule_expect diff_sanitized
 '
 
 # We'll setup different cases for further testing:
index 8e969f3e3680d856073460b5b15e524ad9170d7f..e81759319f57b96c1b03afb51dcb93d620f13482 100755 (executable)
@@ -837,7 +837,7 @@ EOF
 '
 
 cat >expect <<EOF
-:100644 100644 $EMPTY_BLOB 0000000000000000000000000000000000000000 M  dir1/modified
+:100644 100644 $EMPTY_BLOB $ZERO_OID M dir1/modified
 EOF
 test_expect_success 'status refreshes the index' '
        touch dir2/added &&
index 1d45f9a4ed001d7135b435e1c1e1b53f27a5d620..1c85f7555507695b301428b7aabea3b65a199b40 100755 (executable)
@@ -14,9 +14,9 @@ Testing basic merge operations/option parsing.
     ! [c4] c4
      ! [c5] c5
       ! [c6] c6
-       * [master] Merge commit 'c1' into master
+       * [master] Merge commit 'c1'
 --------
-       - [master] Merge commit 'c1' into master
+       - [master] Merge commit 'c1'
  +     * [c1] commit 1
       +  [c6] c6
      +   [c5] c5
@@ -44,8 +44,8 @@ test_write_lines '1 X' 2 '3 X' 4 '5 X' 6 7 8 '9 X' >result.1-3-5-9
 test_write_lines 1 2 3 4 5 6 7 8 '9 Z' >result.9z
 
 create_merge_msgs () {
-       echo "Merge tag 'c2' into master" >msg.1-5 &&
-       echo "Merge tags 'c2' and 'c3' into master" >msg.1-5-9 &&
+       echo "Merge tag 'c2'" >msg.1-5 &&
+       echo "Merge tags 'c2' and 'c3'" >msg.1-5-9 &&
        {
                echo "Squashed commit of the following:" &&
                echo &&
@@ -246,7 +246,7 @@ test_expect_success 'merge --squash c3 with c7' '
        #       file
        EOF
        git cat-file commit HEAD >raw &&
-       sed -e '1,/^$/d' raw >actual &&
+       sed -e "1,/^$/d" raw >actual &&
        test_cmp expect actual
 '
 
@@ -258,7 +258,7 @@ test_expect_success 'merge c3 with c7 with commit.cleanup = scissors' '
        git commit --no-edit -a &&
 
        cat >expect <<-\EOF &&
-       Merge tag '"'"'c7'"'"' into master
+       Merge tag '"'"'c7'"'"'
 
        # ------------------------ >8 ------------------------
        # Do not modify or remove the line above.
@@ -268,7 +268,7 @@ test_expect_success 'merge c3 with c7 with commit.cleanup = scissors' '
        #       file
        EOF
        git cat-file commit HEAD >raw &&
-       sed -e '1,/^$/d' raw >actual &&
+       sed -e "1,/^$/d" raw >actual &&
        test_i18ncmp expect actual
 '
 
@@ -292,7 +292,7 @@ test_expect_success 'merge c3 with c7 with --squash commit.cleanup = scissors' '
        #       file
        EOF
        git cat-file commit HEAD >raw &&
-       sed -e '1,/^$/d' raw >actual &&
+       sed -e "1,/^$/d" raw >actual &&
        test_i18ncmp expect actual
 '
 
@@ -808,10 +808,10 @@ test_expect_success 'merge with conflicted --autostash changes' '
 '
 
 cat >expected.branch <<\EOF
-Merge branch 'c5-branch' (early part) into master
+Merge branch 'c5-branch' (early part)
 EOF
 cat >expected.tag <<\EOF
-Merge commit 'c5~1' into master
+Merge commit 'c5~1'
 EOF
 
 test_expect_success 'merge early part of c2' '
index 2af33f195bc3951f79ad29e3c6c12249c37b9a2d..8e7e0a5865d762c1cb859154c2d4735b9bf8722b 100755 (executable)
@@ -16,7 +16,7 @@ test_expect_success 'merge local branch' '
        git checkout master &&
        test_commit master-2 &&
        git merge local-branch &&
-       check_oneline "Merge branch Qlocal-branchQ into master"
+       check_oneline "Merge branch Qlocal-branchQ"
 '
 
 test_expect_success 'merge octopus branches' '
@@ -26,7 +26,7 @@ test_expect_success 'merge octopus branches' '
        test_commit octopus-2 &&
        git checkout master &&
        git merge octopus-a octopus-b &&
-       check_oneline "Merge branches Qoctopus-aQ and Qoctopus-bQ into master"
+       check_oneline "Merge branches Qoctopus-aQ and Qoctopus-bQ"
 '
 
 test_expect_success 'merge tag' '
@@ -35,7 +35,7 @@ test_expect_success 'merge tag' '
        git checkout master &&
        test_commit master-3 &&
        git merge tag-1 &&
-       check_oneline "Merge tag Qtag-1Q into master"
+       check_oneline "Merge tag Qtag-1Q"
 '
 
 test_expect_success 'ambiguous tag' '
@@ -44,7 +44,7 @@ test_expect_success 'ambiguous tag' '
        git checkout master &&
        test_commit master-4 &&
        git merge ambiguous &&
-       check_oneline "Merge tag QambiguousQ into master"
+       check_oneline "Merge tag QambiguousQ"
 '
 
 test_expect_success 'remote-tracking branch' '
@@ -54,7 +54,7 @@ test_expect_success 'remote-tracking branch' '
        git checkout master &&
        test_commit master-5 &&
        git merge origin/master &&
-       check_oneline "Merge remote-tracking branch Qorigin/masterQ into master"
+       check_oneline "Merge remote-tracking branch Qorigin/masterQ"
 '
 
 test_done
index eea048e52ceb328fd5d97b17e996c8f821ae4abb..015973e8fe227e91f9dff8f9c6b08d298670f1ac 100755 (executable)
@@ -6,6 +6,10 @@ test_description='git blame'
 PROG='git blame -c'
 . "$TEST_DIRECTORY"/annotate-tests.sh
 
+test_expect_success 'setup' '
+       hexsz=$(test_oid hexsz)
+'
+
 test_expect_success 'blame untracked file in empty repo' '
        >untracked &&
        test_must_fail git blame untracked
@@ -105,21 +109,32 @@ test_expect_success 'blame --abbrev=<n> works' '
 '
 
 test_expect_success 'blame -l aligns regular and boundary commits' '
-       check_abbrev 40 -l HEAD &&
-       check_abbrev 39 -l ^HEAD
+       check_abbrev $hexsz         -l HEAD &&
+       check_abbrev $((hexsz - 1)) -l ^HEAD
 '
 
-test_expect_success 'blame --abbrev=40 behaves like -l' '
-       check_abbrev 40 --abbrev=40 HEAD &&
-       check_abbrev 39 --abbrev=40 ^HEAD
+test_expect_success 'blame --abbrev with full length behaves like -l' '
+       check_abbrev $hexsz         --abbrev=$hexsz HEAD &&
+       check_abbrev $((hexsz - 1)) --abbrev=$hexsz ^HEAD
 '
 
-test_expect_success '--no-abbrev works like --abbrev=40' '
-       check_abbrev 40 --no-abbrev
+test_expect_success '--no-abbrev works like --abbrev with full length' '
+       check_abbrev $hexsz --no-abbrev
 '
 
 test_expect_success '--exclude-promisor-objects does not BUG-crash' '
        test_must_fail git blame --exclude-promisor-objects one
 '
 
+test_expect_success 'blame with uncommitted edits in partial clone does not crash' '
+       git init server &&
+       echo foo >server/file.txt &&
+       git -C server add file.txt &&
+       git -C server commit -m file &&
+
+       git clone --filter=blob:none "file://$(pwd)/server" client &&
+       echo bar >>client/file.txt &&
+       git -C client blame file.txt
+'
+
 test_done
index 9130b887d2cc45db769e1e5cbb0ddb1c32cf4b39..ba8013b00285afd7f43e7090284e52fa8921224d 100755 (executable)
@@ -6,7 +6,6 @@ test_description='git blame corner cases'
 pick_fc='s/^[0-9a-f^]* *\([^ ]*\) *(\([^ ]*\) .*/\1-\2/'
 
 test_expect_success setup '
-
        echo A A A A A >one &&
        echo B B B B B >two &&
        echo C C C C C >tres &&
@@ -274,18 +273,14 @@ test_expect_success 'blame file with CRLF core.autocrlf=true' '
        grep "A U Thor" actual
 '
 
-# Tests the splitting and merging of blame entries in blame_coalesce().
-# The output of blame is the same, regardless of whether blame_coalesce() runs
-# or not, so we'd likely only notice a problem if blame crashes or assigned
-# blame to the "splitting" commit ('SPLIT' below).
-test_expect_success 'blame coalesce' '
+test_expect_success 'setup coalesce tests' '
        cat >giraffe <<-\EOF &&
        ABC
        DEF
        EOF
        git add giraffe &&
        git commit -m "original file" &&
-       oid=$(git rev-parse HEAD) &&
+       orig=$(git rev-parse HEAD) &&
 
        cat >giraffe <<-\EOF &&
        ABC
@@ -294,6 +289,7 @@ test_expect_success 'blame coalesce' '
        EOF
        git add giraffe &&
        git commit -m "interior SPLIT line" &&
+       split=$(git rev-parse HEAD) &&
 
        cat >giraffe <<-\EOF &&
        ABC
@@ -301,12 +297,25 @@ test_expect_success 'blame coalesce' '
        EOF
        git add giraffe &&
        git commit -m "same contents as original" &&
+       final=$(git rev-parse HEAD)
+'
+
+test_expect_success 'blame coalesce' '
+       cat >expect <<-EOF &&
+       $orig 1 1 2
+       $orig 2 2
+       EOF
+       git blame --porcelain $final giraffe >actual.raw &&
+       grep "^$orig" actual.raw >actual &&
+       test_cmp expect actual
+'
 
+test_expect_success 'blame does not coalesce non-adjacent result lines' '
        cat >expect <<-EOF &&
-       $oid 1) ABC
-       $oid 2) DEF
+       $orig 1) ABC
+       $orig 3) DEF
        EOF
-       git -c core.abbrev=40 blame -s giraffe >actual &&
+       git blame --no-abbrev -s -L1,1 -L3,3 $split giraffe >actual &&
        test_cmp expect actual
 '
 
index 831125047b93a454e69f5f64f4df7380be38ae0a..bdda0c03fe9ea6fc536fb2711051fed066d7c421 100755 (executable)
@@ -54,7 +54,7 @@ test_expect_success 'setup simulated porcelain' '
        cat >read-porcelain.pl <<-\EOF
        my $field = shift;
        while (<>) {
-               if (/^[0-9a-f]{40} /) {
+               if (/^[0-9a-f]{40,} /) {
                        flush();
                        $hash = $&;
                } elsif (/^$field (.*)/) {
index 6e61882b6f59c2b66b43e01c753c3a9bb8bbd70e..e68e6115a66d3722413a1982aa86cc2a5d5932eb 100755 (executable)
@@ -248,7 +248,7 @@ Final
 EOF
 
 # The first line of b matches best with the last line of a, but the overall
-# match is better if we match it with the the first line of a.
+# match is better if we match it with the first line of a.
 title11="Piggy in the middle"
 cat <<EOF >a11
 abcdefg
index ec261085ec68fdb8c9e9b54a9973be880a5c7db5..a08f72596ab4f622033c820f6251ccea92e38d11 100755 (executable)
@@ -1551,7 +1551,7 @@ test_expect_success $PREREQ '8-bit and sendemail.transferencoding=quoted-printab
                --smtp-server="$(pwd)/fake.sendmail" \
                email-using-8bit \
                2>errors >out &&
-       sed '1,/^$/d' msgtxt1 >actual &&
+       sed "1,/^$/d" msgtxt1 >actual &&
        test_cmp expected actual
 '
 
@@ -1568,7 +1568,7 @@ test_expect_success $PREREQ '8-bit and sendemail.transferencoding=base64' '
                --smtp-server="$(pwd)/fake.sendmail" \
                email-using-8bit \
                2>errors >out &&
-       sed '1,/^$/d' msgtxt1 >actual &&
+       sed "1,/^$/d" msgtxt1 >actual &&
        test_cmp expected actual
 '
 
@@ -1594,7 +1594,7 @@ test_expect_success $PREREQ 'convert from quoted-printable to base64' '
                --smtp-server="$(pwd)/fake.sendmail" \
                email-using-qp \
                2>errors >out &&
-       sed '1,/^$/d' msgtxt1 >actual &&
+       sed "1,/^$/d" msgtxt1 >actual &&
        test_cmp expected actual
 '
 
@@ -1624,7 +1624,7 @@ test_expect_success $PREREQ 'CRLF and sendemail.transferencoding=quoted-printabl
                --smtp-server="$(pwd)/fake.sendmail" \
                email-using-crlf \
                2>errors >out &&
-       sed '1,/^$/d' msgtxt1 >actual &&
+       sed "1,/^$/d" msgtxt1 >actual &&
        test_cmp expected actual
 '
 
@@ -1641,7 +1641,7 @@ test_expect_success $PREREQ 'CRLF and sendemail.transferencoding=base64' '
                --smtp-server="$(pwd)/fake.sendmail" \
                email-using-crlf \
                2>errors >out &&
-       sed '1,/^$/d' msgtxt1 >actual &&
+       sed "1,/^$/d" msgtxt1 >actual &&
        test_cmp expected actual
 '
 
@@ -2142,4 +2142,33 @@ test_expect_success $PREREQ 'test that send-email works outside a repo' '
                "$(pwd)/0001-add-master.patch"
 '
 
+test_expect_success $PREREQ 'test that sendmail config is rejected' '
+       test_config sendmail.program sendmail &&
+       test_must_fail git send-email \
+               --from="Example <nobody@example.com>" \
+               --to=nobody@example.com \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               HEAD^ 2>err &&
+       test_i18ngrep "found configuration options for '"'"sendmail"'"'" err
+'
+
+test_expect_success $PREREQ 'test that sendmail config rejection is specific' '
+       test_config resendmail.program sendmail &&
+       git send-email \
+               --from="Example <nobody@example.com>" \
+               --to=nobody@example.com \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               HEAD^
+'
+
+test_expect_success $PREREQ 'test forbidSendmailVariables behavior override' '
+       test_config sendmail.program sendmail &&
+       test_config sendemail.forbidSendmailVariables false &&
+       git send-email \
+               --from="Example <nobody@example.com>" \
+               --to=nobody@example.com \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               HEAD^
+'
+
 test_done
index 9f2d19ecc4ad058ba00af3373af76d45c0235ed1..e4bb22034ee63d92d8a304f3e9754df9ec4131b8 100755 (executable)
@@ -63,16 +63,16 @@ test_expect_success "$name" '
 
 
 name='detect node change from file to directory #1'
-test_expect_success "$name" "
+test_expect_success "$name" '
        mkdir dir/new_file &&
        mv dir/file dir/new_file/file &&
        mv dir/new_file dir/file &&
        git update-index --remove dir/file &&
        git update-index --add dir/file/file &&
-       git commit -m '$name' &&
+       git commit -m "$name" &&
        test_must_fail git svn set-tree --find-copies-harder --rmdir \
                remotes/git-svn..mybranch
-"
+'
 
 
 name='detect node change from directory to file #1'
@@ -200,8 +200,9 @@ GIT_SVN_ID=alt
 export GIT_SVN_ID
 test_expect_success "$name" \
     'git svn init "$svnrepo" && git svn fetch &&
-     git rev-list --pretty=raw remotes/git-svn | grep ^tree | uniq > a &&
-     git rev-list --pretty=raw remotes/alt | grep ^tree | uniq > b &&
+     git log --format="tree %T %s" remotes/git-svn |
+       awk "!seen[\$0]++ { print \$1, \$2 }" >a &&
+     git log --format="tree %T" alt >b &&
      test_cmp a b'
 
 name='check imported tree checksums expected tree checksums'
index e151df81c0672cdf2cd9d97942fe3fbce8a2c6bc..308c1ef42cd10423767449ce33fa0c3d0cfadc31 100755 (executable)
@@ -92,7 +92,7 @@ test_expect_success 'A: create pack from stdin' '
        EOF
 
        reset refs/tags/to-be-deleted
-       from 0000000000000000000000000000000000000000
+       from $ZERO_OID
 
        tag nested
        mark :6
@@ -102,7 +102,7 @@ test_expect_success 'A: create pack from stdin' '
        EOF
 
        reset refs/tags/nested
-       from 0000000000000000000000000000000000000000
+       from $ZERO_OID
 
        tag nested
        mark :7
@@ -284,8 +284,9 @@ test_expect_success 'A: verify pack' '
 '
 
 test_expect_success 'A: verify diff' '
+       copy=$(git rev-parse --verify master:file2) &&
        cat >expect <<-EOF &&
-       :000000 100755 0000000000000000000000000000000000000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 A      copy-of-file2
+       :000000 100755 $ZERO_OID $copy A        copy-of-file2
        EOF
        git diff-tree -M -r master verify--import-marks >actual &&
        compare_diff_raw expect actual &&
@@ -364,7 +365,7 @@ test_expect_success 'B: fail on invalid blob sha1' '
        COMMIT
 
        from refs/heads/master
-       M 755 0000000000000000000000000000000000000001 zero1
+       M 755 $(echo $ZERO_OID | sed -e "s/0$/1/") zero1
 
        INPUT_END
 
@@ -528,6 +529,7 @@ test_expect_success 'B: fail on invalid committer (5)' '
 test_expect_success 'C: incremental import create pack from stdin' '
        newf=$(echo hi newf | git hash-object -w --stdin) &&
        oldf=$(git rev-parse --verify master:file2) &&
+       thrf=$(git rev-parse --verify master:file3) &&
        test_tick &&
        cat >input <<-INPUT_END &&
        commit refs/heads/branch
@@ -570,10 +572,11 @@ test_expect_success 'C: verify commit' '
 '
 
 test_expect_success 'C: validate rename result' '
+       zero=$ZERO_OID &&
        cat >expect <<-EOF &&
-       :000000 100755 0000000000000000000000000000000000000000 f1fb5da718392694d0076d677d6d0e364c79b0bc A      file2/newf
-       :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 R100   file2   file2/oldf
-       :100644 000000 0d92e9f3374ae2947c23aa477cbc68ce598135f1 0000000000000000000000000000000000000000 D      file3
+       :000000 100755 $zero $newf A    file2/newf
+       :100644 100644 $oldf $oldf R100 file2   file2/oldf
+       :100644 000000 $thrf $zero D    file3
        EOF
        git diff-tree -M -r master branch >actual &&
        compare_diff_raw expect actual
@@ -614,9 +617,11 @@ test_expect_success 'D: verify pack' '
 '
 
 test_expect_success 'D: validate new files added' '
+       f5id=$(echo "$file5_data" | git hash-object --stdin) &&
+       f6id=$(echo "$file6_data" | git hash-object --stdin) &&
        cat >expect <<-EOF &&
-       :000000 100755 0000000000000000000000000000000000000000 e74b7d465e52746be2b4bae983670711e6e66657 A      newdir/exec.sh
-       :000000 100644 0000000000000000000000000000000000000000 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 A      newdir/interesting
+       :000000 100755 $ZERO_OID $f6id A        newdir/exec.sh
+       :000000 100644 $ZERO_OID $f5id A        newdir/interesting
        EOF
        git diff-tree -M -r branch^ branch >actual &&
        compare_diff_raw expect actual
@@ -779,12 +784,13 @@ test_expect_success 'H: verify pack' '
 '
 
 test_expect_success 'H: validate old files removed, new files added' '
+       f4id=$(git rev-parse HEAD:file4) &&
        cat >expect <<-EOF &&
-       :100755 000000 f1fb5da718392694d0076d677d6d0e364c79b0bc 0000000000000000000000000000000000000000 D      file2/newf
-       :100644 000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 0000000000000000000000000000000000000000 D      file2/oldf
-       :100755 000000 85df50785d62d3b05ab03d9cbf7e4a0b49449730 0000000000000000000000000000000000000000 D      file4
-       :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 R100   newdir/interesting      h/e/l/lo
-       :100755 000000 e74b7d465e52746be2b4bae983670711e6e66657 0000000000000000000000000000000000000000 D      newdir/exec.sh
+       :100755 000000 $newf $zero D    file2/newf
+       :100644 000000 $oldf $zero D    file2/oldf
+       :100755 000000 $f4id $zero D    file4
+       :100644 100644 $f5id $f5id R100 newdir/interesting      h/e/l/lo
+       :100755 000000 $f6id $zero D    newdir/exec.sh
        EOF
        git diff-tree -M -r H^ H >actual &&
        compare_diff_raw expect actual
@@ -935,14 +941,15 @@ test_expect_success 'L: verify internal tree sorting' '
        INPUT_END
 
        cat >expect <<-EXPECT_END &&
-       :100644 100644 4268632... 55d3a52... M  b.
-       :040000 040000 0ae5cac... 443c768... M  b
-       :100644 100644 4268632... 55d3a52... M  ba
+       :100644 100644 M        b.
+       :040000 040000 M        b
+       :100644 100644 M        ba
        EXPECT_END
 
        git fast-import <input &&
        GIT_PRINT_SHA1_ELLIPSIS="yes" git diff-tree --abbrev --raw L^ L >output &&
-       test_cmp expect output
+       cut -d" " -f1,2,5 output >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success 'L: nested tree copy does not corrupt deltas' '
@@ -1004,7 +1011,7 @@ test_expect_success 'M: rename file in same subdirectory' '
        INPUT_END
 
        cat >expect <<-EOF &&
-       :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100   file2/newf      file2/n.e.w.f
+       :100755 100755 $newf $newf R100 file2/newf      file2/n.e.w.f
        EOF
        git fast-import <input &&
        git diff-tree -M -r M1^ M1 >actual &&
@@ -1025,7 +1032,7 @@ test_expect_success 'M: rename file to new subdirectory' '
        INPUT_END
 
        cat >expect <<-EOF &&
-       :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100   file2/newf      i/am/new/to/you
+       :100755 100755 $newf $newf R100 file2/newf      i/am/new/to/you
        EOF
        git fast-import <input &&
        git diff-tree -M -r M2^ M2 >actual &&
@@ -1046,7 +1053,7 @@ test_expect_success 'M: rename subdirectory to new subdirectory' '
        INPUT_END
 
        cat >expect <<-EOF &&
-       :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100   i/am/new/to/you other/sub/am/new/to/you
+       :100755 100755 $newf $newf R100 i/am/new/to/you other/sub/am/new/to/you
        EOF
        git fast-import <input &&
        git diff-tree -M -r M3^ M3 >actual &&
@@ -1067,11 +1074,11 @@ test_expect_success 'M: rename root to subdirectory' '
        INPUT_END
 
        cat >expect <<-EOF &&
-       :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 R100   file2/oldf      sub/file2/oldf
-       :100755 100755 85df50785d62d3b05ab03d9cbf7e4a0b49449730 85df50785d62d3b05ab03d9cbf7e4a0b49449730 R100   file4   sub/file4
-       :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc R100   i/am/new/to/you sub/i/am/new/to/you
-       :100755 100755 e74b7d465e52746be2b4bae983670711e6e66657 e74b7d465e52746be2b4bae983670711e6e66657 R100   newdir/exec.sh  sub/newdir/exec.sh
-       :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 R100   newdir/interesting      sub/newdir/interesting
+       :100644 100644 $oldf $oldf R100 file2/oldf      sub/file2/oldf
+       :100755 100755 $f4id $f4id R100 file4   sub/file4
+       :100755 100755 $newf $newf R100 i/am/new/to/you sub/i/am/new/to/you
+       :100755 100755 $f6id $f6id R100 newdir/exec.sh  sub/newdir/exec.sh
+       :100644 100644 $f5id $f5id R100 newdir/interesting      sub/newdir/interesting
        EOF
        git fast-import <input &&
        git diff-tree -M -r M4^ M4 >actual &&
@@ -1097,7 +1104,7 @@ test_expect_success 'N: copy file in same subdirectory' '
        INPUT_END
 
        cat >expect <<-EOF &&
-       :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      file2/n.e.w.f
+       :100755 100755 $newf $newf C100 file2/newf      file2/n.e.w.f
        EOF
        git fast-import <input &&
        git diff-tree -C --find-copies-harder -r N1^ N1 >actual &&
@@ -1129,9 +1136,9 @@ test_expect_success 'N: copy then modify subdirectory' '
        INPUT_END
 
        cat >expect <<-EOF &&
-       :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 C100   newdir/interesting      file3/file5
-       :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      file3/newf
-       :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100   file2/oldf      file3/oldf
+       :100644 100644 $f5id $f5id C100 newdir/interesting      file3/file5
+       :100755 100755 $newf $newf C100 file2/newf      file3/newf
+       :100644 100644 $oldf $oldf C100 file2/oldf      file3/oldf
        EOF
        git fast-import <input &&
        git diff-tree -C --find-copies-harder -r N2^^ N2 >actual &&
@@ -1162,9 +1169,9 @@ test_expect_success 'N: copy dirty subdirectory' '
 '
 
 test_expect_success 'N: copy directory by id' '
-       cat >expect <<-\EOF &&
-       :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      file3/newf
-       :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100   file2/oldf      file3/oldf
+       cat >expect <<-EOF &&
+       :100755 100755 $newf $newf C100 file2/newf      file3/newf
+       :100644 100644 $oldf $oldf C100 file2/oldf      file3/oldf
        EOF
        subdir=$(git rev-parse refs/heads/branch^0:file2) &&
        cat >input <<-INPUT_END &&
@@ -1183,9 +1190,9 @@ test_expect_success 'N: copy directory by id' '
 '
 
 test_expect_success PIPE 'N: read and copy directory' '
-       cat >expect <<-\EOF &&
-       :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      file3/newf
-       :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100   file2/oldf      file3/oldf
+       cat >expect <<-EOF &&
+       :100755 100755 $newf $newf C100 file2/newf      file3/newf
+       :100644 100644 $oldf $oldf C100 file2/oldf      file3/oldf
        EOF
        git update-ref -d refs/heads/N4 &&
        rm -f backflow &&
@@ -1254,9 +1261,9 @@ test_expect_success PIPE 'N: empty directory reads as missing' '
 '
 
 test_expect_success 'N: copy root directory by tree hash' '
-       cat >expect <<-\EOF &&
-       :100755 000000 f1fb5da718392694d0076d677d6d0e364c79b0bc 0000000000000000000000000000000000000000 D      file3/newf
-       :100644 000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 0000000000000000000000000000000000000000 D      file3/oldf
+       cat >expect <<-EOF &&
+       :100755 000000 $newf $zero D    file3/newf
+       :100644 000000 $oldf $zero D    file3/oldf
        EOF
        root=$(git rev-parse refs/heads/branch^0^{tree}) &&
        cat >input <<-INPUT_END &&
@@ -1275,12 +1282,12 @@ test_expect_success 'N: copy root directory by tree hash' '
 '
 
 test_expect_success 'N: copy root by path' '
-       cat >expect <<-\EOF &&
-       :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      oldroot/file2/newf
-       :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100   file2/oldf      oldroot/file2/oldf
-       :100755 100755 85df50785d62d3b05ab03d9cbf7e4a0b49449730 85df50785d62d3b05ab03d9cbf7e4a0b49449730 C100   file4   oldroot/file4
-       :100755 100755 e74b7d465e52746be2b4bae983670711e6e66657 e74b7d465e52746be2b4bae983670711e6e66657 C100   newdir/exec.sh  oldroot/newdir/exec.sh
-       :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 C100   newdir/interesting      oldroot/newdir/interesting
+       cat >expect <<-EOF &&
+       :100755 100755 $newf $newf C100 file2/newf      oldroot/file2/newf
+       :100644 100644 $oldf $oldf C100 file2/oldf      oldroot/file2/oldf
+       :100755 100755 $f4id $f4id C100 file4   oldroot/file4
+       :100755 100755 $f6id $f6id C100 newdir/exec.sh  oldroot/newdir/exec.sh
+       :100644 100644 $f5id $f5id C100 newdir/interesting      oldroot/newdir/interesting
        EOF
        cat >input <<-INPUT_END &&
        commit refs/heads/N-copy-root-path
@@ -1340,10 +1347,10 @@ test_expect_success 'N: delete directory by copying' '
 '
 
 test_expect_success 'N: modify copied tree' '
-       cat >expect <<-\EOF &&
-       :100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 C100   newdir/interesting      file3/file5
-       :100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100   file2/newf      file3/newf
-       :100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100   file2/oldf      file3/oldf
+       cat >expect <<-EOF &&
+       :100644 100644 $f5id $f5id C100 newdir/interesting      file3/file5
+       :100755 100755 $newf $newf C100 file2/newf      file3/newf
+       :100644 100644 $oldf $oldf C100 file2/oldf      file3/oldf
        EOF
        subdir=$(git rev-parse refs/heads/branch^0:file2) &&
        cat >input <<-INPUT_END &&
@@ -2726,7 +2733,7 @@ test_expect_success 'R: corrupt lines do not mess marks file' '
        rm -f io.marks &&
        blob=$(echo hi | git hash-object --stdin) &&
        cat >expect <<-EOF &&
-       :3 0000000000000000000000000000000000000000
+       :3 $ZERO_OID
        :1 $blob
        :2 $blob
        EOF
@@ -3077,7 +3084,7 @@ test_expect_success 'T: delete branch' '
        git branch to-delete &&
        git fast-import <<-EOF &&
        reset refs/heads/to-delete
-       from 0000000000000000000000000000000000000000
+       from $ZERO_OID
        EOF
        test_must_fail git rev-parse --verify refs/heads/to-delete
 '
@@ -3117,6 +3124,9 @@ test_expect_success 'U: initialize for U tests' '
 
        INPUT_END
 
+       f7id=$(echo "blob 1" | git hash-object --stdin) &&
+       f8id=$(echo "sleep well" | git hash-object --stdin) &&
+       f9id=$(echo "au revoir" | git hash-object --stdin) &&
        git fast-import <input
 '
 
@@ -3137,7 +3147,7 @@ test_expect_success 'U: filedelete file succeeds' '
 
 test_expect_success 'U: validate file delete result' '
        cat >expect <<-EOF &&
-       :100644 000000 2907ebb4bf85d91bf0716bb3bd8a68ef48d6da76 0000000000000000000000000000000000000000 D      good/night.txt
+       :100644 000000 $f8id $ZERO_OID D        good/night.txt
        EOF
 
        git diff-tree -M -r U^1 U >actual &&
@@ -3162,7 +3172,7 @@ test_expect_success 'U: filedelete directory succeeds' '
 
 test_expect_success 'U: validate directory delete result' '
        cat >expect <<-EOF &&
-       :100644 000000 69cb75792f55123d8389c156b0b41c2ff00ed507 0000000000000000000000000000000000000000 D      good/bye.txt
+       :100644 000000 $f9id $ZERO_OID D        good/bye.txt
        EOF
 
        git diff-tree -M -r U^1 U >actual &&
@@ -3187,7 +3197,7 @@ test_expect_success 'U: filedelete root succeeds' '
 
 test_expect_success 'U: validate root delete result' '
        cat >expect <<-EOF &&
-       :100644 000000 c18147dc648481eeb65dc5e66628429a64843327 0000000000000000000000000000000000000000 D      hello.c
+       :100644 000000 $f7id $ZERO_OID D        hello.c
        EOF
 
        git diff-tree -M -r U^1 U >actual &&
index ca223dca988832867909a65b69d4265289acaccb..14c1baa73940e716a3ca2b76c38c80a643b3af54 100755 (executable)
@@ -470,12 +470,13 @@ test_expect_success 'add lots of commits and notes' '
 '
 
 test_expect_success 'verify that lots of notes trigger a fanout scheme' '
+       hexsz=$(test_oid hexsz) &&
 
        # None of the entries in the top-level notes tree should be a full SHA1
        git ls-tree --name-only refs/notes/many_notes |
        while read path
        do
-               if test $(expr length "$path") -ge 40
+               if test $(expr length "$path") -ge $hexsz
                then
                        return 1
                fi
@@ -518,7 +519,7 @@ test_expect_success 'verify that importing a notes tree respects the fanout sche
        git ls-tree --name-only refs/notes/other_notes |
        while read path
        do
-               if test $(expr length "$path") -ge 40
+               if test $(expr length "$path") -ge $hexsz
                then
                        return 1
                fi
@@ -593,7 +594,7 @@ test_expect_success 'verify that changing notes respect existing fanout' '
        git ls-tree --name-only refs/notes/many_notes |
        while read path
        do
-               if test $(expr length "$path") -ge 40
+               if test $(expr length "$path") -ge $hexsz
                then
                        return 1
                fi
@@ -616,7 +617,7 @@ i=$(($num_commits - $remaining_notes))
 for sha1 in $(git rev-list -n $i refs/heads/many_commits)
 do
        cat >>input <<INPUT_END
-N 0000000000000000000000000000000000000000 $sha1
+N $ZERO_OID $sha1
 INPUT_END
 done
 
@@ -646,7 +647,6 @@ test_expect_success 'remove lots of notes' '
 '
 
 test_expect_success 'verify that removing notes trigger fanout consolidation' '
-
        # All entries in the top-level notes tree should be a full SHA1
        git ls-tree --name-only -r refs/notes/many_notes |
        while read path
@@ -656,7 +656,7 @@ test_expect_success 'verify that removing notes trigger fanout consolidation' '
                test "$path" = "deadbeef" && continue
                test "$path" = "de/adbeef" && continue
 
-               if test $(expr length "$path") -ne 40
+               if test $(expr length "$path") -ne $hexsz
                then
                        return 1
                fi
index 690c90fb82900f8fdc823a28a5a0387295c1010c..137284255998ddd2653360cf614b265ead14d391 100755 (executable)
@@ -132,12 +132,12 @@ test_expect_success 'reencoding iso-8859-7' '
        sed "s/wer/i18n/" iso-8859-7.fi |
                (cd new &&
                 git fast-import &&
-                # The commit object, if not re-encoded, would be 240 bytes.
+                # The commit object, if not re-encoded, would be 200 bytes plus hash.
                 # Removing the "encoding iso-8859-7\n" header drops 20 bytes.
                 # Re-encoding the Pi character from \xF0 (\360) in iso-8859-7
                 # to \xCF\x80 (\317\200) in UTF-8 adds a byte.  Check for
                 # the expected size.
-                test 221 -eq "$(git cat-file -s i18n)" &&
+                test $(($(test_oid hexsz) + 181)) -eq "$(git cat-file -s i18n)" &&
                 # ...and for the expected translation of bytes.
                 git cat-file commit i18n >actual &&
                 grep $(printf "\317\200") actual &&
@@ -164,12 +164,12 @@ test_expect_success 'preserving iso-8859-7' '
        sed "s/wer/i18n-no-recoding/" iso-8859-7.fi |
                (cd new &&
                 git fast-import &&
-                # The commit object, if not re-encoded, is 240 bytes.
+                # The commit object, if not re-encoded, is 200 bytes plus hash.
                 # Removing the "encoding iso-8859-7\n" header would drops 20
                 # bytes.  Re-encoding the Pi character from \xF0 (\360) in
                 # iso-8859-7 to \xCF\x80 (\317\200) in UTF-8 adds a byte.
                 # Check for the expected size...
-                test 240 -eq "$(git cat-file -s i18n-no-recoding)" &&
+                test $(($(test_oid hexsz) + 200)) -eq "$(git cat-file -s i18n-no-recoding)" &&
                 # ...as well as the expected byte.
                 git cat-file commit i18n-no-recoding >actual &&
                 grep $(printf "\360") actual &&
@@ -192,7 +192,7 @@ test_expect_success 'encoding preserved if reencoding fails' '
                 grep ^encoding actual &&
                 # Verify that the commit has the expected size; i.e.
                 # that no bytes were re-encoded to a different encoding.
-                test 252 -eq "$(git cat-file -s i18n-invalid)" &&
+                test $(($(test_oid hexsz) + 212)) -eq "$(git cat-file -s i18n-invalid)" &&
                 # ...and check for the original special bytes
                 grep $(printf "\360") actual &&
                 grep $(printf "\377") actual)
@@ -694,7 +694,7 @@ test_expect_success 'delete ref because entire history excluded' '
        git fast-export to-delete ^to-delete >actual &&
        cat >expected <<-EOF &&
        reset refs/heads/to-delete
-       from 0000000000000000000000000000000000000000
+       from $ZERO_OID
 
        EOF
        test_cmp expected actual
@@ -704,7 +704,7 @@ test_expect_success 'delete refspec' '
        git fast-export --refspec :refs/heads/to-delete >actual &&
        cat >expected <<-EOF &&
        reset refs/heads/to-delete
-       from 0000000000000000000000000000000000000000
+       from $ZERO_OID
 
        EOF
        test_cmp expected actual
index a5e5dca75341561894d681410aaeec6e365144fc..4a46f31c41933e7d2e5c72e47aebf5abd9d7bb3e 100755 (executable)
@@ -603,7 +603,7 @@ test_expect_success 'cvs server does not run with vanilla git-shell' '
                cd cvswork &&
                CVS_SERVER=$WORKDIR/remote-cvs &&
                export CVS_SERVER &&
-               test_must_fail cvs log merge
+               ! cvs log merge
        )
 '
 
index 84787eee9acec4b65f2404356e06b2f4904cea42..c7a0dd84a4b8b8145b498ab1fa9cd8d82300c9c5 100755 (executable)
@@ -167,10 +167,10 @@ test_expect_success 'adding files' '
 
 test_expect_success 'updating' '
     git pull gitcvs.git &&
-    echo 'hi' > subdir/newfile.bin &&
-    echo 'junk' > subdir/file.h &&
-    echo 'hi' > subdir/newfile.c &&
-    echo 'hello' >> binfile.bin &&
+    echo "hi" >subdir/newfile.bin &&
+    echo "junk" >subdir/file.h &&
+    echo "hi" >subdir/newfile.c &&
+    echo "hello" >>binfile.bin &&
     git add subdir/newfile.bin subdir/file.h subdir/newfile.c binfile.bin &&
     git commit -q -m "Add and change some files" &&
     git push gitcvs.git >/dev/null &&
index cf31ace66763741a7f53e3b9a1cb3c0019255f56..6436c91a3cb73be56ee2e972b64fdaf5a386ee5e 100755 (executable)
@@ -178,7 +178,7 @@ test_expect_success 'setup v1.2 on b1' '
        mkdir cdir &&
        echo "cdir/cfile" >cdir/cfile &&
        git add -A cdir adir t3 t2 &&
-       git commit -q -m 'v1.2' &&
+       git commit -q -m "v1.2" &&
        git tag v1.2 &&
        git push --tags gitcvs.git b1:b1
 '
index 267ddc997d028926a81562fe6fe8eab9157da819..b484e3e25020c4feb06760accd55a1bd07db63b5 100755 (executable)
@@ -621,12 +621,22 @@ test_expect_success \
         git config gitweb.snapshot "zip,tgz, tbz2" &&
         gitweb_run "p=.git;a=tree"'
 
-cat >.git/config <<\EOF
-# testing noval and alternate separator
-[gitweb]
-       blame
-       snapshot = zip tgz
-EOF
+test_expect_success 'setup' '
+       version=$(git config core.repositoryformatversion) &&
+       algo=$(test_might_fail git config extensions.objectformat) &&
+       cat >.git/config <<-\EOF &&
+       # testing noval and alternate separator
+       [gitweb]
+               blame
+               snapshot = zip tgz
+       EOF
+       git config core.repositoryformatversion "$version" &&
+       if test -n "$algo"
+       then
+               git config extensions.objectformat "$algo"
+       fi
+'
+
 test_expect_success \
        'config override: tree view, features enabled in repo config (2)' \
        'gitweb_run "p=.git;a=tree"'
index 34cd01366f92164ffcd712cb86dac4eb1cffa3f5..e046f7db762d355228425ff5b77639be65b1272c 100755 (executable)
@@ -23,6 +23,8 @@ sub adjust_dirsep {
        return $path;
 }
 
+my $oid_re = qr/^[0-9a-fA-F]{40}(?:[0-9a-fA-F]{24})?$/;
+
 BEGIN { use_ok('Git') }
 
 # set up
@@ -59,15 +61,15 @@ ok($@, "config_bool: non-boolean values fail");
 open STDERR, ">&", $tmpstderr or die "cannot restore STDERR";
 
 # ident
-like($r->ident("aUthor"), qr/^A U Thor <author\@example.com> [0-9]+ \+0000$/,
+like($r->ident("aUthor"), qr/^A U Thor <author\@example.com> [0-9]+ [+-]\d{4}$/,
      "ident scalar: author (type)");
-like($r->ident("cOmmitter"), qr/^C O Mitter <committer\@example.com> [0-9]+ \+0000$/,
+like($r->ident("cOmmitter"), qr/^C O Mitter <committer\@example.com> [0-9]+ [+-]\d{4}$/,
      "ident scalar: committer (type)");
 is($r->ident("invalid"), "invalid", "ident scalar: invalid ident string (no parsing)");
 my ($name, $email, $time_tz) = $r->ident('author');
 is_deeply([$name, $email], ["A U Thor", "author\@example.com"],
         "ident array: author");
-like($time_tz, qr/[0-9]+ \+0000/, "ident array: author");
+like($time_tz, qr/[0-9]+ [+-]\d{4}/, "ident array: author");
 is_deeply([$r->ident("Name <email> 123 +0000")], ["Name", "email", "123 +0000"],
          "ident array: ident string");
 is_deeply([$r->ident("invalid")], [], "ident array: invalid ident string");
@@ -93,7 +95,7 @@ is(Git::hash_object("blob", $tmpfile), $file1hash, "hash_object: roundtrip");
 open TEMPFILE, ">$tmpfile" or die "Can't open $tmpfile: $!";
 print TEMPFILE my $test_text = "test blob, to be inserted\n";
 close TEMPFILE or die "Failed writing to $tmpfile: $!";
-like(our $newhash = $r->hash_and_insert_object($tmpfile), qr/[0-9a-fA-F]{40}/,
+like(our $newhash = $r->hash_and_insert_object($tmpfile), $oid_re,
      "hash_and_insert_object: returns hash");
 open TEMPFILE, "+>$tmpfile" or die "Can't open $tmpfile: $!";
 is($r->cat_blob($newhash, \*TEMPFILE), length $test_text, "cat_blob: roundtrip size");
@@ -119,7 +121,7 @@ is($r2->wc_subdir, "directory2/", "wc_subdir initial (2)");
 
 # commands in sub directory
 my $last_commit = $r2->command_oneline(qw(rev-parse --verify HEAD));
-like($last_commit, qr/^[0-9a-fA-F]{40}$/, 'rev-parse returned hash');
+like($last_commit, $oid_re, 'rev-parse returned hash');
 my $dir_commit = $r2->command_oneline('log', '-n1', '--pretty=format:%H', '.');
 isnt($last_commit, $dir_commit, 'log . does not show last commit');
 
index 031e1f8668110c754cb1c1b108b1354efbfcc7de..dac67e89d7d720a916eec8a533d9b1f05101525a 100755 (executable)
@@ -10,7 +10,7 @@ repository.'
 
 test_expect_success 'start p4d' '
        start_p4d &&
-       test_might_fail p4 configure set submit.collision.check=0
+       { p4 configure set submit.collision.check=0 || :; }
 '
 
 test_expect_success 'init depot' '
index 3103be8a32393f736481139dd70793ac4e4d97b7..6a8e194a99088f13e1c5a449686804a7a6611d99 100644 (file)
@@ -798,6 +798,37 @@ list_contains () {
        return 1
 }
 
+# Returns success if the arguments indicate that a command should be
+# accepted by test_must_fail(). If the command is run with env, the env
+# and its corresponding variable settings will be stripped before we
+# test the command being run.
+test_must_fail_acceptable () {
+       if test "$1" = "env"
+       then
+               shift
+               while test $# -gt 0
+               do
+                       case "$1" in
+                       *?=*)
+                               shift
+                               ;;
+                       *)
+                               break
+                               ;;
+                       esac
+               done
+       fi
+
+       case "$1" in
+       git|__git*|test-tool|test-svn-fe|test_terminal)
+               return 0
+               ;;
+       *)
+               return 1
+               ;;
+       esac
+}
+
 # This is not among top-level (test_expect_success | test_expect_failure)
 # but is a prefix that can be used in the test script, like:
 #
@@ -817,6 +848,17 @@ list_contains () {
 #     Multiple signals can be specified as a comma separated list.
 #     Currently recognized signal names are: sigpipe, success.
 #     (Don't use 'success', use 'test_might_fail' instead.)
+#
+# Do not use this to run anything but "git" and other specific testable
+# commands (see test_must_fail_acceptable()).  We are not in the
+# business of vetting system supplied commands -- in other words, this
+# is wrong:
+#
+#    test_must_fail grep pattern output
+#
+# Instead use '!':
+#
+#    ! grep pattern output
 
 test_must_fail () {
        case "$1" in
@@ -828,6 +870,11 @@ test_must_fail () {
                _test_ok=
                ;;
        esac
+       if ! test_must_fail_acceptable "$@"
+       then
+               echo >&7 "test_must_fail: only 'git' is allowed: $*"
+               return 1
+       fi
        "$@" 2>&7
        exit_code=$?
        if test $exit_code -eq 0 && ! list_contains "$_test_ok" success
@@ -905,7 +952,13 @@ test_expect_code () {
 # - not all diff versions understand "-u"
 
 test_cmp() {
-       eval "$GIT_TEST_CMP" '"$@"'
+       test $# -eq 2 || BUG "test_cmp requires two arguments"
+       if ! eval "$GIT_TEST_CMP" '"$@"'
+       then
+               test "x$1" = x- || test -e "$1" || BUG "test_cmp '$1' missing"
+               test "x$2" = x- || test -e "$2" || BUG "test_cmp '$2' missing"
+               return 1
+       fi
 }
 
 # Check that the given config key has the expected value.
@@ -934,7 +987,13 @@ test_cmp_config() {
 # test_cmp_bin - helper to compare binary files
 
 test_cmp_bin() {
-       cmp "$@"
+       test $# -eq 2 || BUG "test_cmp_bin requires two arguments"
+       if ! cmp "$@"
+       then
+               test "x$1" = x- || test -e "$1" || BUG "test_cmp_bin '$1' missing"
+               test "x$2" = x- || test -e "$2" || BUG "test_cmp_bin '$2' missing"
+               return 1
+       fi
 }
 
 # Use this instead of test_cmp to compare files that contain expected and
@@ -1417,9 +1476,7 @@ test_set_hash () {
 
 # Detect the hash algorithm in use.
 test_detect_hash () {
-       # Currently we only support SHA-1, but in the future this function will
-       # actually detect the algorithm in use.
-       test_hash_algo='sha1'
+       test_hash_algo="${GIT_TEST_DEFAULT_HASH:-sha1}"
 }
 
 # Load common hash metadata and common placeholder object IDs for use with
@@ -1468,7 +1525,17 @@ test_oid_cache () {
 # Look up a per-hash value based on a key ($1).  The value must have been loaded
 # by test_oid_init or test_oid_cache.
 test_oid () {
-       local var="test_oid_${test_hash_algo}_$1" &&
+       local algo="${test_hash_algo}" &&
+
+       case "$1" in
+       --hash=*)
+               algo="${1#--hash=}" &&
+               shift;;
+       *)
+               ;;
+       esac &&
+
+       local var="test_oid_${algo}_$1" &&
 
        # If the variable is unset, we must be missing an entry for this
        # key-hash pair, so exit with an error.
index 618a7c8d5ba57507b4c0ac8915115a381f86fe28..ef31f400374755015ccec300bdb450021aeccc17 100644 (file)
@@ -441,17 +441,23 @@ TEST_AUTHOR_LOCALNAME=author
 TEST_AUTHOR_DOMAIN=example.com
 GIT_AUTHOR_EMAIL=${TEST_AUTHOR_LOCALNAME}@${TEST_AUTHOR_DOMAIN}
 GIT_AUTHOR_NAME='A U Thor'
+GIT_AUTHOR_DATE='1112354055 +0200'
 TEST_COMMITTER_LOCALNAME=committer
 TEST_COMMITTER_DOMAIN=example.com
 GIT_COMMITTER_EMAIL=${TEST_COMMITTER_LOCALNAME}@${TEST_COMMITTER_DOMAIN}
 GIT_COMMITTER_NAME='C O Mitter'
+GIT_COMMITTER_DATE='1112354055 +0200'
 GIT_MERGE_VERBOSITY=5
 GIT_MERGE_AUTOEDIT=no
 export GIT_MERGE_VERBOSITY GIT_MERGE_AUTOEDIT
 export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME
 export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME
+export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
 export EDITOR
 
+GIT_DEFAULT_HASH="${GIT_TEST_DEFAULT_HASH:-sha1}"
+export GIT_DEFAULT_HASH
+
 # Tests using GIT_TRACE typically don't want <timestamp> <file>:<line> output
 GIT_TRACE_BARE=1
 export GIT_TRACE_BARE
@@ -1686,7 +1692,11 @@ test_lazy_prereq CURL '
 # which will not work with other hash algorithms and tests that work but don't
 # test anything meaningful (e.g. special values which cause short collisions).
 test_lazy_prereq SHA1 '
-       test $(git hash-object /dev/null) = e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
+       case "$GIT_DEFAULT_HASH" in
+       sha1) true ;;
+       "") test $(git hash-object /dev/null) = e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 ;;
+       *) false ;;
+       esac
 '
 
 test_lazy_prereq REBASE_P '
index 91c00567f4d63367d6766808b0ff90f6faa08765..42ed4db5d3a54e1dbb2bd2fb56481da28411ca1f 100644 (file)
@@ -4,13 +4,13 @@
 #include "sigchain.h"
 #include "string-list.h"
 #include "strbuf.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "quote.h"
 #include "object-store.h"
 
 struct tmp_objdir {
        struct strbuf path;
-       struct argv_array env;
+       struct strvec env;
 };
 
 /*
@@ -24,7 +24,7 @@ static struct tmp_objdir *the_tmp_objdir;
 static void tmp_objdir_free(struct tmp_objdir *t)
 {
        strbuf_release(&t->path);
-       argv_array_clear(&t->env);
+       strvec_clear(&t->env);
        free(t);
 }
 
@@ -79,7 +79,7 @@ static void remove_tmp_objdir_on_signal(int signo)
  * separated by PATH_SEP (which is what separate values in
  * GIT_ALTERNATE_OBJECT_DIRECTORIES).
  */
-static void env_append(struct argv_array *env, const char *key, const char *val)
+static void env_append(struct strvec *env, const char *key, const char *val)
 {
        struct strbuf quoted = STRBUF_INIT;
        const char *old;
@@ -97,16 +97,16 @@ static void env_append(struct argv_array *env, const char *key, const char *val)
 
        old = getenv(key);
        if (!old)
-               argv_array_pushf(env, "%s=%s", key, val);
+               strvec_pushf(env, "%s=%s", key, val);
        else
-               argv_array_pushf(env, "%s=%s%c%s", key, old, PATH_SEP, val);
+               strvec_pushf(env, "%s=%s%c%s", key, old, PATH_SEP, val);
 
        strbuf_release(&quoted);
 }
 
-static void env_replace(struct argv_array *env, const char *key, const char *val)
+static void env_replace(struct strvec *env, const char *key, const char *val)
 {
-       argv_array_pushf(env, "%s=%s", key, val);
+       strvec_pushf(env, "%s=%s", key, val);
 }
 
 static int setup_tmp_objdir(const char *root)
@@ -131,7 +131,7 @@ struct tmp_objdir *tmp_objdir_create(void)
 
        t = xmalloc(sizeof(*t));
        strbuf_init(&t->path, 0);
-       argv_array_init(&t->env);
+       strvec_init(&t->env);
 
        strbuf_addf(&t->path, "%s/incoming-XXXXXX", get_object_directory());
 
@@ -283,7 +283,7 @@ const char **tmp_objdir_env(const struct tmp_objdir *t)
 {
        if (!t)
                return NULL;
-       return t->env.argv;
+       return t->env.v;
 }
 
 void tmp_objdir_add_as_alternate(const struct tmp_objdir *t)
index c6b753bfae4bd4e19fd7e3ea16b9f82a8219f10f..defafbf4c1bc6788c4f7b9692cdcfcda1181116b 100644 (file)
@@ -9,7 +9,7 @@
 #include "string-list.h"
 #include "thread-utils.h"
 #include "sigchain.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "refs.h"
 #include "refspec.h"
 #include "transport-internal.h"
@@ -128,17 +128,17 @@ static struct child_process *get_helper(struct transport *transport)
        helper->in = -1;
        helper->out = -1;
        helper->err = 0;
-       argv_array_pushf(&helper->args, "git-remote-%s", data->name);
-       argv_array_push(&helper->args, transport->remote->name);
-       argv_array_push(&helper->args, remove_ext_force(transport->url));
+       strvec_pushf(&helper->args, "git-remote-%s", data->name);
+       strvec_push(&helper->args, transport->remote->name);
+       strvec_push(&helper->args, remove_ext_force(transport->url));
        helper->git_cmd = 0;
        helper->silent_exec_failure = 1;
 
        if (have_git_dir())
-               argv_array_pushf(&helper->env_array, "%s=%s",
-                                GIT_DIR_ENVIRONMENT, get_git_dir());
+               strvec_pushf(&helper->env_array, "%s=%s",
+                            GIT_DIR_ENVIRONMENT, get_git_dir());
 
-       helper->trace2_child_class = helper->args.argv[0]; /* "remote-<name>" */
+       helper->trace2_child_class = helper->args.v[0]; /* "remote-<name>" */
 
        code = start_command(helper);
        if (code < 0 && errno == ENOENT)
@@ -439,13 +439,13 @@ static int get_importer(struct transport *transport, struct child_process *fasti
        int cat_blob_fd, code;
        child_process_init(fastimport);
        fastimport->in = xdup(helper->out);
-       argv_array_push(&fastimport->args, "fast-import");
-       argv_array_push(&fastimport->args, "--allow-unsafe-features");
-       argv_array_push(&fastimport->args, debug ? "--stats" : "--quiet");
+       strvec_push(&fastimport->args, "fast-import");
+       strvec_push(&fastimport->args, "--allow-unsafe-features");
+       strvec_push(&fastimport->args, debug ? "--stats" : "--quiet");
 
        if (data->bidi_import) {
                cat_blob_fd = xdup(helper->in);
-               argv_array_pushf(&fastimport->args, "--cat-blob-fd=%d", cat_blob_fd);
+               strvec_pushf(&fastimport->args, "--cat-blob-fd=%d", cat_blob_fd);
        }
        fastimport->git_cmd = 1;
 
@@ -466,17 +466,17 @@ static int get_exporter(struct transport *transport,
        /* we need to duplicate helper->in because we want to use it after
         * fastexport is done with it. */
        fastexport->out = dup(helper->in);
-       argv_array_push(&fastexport->args, "fast-export");
-       argv_array_push(&fastexport->args, "--use-done-feature");
-       argv_array_push(&fastexport->args, data->signed_tags ?
+       strvec_push(&fastexport->args, "fast-export");
+       strvec_push(&fastexport->args, "--use-done-feature");
+       strvec_push(&fastexport->args, data->signed_tags ?
                "--signed-tags=verbatim" : "--signed-tags=warn-strip");
        if (data->export_marks)
-               argv_array_pushf(&fastexport->args, "--export-marks=%s.tmp", data->export_marks);
+               strvec_pushf(&fastexport->args, "--export-marks=%s.tmp", data->export_marks);
        if (data->import_marks)
-               argv_array_pushf(&fastexport->args, "--import-marks=%s", data->import_marks);
+               strvec_pushf(&fastexport->args, "--import-marks=%s", data->import_marks);
 
        for (i = 0; i < revlist_args->nr; i++)
-               argv_array_push(&fastexport->args, revlist_args->items[i].string);
+               strvec_push(&fastexport->args, revlist_args->items[i].string);
 
        fastexport->git_cmd = 1;
        return start_command(fastexport);
@@ -1082,7 +1082,7 @@ static int has_attribute(const char *attrs, const char *attr)
 }
 
 static struct ref *get_refs_list(struct transport *transport, int for_push,
-                                const struct argv_array *ref_prefixes)
+                                const struct strvec *ref_prefixes)
 {
        get_helper(transport);
 
index 1cde6258a73bcf8582b0746d1c44a23b30115dc9..27c9daffc47ac95b2070006f570373c14cd4aa22 100644 (file)
@@ -3,7 +3,7 @@
 
 struct ref;
 struct transport;
-struct argv_array;
+struct strvec;
 
 struct transport_vtable {
        /**
@@ -30,7 +30,7 @@ struct transport_vtable {
         * in the ref's old_sha1 field; otherwise it should be all 0.
         **/
        struct ref *(*get_refs_list)(struct transport *transport, int for_push,
-                                    const struct argv_array *ref_prefixes);
+                                    const struct strvec *ref_prefixes);
 
        /**
         * Fetch the objects for the given refs. Note that this gets
index b41386eccb4f6432dcdcd8300ee49f8031bfad56..419be0b6ea4b01933766c1cd6dfa0a3e33e154c4 100644 (file)
@@ -127,7 +127,7 @@ struct bundle_transport_data {
 
 static struct ref *get_refs_from_bundle(struct transport *transport,
                                        int for_push,
-                                       const struct argv_array *ref_prefixes)
+                                       const struct strvec *ref_prefixes)
 {
        struct bundle_transport_data *data = transport->data;
        struct ref *result = NULL;
@@ -283,7 +283,7 @@ static void die_if_server_options(struct transport *transport)
  * remote refs.
  */
 static struct ref *handshake(struct transport *transport, int for_push,
-                            const struct argv_array *ref_prefixes,
+                            const struct strvec *ref_prefixes,
                             int must_list_refs)
 {
        struct git_transport_data *data = transport->data;
@@ -327,7 +327,7 @@ static struct ref *handshake(struct transport *transport, int for_push,
 }
 
 static struct ref *get_refs_via_connect(struct transport *transport, int for_push,
-                                       const struct argv_array *ref_prefixes)
+                                       const struct strvec *ref_prefixes)
 {
        return handshake(transport, for_push, ref_prefixes, 1);
 }
@@ -443,6 +443,7 @@ void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int v
        if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE)
                return;
 
+       memset(&rs, 0, sizeof(rs));
        rs.src = ref->name;
        rs.dst = NULL;
 
@@ -1153,7 +1154,7 @@ int transport_push(struct repository *r,
                int porcelain = flags & TRANSPORT_PUSH_PORCELAIN;
                int pretend = flags & TRANSPORT_PUSH_DRY_RUN;
                int push_ret, ret, err;
-               struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
+               struct strvec ref_prefixes = STRVEC_INIT;
 
                if (check_push_refs(local_refs, rs) < 0)
                        return -1;
@@ -1165,7 +1166,7 @@ int transport_push(struct repository *r,
                                                               &ref_prefixes);
                trace2_region_leave("transport_push", "get_refs_list", r);
 
-               argv_array_clear(&ref_prefixes);
+               strvec_clear(&ref_prefixes);
 
                if (flags & TRANSPORT_PUSH_ALL)
                        match_flags |= MATCH_REFS_ALL;
@@ -1281,7 +1282,7 @@ int transport_push(struct repository *r,
 }
 
 const struct ref *transport_get_remote_refs(struct transport *transport,
-                                           const struct argv_array *ref_prefixes)
+                                           const struct strvec *ref_prefixes)
 {
        if (!transport->got_remote_refs) {
                transport->remote_refs =
index b3c30133ea4073603086ac4c2b75bb223b5897b2..1be4013dec4fa7f8a7f17321f4e16de47e4e1137 100644 (file)
@@ -243,7 +243,7 @@ int transport_push(struct repository *repo,
  * ref_prefixes.
  */
 const struct ref *transport_get_remote_refs(struct transport *transport,
-                                           const struct argv_array *ref_prefixes);
+                                           const struct strvec *ref_prefixes);
 
 /*
  * Fetch the hash algorithm used by a remote.
index f3d303c6e541acd4ab715c0a5a329abdc24e7819..6ebad1a46f3e8986d26303b4a67870650293db72 100644 (file)
@@ -29,9 +29,9 @@ static struct combine_diff_path *ll_diff_tree_paths(
        struct combine_diff_path *p, const struct object_id *oid,
        const struct object_id **parents_oid, int nparent,
        struct strbuf *base, struct diff_options *opt);
-static int ll_diff_tree_oid(const struct object_id *old_oid,
-                           const struct object_id *new_oid,
-                           struct strbuf *base, struct diff_options *opt);
+static void ll_diff_tree_oid(const struct object_id *old_oid,
+                            const struct object_id *new_oid,
+                            struct strbuf *base, struct diff_options *opt);
 
 /*
  * Compare two tree entries, taking into account only path/S_ISDIR(mode),
@@ -679,9 +679,9 @@ static void try_to_follow_renames(const struct object_id *old_oid,
        q->nr = 1;
 }
 
-static int ll_diff_tree_oid(const struct object_id *old_oid,
-                           const struct object_id *new_oid,
-                           struct strbuf *base, struct diff_options *opt)
+static void ll_diff_tree_oid(const struct object_id *old_oid,
+                            const struct object_id *new_oid,
+                            struct strbuf *base, struct diff_options *opt)
 {
        struct combine_diff_path phead, *p;
        pathchange_fn_t pathchange_old = opt->pathchange;
@@ -697,29 +697,27 @@ static int ll_diff_tree_oid(const struct object_id *old_oid,
        }
 
        opt->pathchange = pathchange_old;
-       return 0;
 }
 
-int diff_tree_oid(const struct object_id *old_oid,
-                 const struct object_id *new_oid,
-                 const char *base_str, struct diff_options *opt)
+void diff_tree_oid(const struct object_id *old_oid,
+                  const struct object_id *new_oid,
+                  const char *base_str, struct diff_options *opt)
 {
        struct strbuf base;
-       int retval;
 
        strbuf_init(&base, PATH_MAX);
        strbuf_addstr(&base, base_str);
 
-       retval = ll_diff_tree_oid(old_oid, new_oid, &base, opt);
+       ll_diff_tree_oid(old_oid, new_oid, &base, opt);
        if (!*base_str && opt->flags.follow_renames && diff_might_be_rename())
                try_to_follow_renames(old_oid, new_oid, &base, opt);
 
        strbuf_release(&base);
-
-       return retval;
 }
 
-int diff_root_tree_oid(const struct object_id *new_oid, const char *base, struct diff_options *opt)
+void diff_root_tree_oid(const struct object_id *new_oid,
+                       const char *base,
+                       struct diff_options *opt)
 {
-       return diff_tree_oid(NULL, new_oid, base, opt);
+       diff_tree_oid(NULL, new_oid, base, opt);
 }
index bb0ad34c5457d3b812663fb41ece1804fff6ef7a..0160294712b4c91a02f950af377d8fdf6fa4491b 100644 (file)
@@ -851,7 +851,14 @@ static int match_entry(const struct pathspec_item *item,
        if (matchlen > pathlen) {
                if (match[pathlen] != '/')
                        return 0;
-               if (!S_ISDIR(entry->mode) && !S_ISGITLINK(entry->mode))
+               /*
+                * Reject non-directories as partial pathnames, except
+                * when match is a submodule with a trailing slash and
+                * nothing else (to handle 'submod/' and 'submod'
+                * uniformly).
+                */
+               if (!S_ISDIR(entry->mode) &&
+                   (!S_ISGITLINK(entry->mode) || matchlen > pathlen + 1))
                        return 0;
        }
 
index 4be5fc3075410f4004b9d5fc1902eb84880dded5..323280dd48b2cb1e7f6e113f58c12d9332574ec4 100644 (file)
@@ -1,5 +1,5 @@
 #include "cache.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "repository.h"
 #include "config.h"
 #include "dir.h"
@@ -106,7 +106,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
        const char **msgs = opts->msgs;
        const char *msg;
 
-       argv_array_init(&opts->msgs_to_free);
+       strvec_init(&opts->msgs_to_free);
 
        if (!strcmp(cmd, "checkout"))
                msg = advice_commit_before_merge
@@ -124,7 +124,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
                          "Please commit your changes or stash them before you %s.")
                      : _("Your local changes to the following files would be overwritten by %s:\n%%s");
        msgs[ERROR_WOULD_OVERWRITE] = msgs[ERROR_NOT_UPTODATE_FILE] =
-               argv_array_pushf(&opts->msgs_to_free, msg, cmd, cmd);
+               strvec_pushf(&opts->msgs_to_free, msg, cmd, cmd);
 
        msgs[ERROR_NOT_UPTODATE_DIR] =
                _("Updating the following directories would lose untracked files in them:\n%s");
@@ -145,7 +145,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
                          "Please move or remove them before you %s.")
                      : _("The following untracked working tree files would be removed by %s:\n%%s");
        msgs[ERROR_WOULD_LOSE_UNTRACKED_REMOVED] =
-               argv_array_pushf(&opts->msgs_to_free, msg, cmd, cmd);
+               strvec_pushf(&opts->msgs_to_free, msg, cmd, cmd);
 
        if (!strcmp(cmd, "checkout"))
                msg = advice_commit_before_merge
@@ -163,7 +163,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
                          "Please move or remove them before you %s.")
                      : _("The following untracked working tree files would be overwritten by %s:\n%%s");
        msgs[ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN] =
-               argv_array_pushf(&opts->msgs_to_free, msg, cmd, cmd);
+               strvec_pushf(&opts->msgs_to_free, msg, cmd, cmd);
 
        /*
         * Special case: ERROR_BIND_OVERLAP refers to a pair of paths, we
@@ -189,7 +189,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
 
 void clear_unpack_trees_porcelain(struct unpack_trees_options *opts)
 {
-       argv_array_clear(&opts->msgs_to_free);
+       strvec_clear(&opts->msgs_to_free);
        memset(opts->msgs, 0, sizeof(opts->msgs));
 }
 
index 9c2f08277ee1ac4ba7e16e51c2c2d53c9ff14485..2e87875b154540d24b5c7f5d10bfed6db8e218ce 100644 (file)
@@ -2,7 +2,7 @@
 #define UNPACK_TREES_H
 
 #include "cache.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "string-list.h"
 #include "tree-walk.h"
 
@@ -70,7 +70,7 @@ struct unpack_trees_options {
        struct pathspec *pathspec;
        merge_fn_t fn;
        const char *msgs[NB_UNPACK_TREES_WARNING_TYPES];
-       struct argv_array msgs_to_free;
+       struct strvec msgs_to_free;
        /*
         * Store error messages in an array, each case
         * corresponding to a error message type
index 951a2b23aaf8f03d08f8976557de8616bbb2b5ca..3b858eb457e557592dada080f95f3fe7e218b24b 100644 (file)
@@ -18,7 +18,7 @@
 #include "sigchain.h"
 #include "version.h"
 #include "string-list.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "prio-queue.h"
 #include "protocol.h"
 #include "quote.h"
@@ -88,6 +88,7 @@ struct upload_pack_data {
        enum allow_uor allow_uor;
 
        struct list_objects_filter_options filter_options;
+       struct string_list allowed_filters;
 
        struct packet_writer writer;
 
@@ -103,6 +104,8 @@ struct upload_pack_data {
        unsigned no_progress : 1;
        unsigned use_include_tag : 1;
        unsigned allow_filter : 1;
+       unsigned allow_filter_fallback : 1;
+       unsigned long tree_filter_max_depth;
 
        unsigned done : 1;                                      /* v2 only */
        unsigned allow_ref_in_want : 1;                         /* v2 only */
@@ -120,6 +123,7 @@ static void upload_pack_data_init(struct upload_pack_data *data)
        struct string_list deepen_not = STRING_LIST_INIT_DUP;
        struct string_list uri_protocols = STRING_LIST_INIT_DUP;
        struct object_array extra_edge_obj = OBJECT_ARRAY_INIT;
+       struct string_list allowed_filters = STRING_LIST_INIT_DUP;
 
        memset(data, 0, sizeof(*data));
        data->symref = symref;
@@ -131,6 +135,9 @@ static void upload_pack_data_init(struct upload_pack_data *data)
        data->deepen_not = deepen_not;
        data->uri_protocols = uri_protocols;
        data->extra_edge_obj = extra_edge_obj;
+       data->allowed_filters = allowed_filters;
+       data->allow_filter_fallback = 1;
+       data->tree_filter_max_depth = ULONG_MAX;
        packet_writer_init(&data->writer, 1);
 
        data->keepalive = 5;
@@ -147,6 +154,7 @@ static void upload_pack_data_clear(struct upload_pack_data *data)
        string_list_clear(&data->deepen_not, 0);
        object_array_clear(&data->extra_edge_obj);
        list_objects_filter_release(&data->filter_options);
+       string_list_clear(&data->allowed_filters, 1);
 
        free((char *)data->pack_objects_hook);
 }
@@ -269,45 +277,44 @@ static void create_pack_file(struct upload_pack_data *pack_data,
        if (!pack_data->pack_objects_hook)
                pack_objects.git_cmd = 1;
        else {
-               argv_array_push(&pack_objects.args, pack_data->pack_objects_hook);
-               argv_array_push(&pack_objects.args, "git");
+               strvec_push(&pack_objects.args, pack_data->pack_objects_hook);
+               strvec_push(&pack_objects.args, "git");
                pack_objects.use_shell = 1;
        }
 
        if (pack_data->shallow_nr) {
-               argv_array_push(&pack_objects.args, "--shallow-file");
-               argv_array_push(&pack_objects.args, "");
+               strvec_push(&pack_objects.args, "--shallow-file");
+               strvec_push(&pack_objects.args, "");
        }
-       argv_array_push(&pack_objects.args, "pack-objects");
-       argv_array_push(&pack_objects.args, "--revs");
+       strvec_push(&pack_objects.args, "pack-objects");
+       strvec_push(&pack_objects.args, "--revs");
        if (pack_data->use_thin_pack)
-               argv_array_push(&pack_objects.args, "--thin");
+               strvec_push(&pack_objects.args, "--thin");
 
-       argv_array_push(&pack_objects.args, "--stdout");
+       strvec_push(&pack_objects.args, "--stdout");
        if (pack_data->shallow_nr)
-               argv_array_push(&pack_objects.args, "--shallow");
+               strvec_push(&pack_objects.args, "--shallow");
        if (!pack_data->no_progress)
-               argv_array_push(&pack_objects.args, "--progress");
+               strvec_push(&pack_objects.args, "--progress");
        if (pack_data->use_ofs_delta)
-               argv_array_push(&pack_objects.args, "--delta-base-offset");
+               strvec_push(&pack_objects.args, "--delta-base-offset");
        if (pack_data->use_include_tag)
-               argv_array_push(&pack_objects.args, "--include-tag");
+               strvec_push(&pack_objects.args, "--include-tag");
        if (pack_data->filter_options.choice) {
                const char *spec =
                        expand_list_objects_filter_spec(&pack_data->filter_options);
                if (pack_objects.use_shell) {
                        struct strbuf buf = STRBUF_INIT;
                        sq_quote_buf(&buf, spec);
-                       argv_array_pushf(&pack_objects.args, "--filter=%s", buf.buf);
+                       strvec_pushf(&pack_objects.args, "--filter=%s", buf.buf);
                        strbuf_release(&buf);
                } else {
-                       argv_array_pushf(&pack_objects.args, "--filter=%s",
-                                        spec);
+                       strvec_pushf(&pack_objects.args, "--filter=%s", spec);
                }
        }
        if (uri_protocols) {
                for (i = 0; i < uri_protocols->nr; i++)
-                       argv_array_pushf(&pack_objects.args, "--uri-protocol=%s",
+                       strvec_pushf(&pack_objects.args, "--uri-protocol=%s",
                                         uri_protocols->items[i].string);
        }
 
@@ -482,7 +489,8 @@ static int got_oid(struct upload_pack_data *data,
 {
        if (get_oid_hex(hex, oid))
                die("git upload-pack: expected SHA1 object, got '%s'", hex);
-       if (!has_object_file(oid))
+       if (!has_object_file_with_flags(oid,
+                                       OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT))
                return -1;
        return do_got_oid(data, oid);
 }
@@ -595,9 +603,8 @@ static int do_reachable_revlist(struct child_process *cmd,
                "rev-list", "--stdin", NULL,
        };
        struct object *o;
-       char namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + hash + LF */
+       FILE *cmd_in = NULL;
        int i;
-       const unsigned hexsz = the_hash_algo->hexsz;
 
        cmd->argv = argv;
        cmd->git_cmd = 1;
@@ -615,8 +622,8 @@ static int do_reachable_revlist(struct child_process *cmd,
        if (start_command(cmd))
                goto error;
 
-       namebuf[0] = '^';
-       namebuf[hexsz + 1] = '\n';
+       cmd_in = xfdopen(cmd->in, "w");
+
        for (i = get_max_object_index(); 0 < i; ) {
                o = get_indexed_object(--i);
                if (!o)
@@ -625,11 +632,9 @@ static int do_reachable_revlist(struct child_process *cmd,
                        o->flags &= ~TMP_MARK;
                if (!is_our_ref(o, allow_uor))
                        continue;
-               memcpy(namebuf + 1, oid_to_hex(&o->oid), hexsz);
-               if (write_in_full(cmd->in, namebuf, hexsz + 2) < 0)
+               if (fprintf(cmd_in, "^%s\n", oid_to_hex(&o->oid)) < 0)
                        goto error;
        }
-       namebuf[hexsz] = '\n';
        for (i = 0; i < src->nr; i++) {
                o = src->objects[i].item;
                if (is_our_ref(o, allow_uor)) {
@@ -639,11 +644,12 @@ static int do_reachable_revlist(struct child_process *cmd,
                }
                if (reachable && o->type == OBJ_COMMIT)
                        o->flags |= TMP_MARK;
-               memcpy(namebuf, oid_to_hex(&o->oid), hexsz);
-               if (write_in_full(cmd->in, namebuf, hexsz + 1) < 0)
+               if (fprintf(cmd_in, "%s\n", oid_to_hex(&o->oid)) < 0)
                        goto error;
        }
-       close(cmd->in);
+       if (ferror(cmd_in) || fflush(cmd_in))
+               goto error;
+       fclose(cmd_in);
        cmd->in = -1;
        sigchain_pop(SIGPIPE);
 
@@ -652,8 +658,8 @@ static int do_reachable_revlist(struct child_process *cmd,
 error:
        sigchain_pop(SIGPIPE);
 
-       if (cmd->in >= 0)
-               close(cmd->in);
+       if (cmd_in)
+               fclose(cmd_in);
        if (cmd->out >= 0)
                close(cmd->out);
        return -1;
@@ -731,7 +737,6 @@ static int has_unreachable(struct object_array *src, enum allow_uor allow_uor)
        return 0;
 
 error:
-       sigchain_pop(SIGPIPE);
        if (cmd.out >= 0)
                close(cmd.out);
        return 1;
@@ -880,26 +885,26 @@ static int send_shallow_list(struct upload_pack_data *data)
                deepen(data, data->depth);
                ret = 1;
        } else if (data->deepen_rev_list) {
-               struct argv_array av = ARGV_ARRAY_INIT;
+               struct strvec av = STRVEC_INIT;
                int i;
 
-               argv_array_push(&av, "rev-list");
+               strvec_push(&av, "rev-list");
                if (data->deepen_since)
-                       argv_array_pushf(&av, "--max-age=%"PRItime, data->deepen_since);
+                       strvec_pushf(&av, "--max-age=%"PRItime, data->deepen_since);
                if (data->deepen_not.nr) {
-                       argv_array_push(&av, "--not");
+                       strvec_push(&av, "--not");
                        for (i = 0; i < data->deepen_not.nr; i++) {
                                struct string_list_item *s = data->deepen_not.items + i;
-                               argv_array_push(&av, s->string);
+                               strvec_push(&av, s->string);
                        }
-                       argv_array_push(&av, "--not");
+                       strvec_push(&av, "--not");
                }
                for (i = 0; i < data->want_obj.nr; i++) {
                        struct object *o = data->want_obj.objects[i].item;
-                       argv_array_push(&av, oid_to_hex(&o->oid));
+                       strvec_push(&av, oid_to_hex(&o->oid));
                }
-               deepen_by_rev_list(data, av.argc, av.argv);
-               argv_array_clear(&av);
+               deepen_by_rev_list(data, av.nr, av.v);
+               strvec_clear(&av);
                ret = 1;
        } else {
                if (data->shallows.nr > 0) {
@@ -983,6 +988,63 @@ static int process_deepen_not(const char *line, struct string_list *deepen_not,
        return 0;
 }
 
+NORETURN __attribute__((format(printf,2,3)))
+static void send_err_and_die(struct upload_pack_data *data,
+                            const char *fmt, ...)
+{
+       struct strbuf buf = STRBUF_INIT;
+       va_list ap;
+
+       va_start(ap, fmt);
+       strbuf_vaddf(&buf, fmt, ap);
+       va_end(ap);
+
+       packet_writer_error(&data->writer, "%s", buf.buf);
+       die("%s", buf.buf);
+}
+
+static void check_one_filter(struct upload_pack_data *data,
+                            struct list_objects_filter_options *opts)
+{
+       const char *key = list_object_filter_config_name(opts->choice);
+       struct string_list_item *item = string_list_lookup(&data->allowed_filters,
+                                                          key);
+       int allowed;
+
+       if (item)
+               allowed = (intptr_t)item->util;
+       else
+               allowed = data->allow_filter_fallback;
+
+       if (!allowed)
+               send_err_and_die(data, "filter '%s' not supported", key);
+
+       if (opts->choice == LOFC_TREE_DEPTH &&
+           opts->tree_exclude_depth > data->tree_filter_max_depth)
+               send_err_and_die(data,
+                                "tree filter allows max depth %lu, but got %lu",
+                                data->tree_filter_max_depth,
+                                opts->tree_exclude_depth);
+}
+
+static void check_filter_recurse(struct upload_pack_data *data,
+                                struct list_objects_filter_options *opts)
+{
+       size_t i;
+
+       check_one_filter(data, opts);
+       if (opts->choice != LOFC_COMBINE)
+               return;
+
+       for (i = 0; i < opts->sub_nr; i++)
+               check_filter_recurse(data, &opts->sub[i]);
+}
+
+static void die_if_using_banned_filter(struct upload_pack_data *data)
+{
+       check_filter_recurse(data, &data->filter_options);
+}
+
 static void receive_needs(struct upload_pack_data *data,
                          struct packet_reader *reader)
 {
@@ -1013,6 +1075,7 @@ static void receive_needs(struct upload_pack_data *data,
                                die("git upload-pack: filtering capability not negotiated");
                        list_objects_filter_die_if_populated(&data->filter_options);
                        parse_list_objects_filter(&data->filter_options, arg);
+                       die_if_using_banned_filter(data);
                        continue;
                }
 
@@ -1170,6 +1233,41 @@ static int find_symref(const char *refname, const struct object_id *oid,
        return 0;
 }
 
+static int parse_object_filter_config(const char *var, const char *value,
+                                      struct upload_pack_data *data)
+{
+       struct strbuf buf = STRBUF_INIT;
+       const char *sub, *key;
+       size_t sub_len;
+
+       if (parse_config_key(var, "uploadpackfilter", &sub, &sub_len, &key))
+               return 0;
+
+       if (!sub) {
+               if (!strcmp(key, "allow"))
+                       data->allow_filter_fallback = git_config_bool(var, value);
+               return 0;
+       }
+
+       strbuf_add(&buf, sub, sub_len);
+
+       if (!strcmp(key, "allow"))
+               string_list_insert(&data->allowed_filters, buf.buf)->util =
+                       (void *)(intptr_t)git_config_bool(var, value);
+       else if (!strcmp(buf.buf, "tree") && !strcmp(key, "maxdepth")) {
+               if (!value) {
+                       strbuf_release(&buf);
+                       return config_error_nonbool(var);
+               }
+               string_list_insert(&data->allowed_filters, buf.buf)->util =
+                       (void *)(intptr_t)1;
+               data->tree_filter_max_depth = git_config_ulong(var, value);
+       }
+
+       strbuf_release(&buf);
+       return 0;
+}
+
 static int upload_pack_config(const char *var, const char *value, void *cb_data)
 {
        struct upload_pack_data *data = cb_data;
@@ -1209,6 +1307,8 @@ static int upload_pack_config(const char *var, const char *value, void *cb_data)
                        return git_config_string(&data->pack_objects_hook, var, value);
        }
 
+       parse_object_filter_config(var, value, data);
+
        return parse_hide_refs_config(var, value, "uploadpack");
 }
 
@@ -1389,6 +1489,7 @@ static void process_args(struct packet_reader *request,
                if (data->allow_filter && skip_prefix(arg, "filter ", &p)) {
                        list_objects_filter_die_if_populated(&data->filter_options);
                        parse_list_objects_filter(&data->filter_options, p);
+                       die_if_using_banned_filter(data);
                        continue;
                }
 
@@ -1423,7 +1524,8 @@ static int process_haves(struct upload_pack_data *data, struct oid_array *common
        for (i = 0; i < data->haves.nr; i++) {
                const struct object_id *oid = &data->haves.oid[i];
 
-               if (!has_object_file(oid))
+               if (!has_object_file_with_flags(oid,
+                                               OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT))
                        continue;
 
                oid_array_append(common, oid);
@@ -1521,7 +1623,7 @@ enum fetch_state {
        FETCH_DONE,
 };
 
-int upload_pack_v2(struct repository *r, struct argv_array *keys,
+int upload_pack_v2(struct repository *r, struct strvec *keys,
                   struct packet_reader *request)
 {
        enum fetch_state state = FETCH_PROCESS_ARGS;
index 4bafe16a22c37d3eac65690cc6f1cc68476cf94c..27ddcdc6cb071fd916ad48219a520d8973e961e0 100644 (file)
@@ -11,9 +11,9 @@ struct upload_pack_options {
 void upload_pack(struct upload_pack_options *options);
 
 struct repository;
-struct argv_array;
+struct strvec;
 struct packet_reader;
-int upload_pack_v2(struct repository *r, struct argv_array *keys,
+int upload_pack_v2(struct repository *r, struct strvec *keys,
                   struct packet_reader *request);
 
 struct strbuf;
index 1df884ef0bbfbba5a751eafc1922369ad818fce5..fde02f225b2b9ed17a8246913c3bddfa6483c98b 100644 (file)
@@ -46,10 +46,14 @@ PATTERNS("elixir",
         /* Not real operators, but should be grouped */
         "|:?%[A-Za-z0-9_.]\\{\\}?"),
 IPATTERN("fortran",
+        /* Don't match comment lines */
         "!^([C*]|[ \t]*!)\n"
+        /* Don't match 'module procedure' lines */
         "!^[ \t]*MODULE[ \t]+PROCEDURE[ \t]\n"
+        /* Program, module, block data */
         "^[ \t]*((END[ \t]+)?(PROGRAM|MODULE|BLOCK[ \t]+DATA"
-               "|([^'\" \t]+[ \t]+)*(SUBROUTINE|FUNCTION))[ \t]+[A-Z].*)$",
+               /* Subroutines and functions */
+               "|([^!'\" \t]+[ \t]+)*(SUBROUTINE|FUNCTION))[ \t]+[A-Z].*)$",
         /* -- */
         "[a-zA-Z][a-zA-Z0-9_]*"
         "|\\.([Ee][Qq]|[Nn][Ee]|[Gg][TtEe]|[Ll][TtEe]|[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]|[Aa][Nn][Dd]|[Oo][Rr]|[Nn]?[Ee][Qq][Vv]|[Nn][Oo][Tt])\\."
index cba2e545982c0487160244100af44a14d2e9a898..62217b4a6b26b4efad52643d25f21e7c98a2fa3e 100644 (file)
@@ -49,10 +49,8 @@ static struct worktree *get_main_worktree(void)
        struct worktree *worktree = NULL;
        struct strbuf worktree_path = STRBUF_INIT;
 
-       strbuf_add_absolute_path(&worktree_path, get_git_common_dir());
-       if (!strbuf_strip_suffix(&worktree_path, "/.git/.") && /* in .git */
-           !strbuf_strip_suffix(&worktree_path, "/.git")) /* in worktree */
-               strbuf_strip_suffix(&worktree_path, "/."); /* in bare repo */
+       strbuf_add_real_path(&worktree_path, get_git_common_dir());
+       strbuf_strip_suffix(&worktree_path, "/.git");
 
        worktree = xcalloc(1, sizeof(*worktree));
        worktree->path = strbuf_detach(&worktree_path, NULL);
@@ -66,8 +64,6 @@ static struct worktree *get_main_worktree(void)
        worktree->is_bare = (is_bare_repository_cfg == 1) ||
                is_bare_repository();
        add_head_info(worktree);
-
-       strbuf_release(&worktree_path);
        return worktree;
 }
 
@@ -84,16 +80,8 @@ static struct worktree *get_linked_worktree(const char *id)
        if (strbuf_read_file(&worktree_path, path.buf, 0) <= 0)
                /* invalid gitdir file */
                goto done;
-
        strbuf_rtrim(&worktree_path);
-       if (!strbuf_strip_suffix(&worktree_path, "/.git")) {
-               strbuf_reset(&worktree_path);
-               strbuf_add_absolute_path(&worktree_path, ".");
-               strbuf_strip_suffix(&worktree_path, "/.");
-       }
-
-       strbuf_reset(&path);
-       strbuf_addf(&path, "%s/worktrees/%s/HEAD", get_git_common_dir(), id);
+       strbuf_strip_suffix(&worktree_path, "/.git");
 
        worktree = xcalloc(1, sizeof(*worktree));
        worktree->path = strbuf_detach(&worktree_path, NULL);
index c560cbe860a42daa136e16195535ef10e2ab0a9f..bb0f9120de40f70578867dece592eeecdf0e1e23 100644 (file)
@@ -8,7 +8,7 @@
 #include "diffcore.h"
 #include "quote.h"
 #include "run-command.h"
-#include "argv-array.h"
+#include "strvec.h"
 #include "remote.h"
 #include "refs.h"
 #include "submodule.h"
@@ -703,7 +703,7 @@ static void wt_status_collect_untracked(struct wt_status *s)
        if (!s->show_untracked_files)
                return;
 
-       memset(&dir, 0, sizeof(dir));
+       dir_init(&dir);
        if (s->show_untracked_files != SHOW_ALL_UNTRACKED_FILES)
                dir.flags |=
                        DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
@@ -724,19 +724,15 @@ static void wt_status_collect_untracked(struct wt_status *s)
                struct dir_entry *ent = dir.entries[i];
                if (index_name_is_other(istate, ent->name, ent->len))
                        string_list_insert(&s->untracked, ent->name);
-               free(ent);
        }
 
        for (i = 0; i < dir.ignored_nr; i++) {
                struct dir_entry *ent = dir.ignored[i];
                if (index_name_is_other(istate, ent->name, ent->len))
                        string_list_insert(&s->ignored, ent->name);
-               free(ent);
        }
 
-       free(dir.entries);
-       free(dir.ignored);
-       clear_directory(&dir);
+       dir_clear(&dir);
 
        if (advice_status_u_option)
                s->untracked_in_ms = (getnanotime() - t_begin) / 1000000;
@@ -913,17 +909,16 @@ static void wt_longstatus_print_submodule_summary(struct wt_status *s, int uncom
        struct strbuf summary = STRBUF_INIT;
        char *summary_content;
 
-       argv_array_pushf(&sm_summary.env_array, "GIT_INDEX_FILE=%s",
-                        s->index_file);
+       strvec_pushf(&sm_summary.env_array, "GIT_INDEX_FILE=%s", s->index_file);
 
-       argv_array_push(&sm_summary.args, "submodule");
-       argv_array_push(&sm_summary.args, "summary");
-       argv_array_push(&sm_summary.args, uncommitted ? "--files" : "--cached");
-       argv_array_push(&sm_summary.args, "--for-status");
-       argv_array_push(&sm_summary.args, "--summary-limit");
-       argv_array_pushf(&sm_summary.args, "%d", s->submodule_summary);
+       strvec_push(&sm_summary.args, "submodule");
+       strvec_push(&sm_summary.args, "summary");
+       strvec_push(&sm_summary.args, uncommitted ? "--files" : "--cached");
+       strvec_push(&sm_summary.args, "--for-status");
+       strvec_push(&sm_summary.args, "--summary-limit");
+       strvec_pushf(&sm_summary.args, "%d", s->submodule_summary);
        if (!uncommitted)
-               argv_array_push(&sm_summary.args, s->amend ? "HEAD^" : "HEAD");
+               strvec_push(&sm_summary.args, s->amend ? "HEAD^" : "HEAD");
 
        sm_summary.git_cmd = 1;
        sm_summary.no_stdin = 1;
@@ -1673,13 +1668,13 @@ void wt_status_get_state(struct repository *r,
                state->merge_in_progress = 1;
        } else if (wt_status_check_rebase(NULL, state)) {
                ;               /* all set */
-       } else if (!stat(git_path_cherry_pick_head(r), &st) &&
-                       !get_oid("CHERRY_PICK_HEAD", &oid)) {
+       } else if (refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD") &&
+                  !get_oid("CHERRY_PICK_HEAD", &oid)) {
                state->cherry_pick_in_progress = 1;
                oidcpy(&state->cherry_pick_head_oid, &oid);
        }
        wt_status_check_bisect(NULL, state);
-       if (!stat(git_path_revert_head(r), &st) &&
+       if (refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD") &&
            !get_oid("REVERT_HEAD", &oid)) {
                state->revert_in_progress = 1;
                oidcpy(&state->revert_head_oid, &oid);
@@ -2035,7 +2030,7 @@ static void wt_porcelain_print(struct wt_status *s)
  *   [# branch.upstream <upstream><eol>
  *   [# branch.ab +<ahead> -<behind><eol>]]
  *
- *      <commit> ::= the current commit hash or the the literal
+ *      <commit> ::= the current commit hash or the literal
  *                   "(initial)" to indicate an initialized repo
  *                   with no commits.
  *