diff options
116 files changed, 1254 insertions, 405 deletions
diff --git a/.github/workflows/check-whitespace.yml b/.github/workflows/check-whitespace.yml index ad3466ad16..a58e2dc8ad 100644 --- a/.github/workflows/check-whitespace.yml +++ b/.github/workflows/check-whitespace.yml @@ -9,42 +9,83 @@ on: pull_request: types: [opened, synchronize] +# Avoid unnecessary builds. Unlike the main CI jobs, these are not +# ci-configurable (but could be). +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: check-whitespace: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 - name: git log --check id: check_out run: | - log= + baseSha=${{github.event.pull_request.base.sha}} + problems=() commit= - while read dash etc + commitText= + commitTextmd= + goodparent= + while read dash sha etc do case "${dash}" in "---") - commit="${etc}" + if test -z "${commit}" + then + goodparent=${sha} + fi + commit="${sha}" + commitText="${sha} ${etc}" + commitTextmd="[${sha}](https://github.com/${{ github.repository }}/commit/${sha}) ${etc}" ;; "") ;; *) if test -n "${commit}" then - log="${log}\n${commit}" + problems+=("1) --- ${commitTextmd}") echo "" - echo "--- ${commit}" + echo "--- ${commitText}" + commit= fi - commit= - log="${log}\n${dash} ${etc}" - echo "${dash} ${etc}" + case "${dash}" in + *:[1-9]*:) # contains file and line number information + dashend=${dash#*:} + problems+=("[${dash}](https://github.com/${{ github.repository }}/blob/${{github.event.pull_request.head.ref}}/${dash%%:*}#L${dashend%:}) ${sha} ${etc}") + ;; + *) + problems+=("\`${dash} ${sha} ${etc}\`") + ;; + esac + echo "${dash} ${sha} ${etc}" ;; esac - done <<< $(git log --check --pretty=format:"---% h% s" ${{github.event.pull_request.base.sha}}..) + done <<< $(git log --check --pretty=format:"---% h% s" ${baseSha}..) - if test -n "${log}" + if test ${#problems[*]} -gt 0 then + if test -z "${commit}" + then + goodparent=${baseSha: 0:7} + fi + echo "🛑 Please review the Summary output for further information." + echo "### :x: A whitespace issue was found in one or more of the commits." >$GITHUB_STEP_SUMMARY + echo "" >>$GITHUB_STEP_SUMMARY + echo "Run these commands to correct the problem:" >>$GITHUB_STEP_SUMMARY + echo "1. \`git rebase --whitespace=fix ${goodparent}\`" >>$GITHUB_STEP_SUMMARY + echo "1. \`git push --force\`" >>$GITHUB_STEP_SUMMARY + echo " " >>$GITHUB_STEP_SUMMARY + echo "Errors:" >>$GITHUB_STEP_SUMMARY + for i in "${problems[@]}" + do + echo "${i}" >>$GITHUB_STEP_SUMMARY + done + exit 2 fi diff --git a/.github/workflows/l10n.yml b/.github/workflows/l10n.yml index f7ea0f00a4..6c3849658a 100644 --- a/.github/workflows/l10n.yml +++ b/.github/workflows/l10n.yml @@ -2,6 +2,12 @@ name: git-l10n on: [push, pull_request_target] +# Avoid unnecessary builds. Unlike the main CI jobs, these are not +# ci-configurable (but could be). +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: git-po-helper: if: >- diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e67847a682..f2fd6cf9cd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,6 +11,7 @@ jobs: runs-on: ubuntu-latest outputs: enabled: ${{ steps.check-ref.outputs.enabled }}${{ steps.skip-if-redundant.outputs.enabled }} + skip_concurrent: ${{ steps.check-ref.outputs.skip_concurrent }} steps: - name: try to clone ci-config branch run: | @@ -34,7 +35,15 @@ jobs: then enabled=no fi + + skip_concurrent=yes + if test -x config-repo/ci/config/skip-concurrent && + ! config-repo/ci/config/skip-concurrent '${{ github.ref }}' + then + skip_concurrent=no + fi echo "enabled=$enabled" >>$GITHUB_OUTPUT + echo "skip_concurrent=$skip_concurrent" >>$GITHUB_OUTPUT - name: skip if the commit or tree was already tested id: skip-if-redundant uses: actions/github-script@v6 @@ -82,6 +91,9 @@ jobs: needs: ci-config if: needs.ci-config.outputs.enabled == 'yes' runs-on: windows-latest + concurrency: + group: windows-build-${{ github.ref }} + cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - uses: actions/checkout@v3 - uses: git-for-windows/setup-git-for-windows-sdk@v1 @@ -101,11 +113,14 @@ jobs: windows-test: name: win test runs-on: windows-latest - needs: [windows-build] + needs: [ci-config, windows-build] strategy: fail-fast: false matrix: nr: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + concurrency: + group: windows-test-${{ matrix.nr }}-${{ github.ref }} + cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - name: download tracked files and build artifacts uses: actions/download-artifact@v3 @@ -132,11 +147,14 @@ jobs: vs-build: name: win+VS build needs: ci-config - if: needs.ci-config.outputs.enabled == 'yes' + if: github.event.repository.owner.login == 'git-for-windows' && needs.ci-config.outputs.enabled == 'yes' env: NO_PERL: 1 GIT_CONFIG_PARAMETERS: "'user.name=CI' 'user.email=ci@git'" runs-on: windows-latest + concurrency: + group: vs-build-${{ github.ref }} + cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - uses: actions/checkout@v3 - uses: git-for-windows/setup-git-for-windows-sdk@v1 @@ -184,11 +202,14 @@ jobs: vs-test: name: win+VS test runs-on: windows-latest - needs: vs-build + needs: [ci-config, vs-build] strategy: fail-fast: false matrix: nr: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + concurrency: + group: vs-test-${{ matrix.nr }}-${{ github.ref }} + cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - uses: git-for-windows/setup-git-for-windows-sdk@v1 - name: download tracked files and build artifacts @@ -218,6 +239,9 @@ jobs: name: ${{matrix.vector.jobname}} (${{matrix.vector.pool}}) needs: ci-config if: needs.ci-config.outputs.enabled == 'yes' + concurrency: + group: ${{ matrix.vector.jobname }}-${{ matrix.vector.pool }}-${{ github.ref }} + cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} strategy: fail-fast: false matrix: @@ -277,6 +301,9 @@ jobs: name: ${{matrix.vector.jobname}} (${{matrix.vector.image}}) needs: ci-config if: needs.ci-config.outputs.enabled == 'yes' + concurrency: + group: dockerized-${{ matrix.vector.jobname }}-${{ matrix.vector.image }}-${{ github.ref }} + cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} strategy: fail-fast: false matrix: @@ -318,6 +345,9 @@ jobs: env: jobname: StaticAnalysis runs-on: ubuntu-22.04 + concurrency: + group: static-analysis-${{ github.ref }} + cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - uses: actions/checkout@v3 - run: ci/install-dependencies.sh @@ -329,6 +359,9 @@ jobs: env: jobname: sparse runs-on: ubuntu-20.04 + concurrency: + group: sparse-${{ github.ref }} + cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - name: Download a current `sparse` package # Ubuntu's `sparse` version is too old for us @@ -347,6 +380,9 @@ jobs: name: documentation needs: ci-config if: needs.ci-config.outputs.enabled == 'yes' + concurrency: + group: documentation-${{ github.ref }} + cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} env: jobname: Documentation runs-on: ubuntu-latest diff --git a/Documentation/RelNotes/2.30.8.txt b/Documentation/RelNotes/2.30.8.txt new file mode 100644 index 0000000000..38c23e0345 --- /dev/null +++ b/Documentation/RelNotes/2.30.8.txt @@ -0,0 +1,52 @@ +Git v2.30.8 Release Notes +========================= + +This release addresses the security issues CVE-2023-22490 and +CVE-2023-23946. + + +Fixes since v2.30.7 +------------------- + + * CVE-2023-22490: + + Using a specially-crafted repository, Git can be tricked into using + its local clone optimization even when using a non-local transport. + Though Git will abort local clones whose source $GIT_DIR/objects + directory contains symbolic links (c.f., CVE-2022-39253), the objects + directory itself may still be a symbolic link. + + These two may be combined to include arbitrary files based on known + paths on the victim's filesystem within the malicious repository's + working copy, allowing for data exfiltration in a similar manner as + CVE-2022-39253. + + * CVE-2023-23946: + + By feeding a crafted input to "git apply", a path outside the + working tree can be overwritten as the user who is running "git + apply". + + * A mismatched type in `attr.c::read_attr_from_index()` which could + cause Git to errantly reject attributes on Windows and 32-bit Linux + has been corrected. + +Credit for finding CVE-2023-22490 goes to yvvdwf, and the fix was +developed by Taylor Blau, with additional help from others on the +Git security mailing list. + +Credit for finding CVE-2023-23946 goes to Joern Schneeweisz, and the +fix was developed by Patrick Steinhardt. + + +Johannes Schindelin (1): + attr: adjust a mismatched data type + +Patrick Steinhardt (1): + apply: fix writing behind newly created symbolic links + +Taylor Blau (3): + t5619: demonstrate clone_local() with ambiguous transport + clone: delay picking a transport until after get_repo_path() + dir-iterator: prevent top-level symlinks without FOLLOW_SYMLINKS + diff --git a/Documentation/RelNotes/2.30.9.txt b/Documentation/RelNotes/2.30.9.txt new file mode 100644 index 0000000000..708d626ce6 --- /dev/null +++ b/Documentation/RelNotes/2.30.9.txt @@ -0,0 +1,43 @@ +Git v2.30.9 Release Notes +========================= + +This release addresses the security issues CVE-2023-25652, +CVE-2023-25815, and CVE-2023-29007. + + +Fixes since v2.30.8 +------------------- + + * CVE-2023-25652: + + By feeding specially crafted input to `git apply --reject`, a + path outside the working tree can be overwritten with partially + controlled contents (corresponding to the rejected hunk(s) from + the given patch). + + * CVE-2023-25815: + + When Git is compiled with runtime prefix support and runs without + translated messages, it still used the gettext machinery to + display messages, which subsequently potentially looked for + translated messages in unexpected places. This allowed for + malicious placement of crafted messages. + + * CVE-2023-29007: + + When renaming or deleting a section from a configuration file, + certain malicious configuration values may be misinterpreted as + the beginning of a new configuration section, leading to arbitrary + configuration injection. + +Credit for finding CVE-2023-25652 goes to Ry0taK, and the fix was +developed by Taylor Blau, Junio C Hamano and Johannes Schindelin, +with the help of Linus Torvalds. + +Credit for finding CVE-2023-25815 goes to Maxime Escourbiac and +Yassine BENGANA of Michelin, and the fix was developed by Johannes +Schindelin. + +Credit for finding CVE-2023-29007 goes to André Baptista and VÃtor Pinho +of Ethiack, and the fix was developed by Taylor Blau, and Johannes +Schindelin, with help from Jeff King, and Patrick Steinhardt. diff --git a/Documentation/RelNotes/2.31.7.txt b/Documentation/RelNotes/2.31.7.txt new file mode 100644 index 0000000000..dd44d5bc62 --- /dev/null +++ b/Documentation/RelNotes/2.31.7.txt @@ -0,0 +1,6 @@ +Git v2.31.7 Release Notes +========================= + +This release merges up the fixes that appear in v2.30.8 to +address the security issues CVE-2023-22490 and CVE-2023-23946; +see the release notes for that version for details. diff --git a/Documentation/RelNotes/2.31.8.txt b/Documentation/RelNotes/2.31.8.txt new file mode 100644 index 0000000000..0aa3080780 --- /dev/null +++ b/Documentation/RelNotes/2.31.8.txt @@ -0,0 +1,6 @@ +Git v2.31.8 Release Notes +========================= + +This release merges the fixes that appear in v2.30.9 to address the +security issues CVE-2023-25652, CVE-2023-25815, and CVE-2023-29007; +see the release notes for that version for details. diff --git a/Documentation/RelNotes/2.32.6.txt b/Documentation/RelNotes/2.32.6.txt new file mode 100644 index 0000000000..fd659612e3 --- /dev/null +++ b/Documentation/RelNotes/2.32.6.txt @@ -0,0 +1,6 @@ +Git v2.32.6 Release Notes +========================= + +This release merges up the fixes that appear in v2.30.8 and v2.31.7 +to address the security issues CVE-2023-22490 and CVE-2023-23946; +see the release notes for these versions for details. diff --git a/Documentation/RelNotes/2.32.7.txt b/Documentation/RelNotes/2.32.7.txt new file mode 100644 index 0000000000..7bb35388b5 --- /dev/null +++ b/Documentation/RelNotes/2.32.7.txt @@ -0,0 +1,7 @@ +Git v2.32.7 Release Notes +========================= + +This release merges the fixes that appear in v2.30.9 and v2.31.8 to +address the security issues CVE-2023-25652, CVE-2023-25815, and +CVE-2023-29007; see the release notes for these versions for +details. diff --git a/Documentation/RelNotes/2.33.7.txt b/Documentation/RelNotes/2.33.7.txt new file mode 100644 index 0000000000..078a837cb4 --- /dev/null +++ b/Documentation/RelNotes/2.33.7.txt @@ -0,0 +1,7 @@ +Git v2.33.7 Release Notes +========================= + +This release merges up the fixes that appear in v2.30.8, v2.31.7 +and v2.32.6 to address the security issues CVE-2023-22490 and +CVE-2023-23946; see the release notes for these versions for +details. diff --git a/Documentation/RelNotes/2.33.8.txt b/Documentation/RelNotes/2.33.8.txt new file mode 100644 index 0000000000..d8cf4c7f3a --- /dev/null +++ b/Documentation/RelNotes/2.33.8.txt @@ -0,0 +1,7 @@ +Git v2.33.8 Release Notes +========================= + +This release merges the fixes that appear in v2.30.9, v2.31.8 and +v2.32.7 to address the security issues CVE-2023-25652, +CVE-2023-25815, and CVE-2023-29007; see the release notes for these +versions for details. diff --git a/Documentation/RelNotes/2.34.7.txt b/Documentation/RelNotes/2.34.7.txt new file mode 100644 index 0000000000..88898adacc --- /dev/null +++ b/Documentation/RelNotes/2.34.7.txt @@ -0,0 +1,7 @@ +Git v2.34.7 Release Notes +========================= + +This release merges up the fixes that appear in v2.30.8, v2.31.7, +v2.32.6 and v2.33.7 to address the security issues CVE-2023-22490 +and CVE-2023-23946; see the release notes for these versions +for details. diff --git a/Documentation/RelNotes/2.34.8.txt b/Documentation/RelNotes/2.34.8.txt new file mode 100644 index 0000000000..2b5bd7d9a3 --- /dev/null +++ b/Documentation/RelNotes/2.34.8.txt @@ -0,0 +1,7 @@ +Git v2.34.8 Release Notes +========================= + +This release merges the fixes that appear in v2.30.9, v2.31.8, +v2.32.7 and v2.33.8 to address the security issues CVE-2023-25652, +CVE-2023-25815, and CVE-2023-29007; see the release notes for these +versions for details. diff --git a/Documentation/RelNotes/2.35.7.txt b/Documentation/RelNotes/2.35.7.txt new file mode 100644 index 0000000000..42baabfc3b --- /dev/null +++ b/Documentation/RelNotes/2.35.7.txt @@ -0,0 +1,7 @@ +Git v2.35.7 Release Notes +========================= + +This release merges up the fixes that appear in v2.30.8, v2.31.7, +v2.32.6, v2.33.7 and v2.34.7 to address the security issues +CVE-2023-22490 and CVE-2023-23946; see the release notes for +these versions for details. diff --git a/Documentation/RelNotes/2.35.8.txt b/Documentation/RelNotes/2.35.8.txt new file mode 100644 index 0000000000..3c9c094c2b --- /dev/null +++ b/Documentation/RelNotes/2.35.8.txt @@ -0,0 +1,7 @@ +Git v2.35.8 Release Notes +========================= + +This release merges the fixes that appear in v2.30.9, v2.31.8, +v2.32.7, v2.33.8 and v2.34.8 to address the security issues +CVE-2023-25652, CVE-2023-25815, and CVE-2023-29007; see the release +notes for these versions for details. diff --git a/Documentation/RelNotes/2.36.5.txt b/Documentation/RelNotes/2.36.5.txt new file mode 100644 index 0000000000..8a098c7916 --- /dev/null +++ b/Documentation/RelNotes/2.36.5.txt @@ -0,0 +1,7 @@ +Git v2.36.5 Release Notes +========================= + +This release merges up the fixes that appear in v2.30.8, v2.31.7, +v2.32.6, v2.33.7, v2.34.7 and v2.35.7 to address the security +issues CVE-2023-22490 and CVE-2023-23946; see the release notes +for these versions for details. diff --git a/Documentation/RelNotes/2.36.6.txt b/Documentation/RelNotes/2.36.6.txt new file mode 100644 index 0000000000..e1edebcc43 --- /dev/null +++ b/Documentation/RelNotes/2.36.6.txt @@ -0,0 +1,7 @@ +Git v2.36.6 Release Notes +========================= + +This release merges the fixes that appear in v2.30.9, v2.31.8, +v2.32.7, v2.33.8, v2.34.8 and v2.35.8 to address the security issues +CVE-2023-25652, CVS-2023-25815, and CVE-2023-29007; see the release +notes for these versions for details. diff --git a/Documentation/RelNotes/2.37.6.txt b/Documentation/RelNotes/2.37.6.txt new file mode 100644 index 0000000000..51dc149711 --- /dev/null +++ b/Documentation/RelNotes/2.37.6.txt @@ -0,0 +1,7 @@ +Git v2.37.6 Release Notes +========================= + +This release merges up the fixes that appear in v2.30.8, v2.31.7, +v2.32.6, v2.33.7, v2.34.7, v2.35.7 and v2.36.5 to address the +security issues CVE-2023-22490 and CVE-2023-23946; see the release +notes for these versions for details. diff --git a/Documentation/RelNotes/2.37.7.txt b/Documentation/RelNotes/2.37.7.txt new file mode 100644 index 0000000000..4b8165f4b5 --- /dev/null +++ b/Documentation/RelNotes/2.37.7.txt @@ -0,0 +1,7 @@ +Git v2.37.7 Release Notes +========================= + +This release merges up the fix that appears in v2.30.9, v2.31.8, +v2.32.7, v2.33.8, v2.34.8, v2.35.8 and v2.36.6 to address the +security issues CVE-2023-25652, CVE-2023-25815, and CVE-2023-29007; +see the release notes for these versions for details. diff --git a/Documentation/RelNotes/2.38.4.txt b/Documentation/RelNotes/2.38.4.txt new file mode 100644 index 0000000000..fdfde22022 --- /dev/null +++ b/Documentation/RelNotes/2.38.4.txt @@ -0,0 +1,7 @@ +Git v2.38.4 Release Notes +========================= + +This release merges up the fixes that appear in v2.30.8, v2.31.7, +v2.32.6, v2.33.7, v2.34.7, v2.35.7, v2.36.5 and v2.37.6 to +address the security issues CVE-2023-22490 and CVE-2023-23946; +see the release notes for these versions for details. diff --git a/Documentation/RelNotes/2.38.5.txt b/Documentation/RelNotes/2.38.5.txt new file mode 100644 index 0000000000..2d1f3b1249 --- /dev/null +++ b/Documentation/RelNotes/2.38.5.txt @@ -0,0 +1,8 @@ +Git v2.38.5 Release Notes +========================= + +This release merges up the fix that appears in v2.30.9, v2.31.8, +v2.32.7, v2.33.8, v2.34.8, v2.35.8, v2.36.6 and v2.37.7 to address +the security issues CVE-2023-25652, CVE-2023-25815, and +CVE-2023-29007; see the release notes for these versions for +details. diff --git a/Documentation/RelNotes/2.39.2.txt b/Documentation/RelNotes/2.39.2.txt new file mode 100644 index 0000000000..ebb9900bc5 --- /dev/null +++ b/Documentation/RelNotes/2.39.2.txt @@ -0,0 +1,7 @@ +Git v2.39.2 Release Notes +========================= + +This release merges up the fixes that appear in v2.30.8, v2.31.7, +v2.32.6, v2.33.7, v2.34.7, v2.35.7, v2.36.5, v2.37.6 and v2.38.4 +to address the security issues CVE-2023-22490 and CVE-2023-23946; +see the release notes for these versions for details. diff --git a/Documentation/RelNotes/2.39.3.txt b/Documentation/RelNotes/2.39.3.txt new file mode 100644 index 0000000000..66351b65c2 --- /dev/null +++ b/Documentation/RelNotes/2.39.3.txt @@ -0,0 +1,64 @@ +Git v2.39.3 Release Notes +========================= + +This release merges up the fix that appears in v2.30.9, v2.31.8, +v2.32.7, v2.33.8, v2.34.8, v2.35.8, v2.36.6, v2.37.7 and v2.38.5 to +address the security issues CVE-2023-25652, CVE-2023-25815, and +CVE-2023-29007; see the release notes for these versions for +details. + +This release also merges fixes that have accumulated on the 'master' +front to prepare for the 2.40 release that are still relevant to +2.39.x maintenance track. + +Fixes since v2.39.2 +------------------- + + * Stop running win+VS build by default. + + * CI updates. We probably want a clean-up to move the long shell + script embedded in yaml file into a separate file, but that can + come later. + + * Avoid unnecessary builds in CI, with settings configured in + ci-config. + + * Redefining system functions for a few functions did not follow our + usual "implement git_foo() and #define foo(args) git_foo(args)" + pattern, which has broken build for some folks. + + * Deal with a few deprecation warning from cURL library. + + * Newer regex library macOS stopped enabling GNU-like enhanced BRE, + where '\(A\|B\)' works as alternation, unless explicitly asked with + the REG_ENHANCED flag. "git grep" now can be compiled to do so, to + retain the old behaviour. + + * When given a pattern that matches an empty string at the end of a + line, the code to parse the "git diff" line-ranges fell into an + infinite loop, which has been corrected. + + * Fix the sequence to fsync $GIT_DIR/packed-refs file that forgot to + flush its output to the disk.. + + * "git diff --relative" did not mix well with "git diff --ext-diff", + which has been corrected. + + * The logic to see if we are using the "cone" mode by checking the + sparsity patterns has been tightened to avoid mistaking a pattern + that names a single file as specifying a cone. + + * Doc update for environment variables set when hooks are invoked. + + * Document ORIG_HEAD a bit more. + + * "git ls-tree --format='%(path) %(path)' $tree $path" showed the + path three times, which has been corrected. + + * Document that "branch -f <branch>" disables only the safety to + avoid recreating an existing branch. + + * Clarify how "checkout -b/-B" and "git branch [-f]" are similar but + different in the documentation. + +Also contains minor documentation updates and code clean-ups. diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index 12c5f84e3b..2aaf13b45d 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -123,6 +123,10 @@ OPTIONS points to a valid commit. In combination with `-m` (or `--move`), allow renaming the branch even if the new branch name already exists, the same applies for `-c` (or `--copy`). ++ +Note that 'git branch -f <branchname> [<start-point>]', even with '-f', +refuses to change an existing branch `<branchname>` that is checked out +in another worktree linked to the same repository. -m:: --move:: diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt index 4cb9d555b4..dcff44196d 100644 --- a/Documentation/git-checkout.txt +++ b/Documentation/git-checkout.txt @@ -146,14 +146,16 @@ on your side branch as `theirs` (i.e. "one contributor's work on top of it"). -b <new-branch>:: - Create a new branch named `<new-branch>` and start it at - `<start-point>`; see linkgit:git-branch[1] for details. + Create a new branch named `<new-branch>`, start it at + `<start-point>`, and check the resulting branch out; + see linkgit:git-branch[1] for details. -B <new-branch>:: - Creates the branch `<new-branch>` and start it at `<start-point>`; - if it already exists, then reset it to `<start-point>`. This is - equivalent to running "git branch" with "-f"; see - linkgit:git-branch[1] for details. + Creates the branch `<new-branch>`, start it at `<start-point>`; + if it already exists, then reset it to `<start-point>`. And then + check the resulting branch out. This is equivalent to running + "git branch" with "-f" followed by "git checkout" of that branch; + see linkgit:git-branch[1] for details. -t:: --track[=(direct|inherit)]:: diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index 1e8ac9df60..fdcad3d200 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -219,7 +219,7 @@ again, this time exercising more care about matching up context lines. ------------ $ git cherry-pick topic^ <1> $ git diff <2> -$ git reset --merge ORIG_HEAD <3> +$ git cherry-pick --abort <3> $ git cherry-pick -Xpatience topic^ <4> ------------ <1> apply the change that would be shown by `git show topic^`. diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt index 2d6a1391c8..0aeff572a5 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.txt @@ -37,7 +37,8 @@ Then "`git merge topic`" will replay the changes made on the `topic` branch since it diverged from `master` (i.e., `E`) until its current commit (`C`) on top of `master`, and record the result in a new commit along with the names of the two parent commits and -a log message from the user describing the changes. +a log message from the user describing the changes. Before the operation, +`ORIG_HEAD` is set to the tip of the current branch (`C`). ------------ A---B---C topic diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index f9675bd24e..d811c1cf44 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -38,6 +38,13 @@ The current branch is reset to `<upstream>` or `<newbase>` if the `git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set to point at the tip of the branch before the reset. +[NOTE] +`ORIG_HEAD` is not guaranteed to still point to the previous branch tip +at the end of the rebase if other commands that write that pseudo-ref +(e.g. `git reset`) are used during the rebase. The previous branch tip, +however, is accessible using the reflog of the current branch +(i.e. `@{1}`, see linkgit:gitrevisions[7]). + The commits that were previously saved into the temporary area are then reapplied to the current branch, one by one, in order. Note that any commits in `HEAD` which introduce the same textual changes as a commit diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt index 01cb4c9b9c..79ad5643ee 100644 --- a/Documentation/git-reset.txt +++ b/Documentation/git-reset.txt @@ -49,7 +49,8 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode. 'git reset' [<mode>] [<commit>]:: This form resets the current branch head to `<commit>` and possibly updates the index (resetting it to the tree of `<commit>`) and - the working tree depending on `<mode>`. If `<mode>` is omitted, + the working tree depending on `<mode>`. Before the operation, `ORIG_HEAD` + is set to the tip of the current branch. If `<mode>` is omitted, defaults to `--mixed`. The `<mode>` must be one of the following: + -- diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt index a16e62bc8c..62908602e7 100644 --- a/Documentation/githooks.txt +++ b/Documentation/githooks.txt @@ -27,6 +27,18 @@ repository. An exception are hooks triggered during a push ('pre-receive', 'update', 'post-receive', 'post-update', 'push-to-checkout') which are always executed in $GIT_DIR. +Environment variables, such as `GIT_DIR`, `GIT_WORK_TREE`, etc., are exported +so that Git commands run by the hook can correctly locate the repository. If +your hook needs to invoke Git commands in a foreign repository or in a +different working tree of the same repository, then it should clear these +environment variables so they do not interfere with Git operations at the +foreign location. For example: + +------------ +local_desc=$(git describe) +foreign_desc=$(unset $(git rev-parse --local-env-vars); git -C ../foreign-repo describe) +------------ + Hooks can get their arguments via the environment, command-line arguments, and stdin. See the documentation for each hook below for details. diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt index 0d2e55d781..9aa58052bc 100644 --- a/Documentation/revisions.txt +++ b/Documentation/revisions.txt @@ -49,7 +49,8 @@ characters and to avoid word splitting. `FETCH_HEAD` records the branch which you fetched from a remote repository with your last `git fetch` invocation. `ORIG_HEAD` is created by commands that move your `HEAD` in a drastic -way, to record the position of the `HEAD` before their operation, so that +way (`git am`, `git merge`, `git rebase`, `git reset`), +to record the position of the `HEAD` before their operation, so that you can easily change the tip of the branch back to the state before you ran them. `MERGE_HEAD` records the commit(s) which you are merging into your branch diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 1937bc6802..eec953731c 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.39.1 +DEF_VER=v2.39.3 LF=' ' @@ -139,7 +139,7 @@ Issues of note: not need that functionality, use NO_CURL to build without it. - Git requires version "7.19.4" or later of "libcurl" to build + Git requires version "7.19.5" or later of "libcurl" to build without NO_CURL. This version requirement may be bumped in the future. @@ -289,6 +289,10 @@ include shared.mak # Define NO_REGEX if your C library lacks regex support with REG_STARTEND # feature. # +# Define USE_ENHANCED_BASIC_REGULAR_EXPRESSIONS if your C library provides +# the flag REG_ENHANCED and you'd like to use it to enable enhanced basic +# regular expressions. +# # Define HAVE_DEV_TTY if your system can open /dev/tty to interact with the # user. # @@ -2040,6 +2044,11 @@ endif ifdef NO_REGEX COMPAT_CFLAGS += -Icompat/regex COMPAT_OBJS += compat/regex/regex.o +else +ifdef USE_ENHANCED_BASIC_REGULAR_EXPRESSIONS + COMPAT_CFLAGS += -DUSE_ENHANCED_BASIC_REGULAR_EXPRESSIONS + COMPAT_OBJS += compat/regcomp_enhanced.o +endif endif ifdef NATIVE_CRLF BASIC_CFLAGS += -DNATIVE_CRLF @@ -1 +1 @@ -Documentation/RelNotes/2.39.1.txt
\ No newline at end of file +Documentation/RelNotes/2.39.3.txt
\ No newline at end of file diff --git a/add-interactive.c b/add-interactive.c index ae1839c04a..00a0f6f96f 100644 --- a/add-interactive.c +++ b/add-interactive.c @@ -724,7 +724,7 @@ static int run_update(struct add_i_state *s, const struct pathspec *ps, } static void revert_from_diff(struct diff_queue_struct *q, - struct diff_options *opt, void *data) + struct diff_options *opt, void *data UNUSED) { int i, add_flags = ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE; @@ -2913,7 +2913,7 @@ static int apply_one_fragment(struct apply_state *state, break; case ' ': if (plen && (ws_rule & WS_BLANK_AT_EOF) && - ws_blank_line(patch + 1, plen, ws_rule)) + ws_blank_line(patch + 1, plen)) is_blank_context = 1; /* fallthrough */ case '-': @@ -2942,7 +2942,7 @@ static int apply_one_fragment(struct apply_state *state, (first == '+' ? 0 : LINE_COMMON)); if (first == '+' && (ws_rule & WS_BLANK_AT_EOF) && - ws_blank_line(patch + 1, plen, ws_rule)) + ws_blank_line(patch + 1, plen)) added_blank_line = 1; break; case '@': case '\\': @@ -4418,6 +4418,33 @@ static int create_one_file(struct apply_state *state, if (state->cached) return 0; + /* + * We already try to detect whether files are beyond a symlink in our + * up-front checks. But in the case where symlinks are created by any + * of the intermediate hunks it can happen that our up-front checks + * didn't yet see the symlink, but at the point of arriving here there + * in fact is one. We thus repeat the check for symlinks here. + * + * Note that this does not make the up-front check obsolete as the + * failure mode is different: + * + * - The up-front checks cause us to abort before we have written + * anything into the working directory. So when we exit this way the + * working directory remains clean. + * + * - The checks here happen in the middle of the action where we have + * already started to apply the patch. The end result will be a dirty + * working directory. + * + * Ideally, we should update the up-front checks to catch what would + * happen when we apply the patch before we damage the working tree. + * We have all the information necessary to do so. But for now, as a + * part of embargoed security work, having this check would serve as a + * reasonable first step. + */ + if (path_is_beyond_symlink(state, path)) + return error(_("affected file '%s' is beyond a symbolic link"), path); + res = try_create_file(state, path, mode, buf, size); if (res < 0) return -1; @@ -4549,7 +4576,7 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch) FILE *rej; char namebuf[PATH_MAX]; struct fragment *frag; - int cnt = 0; + int fd, cnt = 0; struct strbuf sb = STRBUF_INIT; for (cnt = 0, frag = patch->fragments; frag; frag = frag->next) { @@ -4589,7 +4616,17 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch) memcpy(namebuf, patch->new_name, cnt); memcpy(namebuf + cnt, ".rej", 5); - rej = fopen(namebuf, "w"); + fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666); + if (fd < 0) { + if (errno != EEXIST) + return error_errno(_("cannot open %s"), namebuf); + if (unlink(namebuf)) + return error_errno(_("cannot unlink '%s'"), namebuf); + fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666); + if (fd < 0) + return error_errno(_("cannot open %s"), namebuf); + } + rej = fdopen(fd, "w"); if (!rej) return error_errno(_("cannot open %s"), namebuf); @@ -13,8 +13,7 @@ struct blob *lookup_blob(struct repository *r, const struct object_id *oid) return object_as_type(obj, OBJ_BLOB, 0); } -int parse_blob_buffer(struct blob *item, void *buffer, unsigned long size) +void parse_blob_buffer(struct blob *item) { item->object.parsed = 1; - return 0; } @@ -11,8 +11,6 @@ struct blob { struct blob *lookup_blob(struct repository *r, const struct object_id *oid); -int parse_blob_buffer(struct blob *item, void *buffer, unsigned long size); - /** * Blobs do not contain references to other objects and do not have * structured data that needs parsing. However, code may use the @@ -21,5 +19,6 @@ int parse_blob_buffer(struct blob *item, void *buffer, unsigned long size); * parse_blob_buffer() is used (by object.c) to flag that the object * has been read successfully from the database. **/ +void parse_blob_buffer(struct blob *item); #endif /* BLOB_H */ diff --git a/builtin/add.c b/builtin/add.c index 76277df326..190d1a692a 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -88,7 +88,7 @@ static int fix_unmerged_status(struct diff_filepair *p, } static void update_callback(struct diff_queue_struct *q, - struct diff_options *opt, void *cbdata) + struct diff_options *opt UNUSED, void *cbdata) { int i; struct update_callback_data *data = cbdata; diff --git a/builtin/am.c b/builtin/am.c index 30c9b3a9cd..dddf1b9af0 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -1476,6 +1476,7 @@ static int run_apply(const struct am_state *state, const char *index_file) int res, opts_left; int force_apply = 0; int options = 0; + const char **apply_argv; if (init_apply_state(&apply_state, the_repository, NULL)) BUG("init_apply_state() failed"); @@ -1483,7 +1484,15 @@ static int run_apply(const struct am_state *state, const char *index_file) strvec_push(&apply_opts, "apply"); strvec_pushv(&apply_opts, state->git_apply_opts.v); - opts_left = apply_parse_options(apply_opts.nr, apply_opts.v, + /* + * Build a copy that apply_parse_options() can rearrange. + * apply_opts.v keeps referencing the allocated strings for + * strvec_clear() to release. + */ + ALLOC_ARRAY(apply_argv, apply_opts.nr); + COPY_ARRAY(apply_argv, apply_opts.v, apply_opts.nr); + + opts_left = apply_parse_options(apply_opts.nr, apply_argv, &apply_state, &force_apply, &options, NULL); @@ -1513,6 +1522,7 @@ static int run_apply(const struct am_state *state, const char *index_file) strvec_clear(&apply_paths); strvec_clear(&apply_opts); clear_apply_state(&apply_state); + free(apply_argv); if (res) return res; diff --git a/builtin/branch.c b/builtin/branch.c index 9470c980c1..f63fd45edb 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -581,13 +581,13 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int strbuf_release(&logmsg); strbuf_addf(&oldsection, "branch.%s", interpreted_oldname); - strbuf_release(&oldref); strbuf_addf(&newsection, "branch.%s", interpreted_newname); - strbuf_release(&newref); if (!copy && git_config_rename_section(oldsection.buf, newsection.buf) < 0) die(_("Branch is renamed, but update of config-file failed")); - if (copy && strcmp(oldname, newname) && git_config_copy_section(oldsection.buf, newsection.buf) < 0) + if (copy && strcmp(interpreted_oldname, interpreted_newname) && git_config_copy_section(oldsection.buf, newsection.buf) < 0) die(_("Branch is copied, but update of config-file failed")); + strbuf_release(&oldref); + strbuf_release(&newref); strbuf_release(&oldsection); strbuf_release(&newsection); } diff --git a/builtin/bundle.c b/builtin/bundle.c index c12c09f854..acceef6200 100644 --- a/builtin/bundle.c +++ b/builtin/bundle.c @@ -55,13 +55,12 @@ static int parse_options_cmd_bundle(int argc, const char * const usagestr[], const struct option options[], char **bundle_file) { - int newargc; - newargc = parse_options(argc, argv, NULL, options, usagestr, + argc = parse_options(argc, argv, NULL, options, usagestr, PARSE_OPT_STOP_AT_NON_OPTION); - if (argc < 1) - usage_with_options(usagestr, options); + if (!argc) + usage_msg_opt(_("need a <file> argument"), usagestr, options); *bundle_file = prefix_filename(prefix, argv[0]); - return newargc; + return argc; } static int cmd_bundle_create(int argc, const char **argv, const char *prefix) { diff --git a/builtin/clone.c b/builtin/clone.c index f518bb2dc1..3c2ae31a55 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -1170,10 +1170,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix) refspec_appendf(&remote->fetch, "+%s*:%s*", src_ref_prefix, branch_top.buf); - transport = transport_get(remote, remote->url[0]); - transport_set_verbosity(transport, option_verbosity, option_progress); - transport->family = family; - path = get_repo_path(remote->url[0], &is_bundle); is_local = option_local != 0 && path && !is_bundle; if (is_local) { @@ -1195,6 +1191,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix) } if (option_local > 0 && !is_local) warning(_("--local is ignored")); + + transport = transport_get(remote, path ? path : remote->url[0]); + transport_set_verbosity(transport, option_verbosity, option_progress); + transport->family = family; transport->cloning = 1; if (is_bundle) { diff --git a/builtin/fast-export.c b/builtin/fast-export.c index 3b3314e7b2..39a890fc00 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -409,7 +409,7 @@ static const char *anonymize_oid(const char *oid_hex) } static void show_filemodify(struct diff_queue_struct *q, - struct diff_options *options, void *data) + struct diff_options *options UNUSED, void *data) { int i; struct string_list *changed = data; diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index c3ea09281a..b1f69fbe92 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -94,16 +94,16 @@ static size_t expand_show_tree(struct strbuf *sb, const char *start, } else if (skip_prefix(start, "(objectname)", &p)) { strbuf_add_unique_abbrev(sb, data->oid, abbrev); } else if (skip_prefix(start, "(path)", &p)) { - const char *name = data->base->buf; + const char *name; const char *prefix = chomp_prefix ? ls_tree_prefix : NULL; - struct strbuf quoted = STRBUF_INIT; struct strbuf sbuf = STRBUF_INIT; + size_t baselen = data->base->len; + strbuf_addstr(data->base, data->pathname); name = relative_path(data->base->buf, prefix, &sbuf); - quote_c_style(name, "ed, NULL, 0); - strbuf_addbuf(sb, "ed); + quote_c_style(name, sb, NULL, 0); + strbuf_setlen(data->base, baselen); strbuf_release(&sbuf); - strbuf_release("ed); } else { errlen = (unsigned long)len; die(_("bad ls-tree format: %%%.*s"), errlen, start); @@ -144,7 +144,6 @@ static int show_recursive(const char *base, size_t baselen, const char *pathname static int show_tree_fmt(const struct object_id *oid, struct strbuf *base, const char *pathname, unsigned mode, void *context UNUSED) { - size_t baselen; int recurse = 0; struct strbuf sb = STRBUF_INIT; enum object_type type = object_type(mode); @@ -164,12 +163,10 @@ static int show_tree_fmt(const struct object_id *oid, struct strbuf *base, if (type == OBJ_BLOB && (ls_options & LS_TREE_ONLY)) return 0; - baselen = base->len; strbuf_expand(&sb, format, expand_show_tree, &data); strbuf_addch(&sb, line_termination); fwrite(sb.buf, sb.len, 1, stdout); strbuf_release(&sb); - strbuf_setlen(base, baselen); return recurse; } diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index e3767087bb..ae2c011681 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -98,7 +98,7 @@ static void *origin(struct merge_list *entry, unsigned long *size) return NULL; } -static int show_outf(void *priv_, mmbuffer_t *mb, int nbuf) +static int show_outf(void *priv UNUSED, mmbuffer_t *mb, int nbuf) { int i; for (i = 0; i < nbuf; i++) diff --git a/builtin/merge.c b/builtin/merge.c index dd474371a2..17b41fbe38 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -776,7 +776,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, } static void count_diff_files(struct diff_queue_struct *q, - struct diff_options *opt, void *data) + struct diff_options *opt UNUSED, void *data) { int *count = data; diff --git a/builtin/rerere.c b/builtin/rerere.c index 8b7392d5b4..94ffb8c21a 100644 --- a/builtin/rerere.c +++ b/builtin/rerere.c @@ -14,7 +14,7 @@ static const char * const rerere_usage[] = { NULL, }; -static int outf(void *dummy, mmbuffer_t *ptr, int nbuf) +static int outf(void *dummy UNUSED, mmbuffer_t *ptr, int nbuf) { int i; for (i = 0; i < nbuf; i++) diff --git a/builtin/reset.c b/builtin/reset.c index 1fa86edb4c..d2e0185e55 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -133,7 +133,8 @@ static void print_new_head_line(struct commit *commit) } static void update_index_from_diff(struct diff_queue_struct *q, - struct diff_options *opt, void *data) + struct diff_options *opt UNUSED, + void *data) { int i; int intent_to_add = *(int *)data; diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 05f2c9bc98..6743fb27bd 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -1043,7 +1043,7 @@ static void prepare_submodule_summary(struct summary_cb *info, } static void submodule_summary_callback(struct diff_queue_struct *q, - struct diff_options *options, + struct diff_options *options UNUSED, void *data) { int i; @@ -1865,7 +1865,7 @@ unsigned ws_check(const char *line, int len, unsigned ws_rule); void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws); char *whitespace_error_string(unsigned ws); void ws_fix_copy(struct strbuf *, const char *, int, unsigned, int *); -int ws_blank_line(const char *line, int len, unsigned ws_rule); +int ws_blank_line(const char *line, int len); #define ws_tab_width(rule) ((rule) & WS_TAB_WIDTH_MASK) /* ls-files */ diff --git a/combine-diff.c b/combine-diff.c index b0ece95480..1a39b5dde0 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -372,7 +372,7 @@ struct combine_diff_state { static void consume_hunk(void *state_, long ob, long on, long nb, long nn, - const char *funcline, long funclen) + const char *func UNUSED, long funclen UNUSED) { struct combine_diff_state *state = state_; @@ -701,8 +701,10 @@ static void clear_commit_marks_1(struct commit_list **plist, if (!parents) return; - while ((parents = parents->next)) - commit_list_insert(parents->item, plist); + while ((parents = parents->next)) { + if (parents->item->object.flags & mark) + commit_list_insert(parents->item, plist); + } commit = commit->parents->item; } diff --git a/compat/regcomp_enhanced.c b/compat/regcomp_enhanced.c new file mode 100644 index 0000000000..84193ce53b --- /dev/null +++ b/compat/regcomp_enhanced.c @@ -0,0 +1,9 @@ +#include "../git-compat-util.h" +#undef regcomp + +int git_regcomp(regex_t *preg, const char *pattern, int cflags) +{ + if (!(cflags & REG_EXTENDED)) + cflags |= REG_ENHANCED; + return regcomp(preg, pattern, cflags); +} @@ -3487,9 +3487,10 @@ void git_config_set_multivar(const char *key, const char *value, flags); } -static int section_name_match (const char *buf, const char *name) +static size_t section_name_match (const char *buf, const char *name) { - int i = 0, j = 0, dot = 0; + size_t i = 0, j = 0; + int dot = 0; if (buf[i] != '[') return 0; for (i = 1; buf[i] && buf[i] != ']'; i++) { @@ -3542,6 +3543,8 @@ static int section_name_is_ok(const char *name) return 1; } +#define GIT_CONFIG_MAX_LINE_LEN (512 * 1024) + /* if new_name == NULL, the section is removed instead */ static int git_config_copy_or_rename_section_in_file(const char *config_filename, const char *old_name, @@ -3551,11 +3554,12 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename char *filename_buf = NULL; struct lock_file lock = LOCK_INIT; int out_fd; - char buf[1024]; + struct strbuf buf = STRBUF_INIT; FILE *config_file = NULL; struct stat st; struct strbuf copystr = STRBUF_INIT; struct config_store_data store; + uint32_t line_nr = 0; memset(&store, 0, sizeof(store)); @@ -3592,16 +3596,25 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename goto out; } - while (fgets(buf, sizeof(buf), config_file)) { - unsigned i; - int length; + while (!strbuf_getwholeline(&buf, config_file, '\n')) { + size_t i, length; int is_section = 0; - char *output = buf; - for (i = 0; buf[i] && isspace(buf[i]); i++) + char *output = buf.buf; + + line_nr++; + + if (buf.len >= GIT_CONFIG_MAX_LINE_LEN) { + ret = error(_("refusing to work with overly long line " + "in '%s' on line %"PRIuMAX), + config_filename, (uintmax_t)line_nr); + goto out; + } + + for (i = 0; buf.buf[i] && isspace(buf.buf[i]); i++) ; /* do nothing */ - if (buf[i] == '[') { + if (buf.buf[i] == '[') { /* it's a section */ - int offset; + size_t offset; is_section = 1; /* @@ -3618,7 +3631,7 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename strbuf_reset(©str); } - offset = section_name_match(&buf[i], old_name); + offset = section_name_match(&buf.buf[i], old_name); if (offset > 0) { ret++; if (!new_name) { @@ -3693,6 +3706,7 @@ out: out_no_rollback: free(filename_buf); config_store_data_clear(&store); + strbuf_release(&buf); return ret; } diff --git a/config.mak.uname b/config.mak.uname index d63629fe80..7d25995265 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -147,6 +147,7 @@ ifeq ($(uname_S),Darwin) FREAD_READS_DIRECTORIES = UnfortunatelyYes HAVE_NS_GET_EXECUTABLE_PATH = YesPlease CSPRNG_METHOD = arc4random + USE_ENHANCED_BASIC_REGULAR_EXPRESSIONS = YesPlease # Workaround for `gettext` being keg-only and not even being linked via # `brew link --force gettext`, should be obsolete as of @@ -66,7 +66,7 @@ static NORETURN void die_initial_contact(int unexpected) } /* Checks if the server supports the capability 'c' */ -int server_supports_v2(const char *c, int die_on_error) +int server_supports_v2(const char *c) { int i; @@ -76,11 +76,13 @@ int server_supports_v2(const char *c, int die_on_error) (!*out || *out == '=')) return 1; } + return 0; +} - if (die_on_error) +void ensure_server_supports_v2(const char *c) +{ + if (!server_supports_v2(c)) die(_("server doesn't support '%s'"), c); - - return 0; } int server_feature_v2(const char *c, const char **v) @@ -477,7 +479,7 @@ static void send_capabilities(int fd_out, struct packet_reader *reader) { const char *hash_name; - if (server_supports_v2("agent", 0)) + if (server_supports_v2("agent")) packet_write_fmt(fd_out, "agent=%s", git_user_agent_sanitized()); if (server_feature_v2("object-format", &hash_name)) { @@ -504,17 +506,18 @@ struct ref **get_remote_refs(int fd_out, struct packet_reader *reader, &transport_options->unborn_head_target : NULL; *list = NULL; - if (server_supports_v2("ls-refs", 1)) - packet_write_fmt(fd_out, "command=ls-refs\n"); + ensure_server_supports_v2("ls-refs"); + packet_write_fmt(fd_out, "command=ls-refs\n"); /* Send capabilities */ send_capabilities(fd_out, reader); - if (server_options && server_options->nr && - server_supports_v2("server-option", 1)) + if (server_options && server_options->nr) { + ensure_server_supports_v2("server-option"); for (i = 0; i < server_options->nr; i++) packet_write_fmt(fd_out, "server-option=%s", server_options->items[i].string); + } packet_delim(fd_out); /* When pushing we don't want to request the peeled tags */ @@ -20,7 +20,8 @@ enum protocol_version discover_version(struct packet_reader *reader); int server_supports_hash(const char *desired, int *feature_supported); const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp, int *offset); -int server_supports_v2(const char *c, int die_on_error); +int server_supports_v2(const char *c); +void ensure_server_supports_v2(const char *c); int server_feature_v2(const char *c, const char **v); int server_supports_feature(const char *c, const char *feature, int die_on_error); diff --git a/diff-lib.c b/diff-lib.c index 2edea41a23..dec040c366 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -673,7 +673,7 @@ int index_differs_from(struct repository *r, return (has_changes != 0); } -static struct strbuf *idiff_prefix_cb(struct diff_options *opt, void *data) +static struct strbuf *idiff_prefix_cb(struct diff_options *opt UNUSED, void *data) { return data; } @@ -604,7 +604,7 @@ static unsigned long diff_filespec_size(struct repository *r, return one->size; } -static int count_trailing_blank(mmfile_t *mf, unsigned ws_rule) +static int count_trailing_blank(mmfile_t *mf) { char *ptr = mf->ptr; long size = mf->size; @@ -622,7 +622,7 @@ static int count_trailing_blank(mmfile_t *mf, unsigned ws_rule) for (prev_eol = ptr; mf->ptr <= prev_eol; prev_eol--) if (*prev_eol == '\n') break; - if (!ws_blank_line(prev_eol + 1, ptr - prev_eol, ws_rule)) + if (!ws_blank_line(prev_eol + 1, ptr - prev_eol)) break; cnt++; ptr = prev_eol - 1; @@ -634,9 +634,8 @@ static void check_blank_at_eof(mmfile_t *mf1, mmfile_t *mf2, struct emit_callback *ecbdata) { int l1, l2, at; - unsigned ws_rule = ecbdata->ws_rule; - l1 = count_trailing_blank(mf1, ws_rule); - l2 = count_trailing_blank(mf2, ws_rule); + l1 = count_trailing_blank(mf1); + l2 = count_trailing_blank(mf2); if (l2 <= l1) { ecbdata->blank_at_eof_in_preimage = 0; ecbdata->blank_at_eof_in_postimage = 0; @@ -1583,7 +1582,7 @@ static int new_blank_line_at_eof(struct emit_callback *ecbdata, const char *line ecbdata->blank_at_eof_in_preimage <= ecbdata->lno_in_preimage && ecbdata->blank_at_eof_in_postimage <= ecbdata->lno_in_postimage)) return 0; - return ws_blank_line(line, len, ecbdata->ws_rule); + return ws_blank_line(line, len); } static void emit_add_line(struct emit_callback *ecbdata, @@ -1955,7 +1954,7 @@ static int color_words_output_graph_prefix(struct diff_words_data *diff_words) static void fn_out_diff_words_aux(void *priv, long minus_first, long minus_len, long plus_first, long plus_len, - const char *func, long funclen) + const char *func UNUSED, long funclen UNUSED) { struct diff_words_data *diff_words = priv; struct diff_words_style *style = diff_words->style; @@ -3185,8 +3184,9 @@ static int is_conflict_marker(const char *line, int marker_size, unsigned long l } static void checkdiff_consume_hunk(void *priv, - long ob, long on, long nb, long nn, - const char *func, long funclen) + long ob UNUSED, long on UNUSED, + long nb, long nn UNUSED, + const char *func UNUSED, long funclen UNUSED) { struct checkdiff_t *data = priv; @@ -4213,7 +4213,6 @@ static void prep_temp_blob(struct index_state *istate, } static struct diff_tempfile *prepare_temp_file(struct repository *r, - const char *name, struct diff_filespec *one) { struct diff_tempfile *temp = claim_diff_tempfile(); @@ -4231,18 +4230,18 @@ static struct diff_tempfile *prepare_temp_file(struct repository *r, if (!S_ISGITLINK(one->mode) && (!one->oid_valid || - reuse_worktree_file(r->index, name, &one->oid, 1))) { + reuse_worktree_file(r->index, one->path, &one->oid, 1))) { struct stat st; - if (lstat(name, &st) < 0) { + if (lstat(one->path, &st) < 0) { if (errno == ENOENT) goto not_a_valid_file; - die_errno("stat(%s)", name); + die_errno("stat(%s)", one->path); } if (S_ISLNK(st.st_mode)) { struct strbuf sb = STRBUF_INIT; - if (strbuf_readlink(&sb, name, st.st_size) < 0) - die_errno("readlink(%s)", name); - prep_temp_blob(r->index, name, temp, sb.buf, sb.len, + if (strbuf_readlink(&sb, one->path, st.st_size) < 0) + die_errno("readlink(%s)", one->path); + prep_temp_blob(r->index, one->path, temp, sb.buf, sb.len, (one->oid_valid ? &one->oid : null_oid()), (one->oid_valid ? @@ -4251,7 +4250,7 @@ static struct diff_tempfile *prepare_temp_file(struct repository *r, } else { /* we can borrow from the file in the work tree */ - temp->name = name; + temp->name = one->path; if (!one->oid_valid) oid_to_hex_r(temp->hex, null_oid()); else @@ -4269,7 +4268,7 @@ static struct diff_tempfile *prepare_temp_file(struct repository *r, else { if (diff_populate_filespec(r, one, NULL)) die("cannot read data blob for %s", one->path); - prep_temp_blob(r->index, name, temp, + prep_temp_blob(r->index, one->path, temp, one->data, one->size, &one->oid, one->mode); } @@ -4278,10 +4277,9 @@ static struct diff_tempfile *prepare_temp_file(struct repository *r, static void add_external_diff_name(struct repository *r, struct strvec *argv, - const char *name, struct diff_filespec *df) { - struct diff_tempfile *temp = prepare_temp_file(r, name, df); + struct diff_tempfile *temp = prepare_temp_file(r, df); strvec_push(argv, temp->name); strvec_push(argv, temp->hex); strvec_push(argv, temp->mode); @@ -4308,11 +4306,9 @@ static void run_external_diff(const char *pgm, strvec_push(&cmd.args, name); if (one && two) { - add_external_diff_name(o->repo, &cmd.args, name, one); - if (!other) - add_external_diff_name(o->repo, &cmd.args, name, two); - else { - add_external_diff_name(o->repo, &cmd.args, other, two); + add_external_diff_name(o->repo, &cmd.args, one); + add_external_diff_name(o->repo, &cmd.args, two); + if (other) { strvec_push(&cmd.args, other); strvec_push(&cmd.args, xfrm_msg); } @@ -7037,7 +7033,7 @@ static char *run_textconv(struct repository *r, struct strbuf buf = STRBUF_INIT; int err = 0; - temp = prepare_temp_file(r, spec->path, spec); + temp = prepare_temp_file(r, spec); strvec_push(&child.args, pgm); strvec_push(&child.args, temp->name); diff --git a/dir-iterator.c b/dir-iterator.c index b17e9f970a..3764dd81a1 100644 --- a/dir-iterator.c +++ b/dir-iterator.c @@ -203,7 +203,7 @@ struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags) { struct dir_iterator_int *iter = xcalloc(1, sizeof(*iter)); struct dir_iterator *dir_iterator = &iter->base; - int saved_errno; + int saved_errno, err; strbuf_init(&iter->base.path, PATH_MAX); strbuf_addstr(&iter->base.path, path); @@ -213,10 +213,15 @@ struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags) iter->flags = flags; /* - * Note: stat already checks for NULL or empty strings and - * inexistent paths. + * Note: stat/lstat already checks for NULL or empty strings and + * nonexistent paths. */ - if (stat(iter->base.path.buf, &iter->base.st) < 0) { + if (iter->flags & DIR_ITERATOR_FOLLOW_SYMLINKS) + err = stat(iter->base.path.buf, &iter->base.st); + else + err = lstat(iter->base.path.buf, &iter->base.st); + + if (err < 0) { saved_errno = errno; goto error_out; } diff --git a/dir-iterator.h b/dir-iterator.h index 08229157c6..e3b6ff2800 100644 --- a/dir-iterator.h +++ b/dir-iterator.h @@ -61,6 +61,11 @@ * not the symlinks themselves, which is the default behavior. Broken * symlinks are ignored. * + * Note: setting DIR_ITERATOR_FOLLOW_SYMLINKS affects resolving the + * starting path as well (e.g., attempting to iterate starting at a + * symbolic link pointing to a directory without FOLLOW_SYMLINKS will + * result in an error). + * * Warning: circular symlinks are also followed when * DIR_ITERATOR_FOLLOW_SYMLINKS is set. The iteration may end up with * an ELOOP if they happen and DIR_ITERATOR_PEDANTIC is set. @@ -732,6 +732,13 @@ static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern goto clear_hashmaps; } + if (!(given->flags & PATTERN_FLAG_MUSTBEDIR) && + strcmp(given->pattern, "/*")) { + /* Not a cone pattern. */ + warning(_("unrecognized pattern: '%s'"), given->pattern); + goto clear_hashmaps; + } + prev = given->pattern; cur = given->pattern + 1; next = given->pattern + 2; diff --git a/fetch-pack.c b/fetch-pack.c index 998fc2fa1e..04016d1e32 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -1317,15 +1317,15 @@ static void write_fetch_command_and_capabilities(struct strbuf *req_buf, { const char *hash_name; - if (server_supports_v2("fetch", 1)) - packet_buf_write(req_buf, "command=fetch"); - if (server_supports_v2("agent", 0)) + ensure_server_supports_v2("fetch"); + packet_buf_write(req_buf, "command=fetch"); + if (server_supports_v2("agent")) packet_buf_write(req_buf, "agent=%s", git_user_agent_sanitized()); - if (advertise_sid && server_supports_v2("session-id", 0)) + if (advertise_sid && server_supports_v2("session-id")) packet_buf_write(req_buf, "session-id=%s", trace2_session_id()); - if (server_options && server_options->nr && - server_supports_v2("server-option", 1)) { + if (server_options && server_options->nr) { int i; + ensure_server_supports_v2("server-option"); for (i = 0; i < server_options->nr; i++) packet_buf_write(req_buf, "server-option=%s", server_options->items[i].string); @@ -100,6 +100,8 @@ static void init_gettext_charset(const char *domain) setlocale(LC_CTYPE, "C"); } +int git_gettext_enabled = 0; + void git_setup_gettext(void) { const char *podir = getenv(GIT_TEXT_DOMAIN_DIR_ENVIRONMENT); @@ -119,6 +121,8 @@ void git_setup_gettext(void) init_gettext_charset("git"); textdomain("git"); + git_gettext_enabled = 1; + free(p); } @@ -29,9 +29,11 @@ #define FORMAT_PRESERVING(n) __attribute__((format_arg(n))) #ifndef NO_GETTEXT +extern int git_gettext_enabled; void git_setup_gettext(void); int gettext_width(const char *s); #else +#define git_gettext_enabled (0) static inline void git_setup_gettext(void) { } @@ -45,12 +47,16 @@ static inline FORMAT_PRESERVING(1) const char *_(const char *msgid) { if (!*msgid) return ""; + if (!git_gettext_enabled) + return msgid; return gettext(msgid); } static inline FORMAT_PRESERVING(1) FORMAT_PRESERVING(2) const char *Q_(const char *msgid, const char *plu, unsigned long n) { + if (!git_gettext_enabled) + return n == 1 ? msgid : plu; return ngettext(msgid, plu, n); } diff --git a/git-compat-util.h b/git-compat-util.h index af05077560..de57f435e2 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -341,11 +341,13 @@ struct itimerval { #endif #ifdef NO_SETITIMER -static inline int setitimer(int which UNUSED, - const struct itimerval *value UNUSED, - struct itimerval *newvalue UNUSED) { +static inline int git_setitimer(int which UNUSED, + const struct itimerval *value UNUSED, + struct itimerval *newvalue UNUSED) { return 0; /* pretend success */ } +#undef setitimer +#define setitimer(which,value,ovalue) git_setitimer(which,value,ovalue) #endif #ifndef NO_LIBGEN_H @@ -1344,6 +1346,11 @@ static inline int regexec_buf(const regex_t *preg, const char *buf, size_t size, return regexec(preg, buf, nmatch, pmatch, eflags | REG_STARTEND); } +#ifdef USE_ENHANCED_BASIC_REGULAR_EXPRESSIONS +int git_regcomp(regex_t *preg, const char *pattern, int cflags); +#define regcomp git_regcomp +#endif + #ifndef DIR_HAS_BSD_GROUP_SEMANTICS # define FORCE_DIR_SET_GID S_ISGID #else @@ -1479,14 +1486,19 @@ int open_nofollow(const char *path, int flags); #endif #ifndef _POSIX_THREAD_SAFE_FUNCTIONS -static inline void flockfile(FILE *fh UNUSED) +static inline void git_flockfile(FILE *fh UNUSED) { ; /* nothing */ } -static inline void funlockfile(FILE *fh UNUSED) +static inline void git_funlockfile(FILE *fh UNUSED) { ; /* nothing */ } +#undef flockfile +#undef funlockfile +#undef getc_unlocked +#define flockfile(fh) git_flockfile(fh) +#define funlockfile(fh) git_funlockfile(fh) #define getc_unlocked(fh) getc(fh) #endif diff --git a/git-curl-compat.h b/git-curl-compat.h index 56a83b6bbd..fd96b3cdff 100644 --- a/git-curl-compat.h +++ b/git-curl-compat.h @@ -126,4 +126,12 @@ #define GIT_CURL_HAVE_CURLSSLSET_NO_BACKENDS #endif +/** + * CURLOPT_PROTOCOLS_STR and CURLOPT_REDIR_PROTOCOLS_STR were added in 7.85.0, + * released in August 2022. + */ +#if LIBCURL_VERSION_NUM >= 0x075500 +#define GIT_CURL_HAVE_CURLOPT_PROTOCOLS_STR 1 +#endif + #endif diff --git a/http-push.c b/http-push.c index 5f4340a36e..7f71316456 100644 --- a/http-push.c +++ b/http-push.c @@ -198,13 +198,13 @@ static void curl_setup_http(CURL *curl, const char *url, const char *custom_req, struct buffer *buffer, curl_write_callback write_fn) { - curl_easy_setopt(curl, CURLOPT_PUT, 1); + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_INFILE, buffer); curl_easy_setopt(curl, CURLOPT_INFILESIZE, buffer->buf.len); curl_easy_setopt(curl, CURLOPT_READFUNCTION, fread_buffer); - curl_easy_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer); - curl_easy_setopt(curl, CURLOPT_IOCTLDATA, buffer); + curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, seek_buffer); + curl_easy_setopt(curl, CURLOPT_SEEKDATA, buffer); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_fn); curl_easy_setopt(curl, CURLOPT_NOBODY, 0); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, custom_req); @@ -157,21 +157,19 @@ size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_) return size / eltsize; } -curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp) +int seek_buffer(void *clientp, curl_off_t offset, int origin) { struct buffer *buffer = clientp; - switch (cmd) { - case CURLIOCMD_NOP: - return CURLIOE_OK; - - case CURLIOCMD_RESTARTREAD: - buffer->posn = 0; - return CURLIOE_OK; - - default: - return CURLIOE_UNKNOWNCMD; + if (origin != SEEK_SET) + BUG("seek_buffer only handles SEEK_SET"); + if (offset < 0 || offset >= buffer->buf.len) { + error("curl seek would be outside of buffer"); + return CURL_SEEKFUNC_FAIL; } + + buffer->posn = offset; + return CURL_SEEKFUNC_OK; } size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_) @@ -766,20 +764,37 @@ void setup_curl_trace(CURL *handle) curl_easy_setopt(handle, CURLOPT_DEBUGDATA, NULL); } -static long get_curl_allowed_protocols(int from_user) +static void proto_list_append(struct strbuf *list, const char *proto) { - long allowed_protocols = 0; + if (!list) + return; + if (list->len) + strbuf_addch(list, ','); + strbuf_addstr(list, proto); +} - if (is_transport_allowed("http", from_user)) - allowed_protocols |= CURLPROTO_HTTP; - if (is_transport_allowed("https", from_user)) - allowed_protocols |= CURLPROTO_HTTPS; - if (is_transport_allowed("ftp", from_user)) - allowed_protocols |= CURLPROTO_FTP; - if (is_transport_allowed("ftps", from_user)) - allowed_protocols |= CURLPROTO_FTPS; +static long get_curl_allowed_protocols(int from_user, struct strbuf *list) +{ + long bits = 0; - return allowed_protocols; + if (is_transport_allowed("http", from_user)) { + bits |= CURLPROTO_HTTP; + proto_list_append(list, "http"); + } + if (is_transport_allowed("https", from_user)) { + bits |= CURLPROTO_HTTPS; + proto_list_append(list, "https"); + } + if (is_transport_allowed("ftp", from_user)) { + bits |= CURLPROTO_FTP; + proto_list_append(list, "ftp"); + } + if (is_transport_allowed("ftps", from_user)) { + bits |= CURLPROTO_FTPS; + proto_list_append(list, "ftps"); + } + + return bits; } #ifdef GIT_CURL_HAVE_CURL_HTTP_VERSION_2 @@ -923,10 +938,26 @@ static CURL *get_curl_handle(void) curl_easy_setopt(result, CURLOPT_MAXREDIRS, 20); curl_easy_setopt(result, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL); + +#ifdef GIT_CURL_HAVE_CURLOPT_PROTOCOLS_STR + { + struct strbuf buf = STRBUF_INIT; + + get_curl_allowed_protocols(0, &buf); + curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS_STR, buf.buf); + strbuf_reset(&buf); + + get_curl_allowed_protocols(-1, &buf); + curl_easy_setopt(result, CURLOPT_PROTOCOLS_STR, buf.buf); + strbuf_release(&buf); + } +#else curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS, - get_curl_allowed_protocols(0)); + get_curl_allowed_protocols(0, NULL)); curl_easy_setopt(result, CURLOPT_PROTOCOLS, - get_curl_allowed_protocols(-1)); + get_curl_allowed_protocols(-1, NULL)); +#endif + if (getenv("GIT_CURL_VERBOSE")) http_trace_curl_no_data(); setup_curl_trace(result); @@ -40,7 +40,7 @@ struct buffer { size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf); size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf); size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf); -curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp); +int seek_buffer(void *clientp, curl_off_t offset, int origin); /* Slot lifecycle functions */ struct active_request_slot *get_active_slot(void); diff --git a/line-range.c b/line-range.c index 955a8a9535..47bf0d6f1a 100644 --- a/line-range.c +++ b/line-range.c @@ -135,7 +135,7 @@ static const char *find_funcname_matching_regexp(xdemitconf_t *xecfg, const char { int reg_error; regmatch_t match[1]; - while (1) { + while (*start) { const char *bol, *eol; reg_error = regexec(regexp, start, 1, match, 0); if (reg_error == REG_NOMATCH) @@ -148,8 +148,8 @@ static const char *find_funcname_matching_regexp(xdemitconf_t *xecfg, const char /* determine extent of line matched */ bol = start+match[0].rm_so; eol = start+match[0].rm_eo; - while (bol > start && *bol != '\n') - bol--; + while (bol > start && *--bol != '\n') + ; /* nothing */ if (*bol == '\n') bol++; while (*eol && *eol != '\n') @@ -161,6 +161,7 @@ static const char *find_funcname_matching_regexp(xdemitconf_t *xecfg, const char return bol; start = eol; } + return NULL; } static const char *parse_range_funcname( diff --git a/list-objects-filter.c b/list-objects-filter.c index b9543545ca..7ed21cb299 100644 --- a/list-objects-filter.c +++ b/list-objects-filter.c @@ -70,13 +70,13 @@ struct filter { }; static enum list_objects_filter_result filter_blobs_none( - struct repository *r, + struct repository *r UNUSED, enum list_objects_filter_situation filter_situation, struct object *obj, - const char *pathname, - const char *filename, + const char *pathname UNUSED, + const char *filename UNUSED, struct oidset *omits, - void *filter_data_) + void *filter_data_ UNUSED) { switch (filter_situation) { default: @@ -112,7 +112,7 @@ static enum list_objects_filter_result filter_blobs_none( } static void filter_blobs_none__init( - struct list_objects_filter_options *filter_options, + struct list_objects_filter_options *filter_options UNUSED, struct filter *filter) { filter->filter_object_fn = filter_blobs_none; @@ -159,11 +159,11 @@ static int filter_trees_update_omits( } static enum list_objects_filter_result filter_trees_depth( - struct repository *r, + struct repository *r UNUSED, enum list_objects_filter_situation filter_situation, struct object *obj, - const char *pathname, - const char *filename, + const char *pathname UNUSED, + const char *filename UNUSED, struct oidset *omits, void *filter_data_) { @@ -274,8 +274,8 @@ static enum list_objects_filter_result filter_blobs_limit( struct repository *r, enum list_objects_filter_situation filter_situation, struct object *obj, - const char *pathname, - const char *filename, + const char *pathname UNUSED, + const char *filename UNUSED, struct oidset *omits, void *filter_data_) { @@ -514,6 +514,7 @@ static enum list_objects_filter_result filter_sparse( static void filter_sparse_free(void *filter_data) { struct filter_sparse_data *d = filter_data; + clear_pattern_list(&d->pl); free(d->array_frame); free(d); } @@ -554,12 +555,12 @@ struct filter_object_type_data { }; static enum list_objects_filter_result filter_object_type( - struct repository *r, + struct repository *r UNUSED, enum list_objects_filter_situation filter_situation, struct object *obj, - const char *pathname, - const char *filename, - struct oidset *omits, + const char *pathname UNUSED, + const char *filename UNUSED, + struct oidset *omits UNUSED, void *filter_data_) { struct filter_object_type_data *filter_data = filter_data_; @@ -675,7 +676,7 @@ static enum list_objects_filter_result filter_combine( struct object *obj, const char *pathname, const char *filename, - struct oidset *omits, + struct oidset *omits UNUSED, void *filter_data) { struct combine_filter_data *d = filter_data; diff --git a/list-objects.c b/list-objects.c index 250d9de41c..7528fe1db2 100644 --- a/list-objects.c +++ b/list-objects.c @@ -81,36 +81,6 @@ static void process_blob(struct traversal_context *ctx, strbuf_setlen(path, pathlen); } -/* - * Processing a gitlink entry currently does nothing, since - * we do not recurse into the subproject. - * - * We *could* eventually add a flag that actually does that, - * which would involve: - * - is the subproject actually checked out? - * - if so, see if the subproject has already been added - * to the alternates list, and add it if not. - * - process the commit (or tag) the gitlink points to - * recursively. - * - * However, it's unclear whether there is really ever any - * reason to see superprojects and subprojects as such a - * "unified" object pool (potentially resulting in a totally - * humongous pack - avoiding which was the whole point of - * having gitlinks in the first place!). - * - * So for now, there is just a note that we *could* follow - * the link, and how to do it. Whether it necessarily makes - * any sense what-so-ever to ever do that is another issue. - */ -static void process_gitlink(struct traversal_context *ctx, - const unsigned char *sha1, - struct strbuf *path, - const char *name) -{ - /* Nothing to do */ -} - static void process_tree(struct traversal_context *ctx, struct tree *tree, struct strbuf *base, @@ -149,8 +119,7 @@ static void process_tree_contents(struct traversal_context *ctx, process_tree(ctx, t, base, entry.path); } else if (S_ISGITLINK(entry.mode)) - process_gitlink(ctx, entry.oid.hash, - base, entry.path); + ; /* ignore gitlink */ else { struct blob *b = lookup_blob(ctx->revs->repo, &entry.oid); if (!b) { @@ -194,8 +194,9 @@ int ls_refs(struct repository *r, struct packet_reader *request) send_possibly_unborn_head(&data); if (!data.prefixes.nr) strvec_push(&data.prefixes, ""); - for_each_fullref_in_prefixes(get_git_namespace(), data.prefixes.v, - send_ref, &data); + refs_for_each_fullref_in_prefixes(get_main_ref_store(r), + get_git_namespace(), data.prefixes.v, + send_ref, &data); packet_fflush(stdout); strvec_clear(&data.prefixes); strbuf_release(&data.buf); diff --git a/object-file.c b/object-file.c index 26290554bb..c1b71c2834 100644 --- a/object-file.c +++ b/object-file.c @@ -1864,13 +1864,6 @@ out: return 0; } -static int write_buffer(int fd, const void *buf, size_t len) -{ - if (write_in_full(fd, buf, len) < 0) - return error_errno(_("file write error")); - return 0; -} - static void hash_object_file_literally(const struct git_hash_algo *algo, const void *buf, unsigned long len, const char *type, struct object_id *oid) @@ -2015,8 +2008,8 @@ static int write_loose_object_common(git_hash_ctx *c, ret = git_deflate(stream, flush ? Z_FINISH : 0); the_hash_algo->update_fn(c, in0, stream->next_in - in0); - if (write_buffer(fd, compressed, stream->next_out - compressed) < 0) - die(_("unable to write loose object file")); + if (write_in_full(fd, compressed, stream->next_out - compressed) < 0) + die_errno(_("unable to write loose object file")); stream->next_out = compressed; stream->avail_out = compressed_len; @@ -212,8 +212,7 @@ struct object *parse_object_buffer(struct repository *r, const struct object_id if (type == OBJ_BLOB) { struct blob *blob = lookup_blob(r, oid); if (blob) { - if (parse_blob_buffer(blob, buffer, size)) - return NULL; + parse_blob_buffer(blob); obj = &blob->object; } } else if (type == OBJ_TREE) { @@ -292,7 +291,7 @@ struct object *parse_object_with_flags(struct repository *r, error(_("hash mismatch %s"), oid_to_hex(oid)); return NULL; } - parse_blob_buffer(lookup_blob(r, oid), NULL, 0); + parse_blob_buffer(lookup_blob(r, oid)); return lookup_object(r, oid); } diff --git a/pack-write.c b/pack-write.c index 00787e306d..3363729748 100644 --- a/pack-write.c +++ b/pack-write.c @@ -5,7 +5,6 @@ #include "chunk-format.h" #include "pack-mtimes.h" #include "oidmap.h" -#include "chunk-format.h" #include "pack-objects.h" void reset_pack_idx_option(struct pack_idx_option *opts) diff --git a/range-diff.c b/range-diff.c index 8b7d81adc1..8255ab4349 100644 --- a/range-diff.c +++ b/range-diff.c @@ -269,14 +269,18 @@ static void find_exact_matches(struct string_list *a, struct string_list *b) hashmap_clear(&map); } -static int diffsize_consume(void *data, char *line, unsigned long len) +static int diffsize_consume(void *data, + char *line UNUSED, + unsigned long len UNUSED) { (*(int *)data)++; return 0; } -static void diffsize_hunk(void *data, long ob, long on, long nb, long nn, - const char *funcline, long funclen) +static void diffsize_hunk(void *data, + long ob UNUSED, long on UNUSED, + long nb UNUSED, long nn UNUSED, + const char *func UNUSED, long funclen UNUSED) { diffsize_consume(data, NULL, 0); } @@ -461,7 +465,7 @@ static void patch_diff(const char *a, const char *b, diff_flush(diffopt); } -static struct strbuf *output_prefix_cb(struct diff_options *opt, void *data) +static struct strbuf *output_prefix_cb(struct diff_options *opt UNUSED, void *data) { return data; } diff --git a/ref-filter.c b/ref-filter.c index 9dc2cd1451..971303683b 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -2128,8 +2128,9 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter, return for_each_fullref_in("", cb, cb_data); } - return for_each_fullref_in_prefixes(NULL, filter->name_patterns, - cb, cb_data); + return refs_for_each_fullref_in_prefixes(get_main_ref_store(the_repository), + NULL, filter->name_patterns, + cb, cb_data); } /* @@ -193,7 +193,6 @@ static void mark_reachable(struct expire_reflog_policy_cb *cb) commit_list_insert(commit, &leftover); continue; } - commit->object.flags |= REACHABLE; parent = commit->parents; while (parent) { commit = parent->item; @@ -371,6 +370,9 @@ void reflog_expiry_cleanup(void *cb_data) clear_commit_marks(cb->tip_commit, REACHABLE); break; } + for (elem = cb->mark_list; elem; elem = elem->next) + clear_commit_marks(elem->item, REACHABLE); + free_commit_list(cb->mark_list); } int count_reflog_ent(struct object_id *ooid UNUSED, @@ -1723,9 +1723,10 @@ static void find_longest_prefixes(struct string_list *out, strbuf_release(&prefix); } -int for_each_fullref_in_prefixes(const char *namespace, - const char **patterns, - each_ref_fn fn, void *cb_data) +int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store, + const char *namespace, + const char **patterns, + each_ref_fn fn, void *cb_data) { struct string_list prefixes = STRING_LIST_INIT_DUP; struct string_list_item *prefix; @@ -1740,7 +1741,7 @@ int for_each_fullref_in_prefixes(const char *namespace, for_each_string_list_item(prefix, &prefixes) { strbuf_addstr(&buf, prefix->string); - ret = for_each_fullref_in(buf.buf, fn, cb_data); + ret = refs_for_each_fullref_in(ref_store, buf.buf, fn, cb_data); if (ret) break; strbuf_setlen(&buf, namespace_len); @@ -354,8 +354,10 @@ int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data); * * callers should be prepared to ignore references that they did not ask for. */ -int for_each_fullref_in_prefixes(const char *namespace, const char **patterns, - each_ref_fn fn, void *cb_data); +int refs_for_each_fullref_in_prefixes(struct ref_store *refs, + const char *namespace, const char **patterns, + each_ref_fn fn, void *cb_data); + /** * iterate refs from the respective area. */ diff --git a/refs/packed-backend.c b/refs/packed-backend.c index c1c71d183e..6f5a0709fb 100644 --- a/refs/packed-backend.c +++ b/refs/packed-backend.c @@ -1263,7 +1263,8 @@ static int write_with_updates(struct packed_ref_store *refs, goto error; } - if (fsync_component(FSYNC_COMPONENT_REFERENCE, get_tempfile_fd(refs->tempfile)) || + if (fflush(out) || + fsync_component(FSYNC_COMPONENT_REFERENCE, get_tempfile_fd(refs->tempfile)) || close_tempfile_gently(refs->tempfile)) { strbuf_addf(err, "error closing file %s: %s", get_tempfile_path(refs->tempfile), diff --git a/remote-curl.c b/remote-curl.c index 72dfb8fb86..a76b6405eb 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -717,25 +717,23 @@ static size_t rpc_out(void *ptr, size_t eltsize, return avail; } -static curlioerr rpc_ioctl(CURL *handle, int cmd, void *clientp) +static int rpc_seek(void *clientp, curl_off_t offset, int origin) { struct rpc_state *rpc = clientp; - switch (cmd) { - case CURLIOCMD_NOP: - return CURLIOE_OK; + if (origin != SEEK_SET) + BUG("rpc_seek only handles SEEK_SET, not %d", origin); - case CURLIOCMD_RESTARTREAD: - if (rpc->initial_buffer) { - rpc->pos = 0; - return CURLIOE_OK; + if (rpc->initial_buffer) { + if (offset < 0 || offset > rpc->len) { + error("curl seek would be outside of rpc buffer"); + return CURL_SEEKFUNC_FAIL; } - error(_("unable to rewind rpc post data - try increasing http.postBuffer")); - return CURLIOE_FAILRESTART; - - default: - return CURLIOE_UNKNOWNCMD; + rpc->pos = offset; + return CURL_SEEKFUNC_OK; } + error(_("unable to rewind rpc post data - try increasing http.postBuffer")); + return CURL_SEEKFUNC_FAIL; } struct check_pktline_state { @@ -959,8 +957,8 @@ retry: rpc->initial_buffer = 1; curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, rpc_out); curl_easy_setopt(slot->curl, CURLOPT_INFILE, rpc); - curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, rpc_ioctl); - curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, rpc); + curl_easy_setopt(slot->curl, CURLOPT_SEEKFUNCTION, rpc_seek); + curl_easy_setopt(slot->curl, CURLOPT_SEEKDATA, rpc); if (options.verbosity > 1) { fprintf(stderr, "POST %s (chunked)\n", rpc->service_name); fflush(stderr); diff --git a/revision.c b/revision.c index 439e34a7c5..ec441b80ef 100644 --- a/revision.c +++ b/revision.c @@ -600,10 +600,12 @@ static struct commit *one_relevant_parent(const struct rev_info *revs, static int tree_difference = REV_TREE_SAME; static void file_add_remove(struct diff_options *options, - int addremove, unsigned mode, - const struct object_id *oid, - int oid_valid, - const char *fullpath, unsigned dirty_submodule) + int addremove, + unsigned mode UNUSED, + const struct object_id *oid UNUSED, + int oid_valid UNUSED, + const char *fullpath UNUSED, + unsigned dirty_submodule UNUSED) { int diff = addremove == '+' ? REV_TREE_NEW : REV_TREE_OLD; struct rev_info *revs = options->change_fn_data; @@ -614,12 +616,15 @@ static void file_add_remove(struct diff_options *options, } static void file_change(struct diff_options *options, - unsigned old_mode, unsigned new_mode, - const struct object_id *old_oid, - const struct object_id *new_oid, - int old_oid_valid, int new_oid_valid, - const char *fullpath, - unsigned old_dirty_submodule, unsigned new_dirty_submodule) + unsigned old_mode UNUSED, + unsigned new_mode UNUSED, + const struct object_id *old_oid UNUSED, + const struct object_id *new_oid UNUSED, + int old_oid_valid UNUSED, + int new_oid_valid UNUSED, + const char *fullpath UNUSED, + unsigned old_dirty_submodule UNUSED, + unsigned new_dirty_submodule UNUSED) { tree_difference = REV_TREE_DIFFERENT; options->flags.has_changes = 1; diff --git a/sequencer.c b/sequencer.c index 9827e1adcb..f51d403b7d 100644 --- a/sequencer.c +++ b/sequencer.c @@ -36,7 +36,6 @@ #include "rebase-interactive.h" #include "reset.h" #include "branch.h" -#include "log-tree.h" #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION" diff --git a/submodule.c b/submodule.c index 8ac2fca855..fae24ef34a 100644 --- a/submodule.c +++ b/submodule.c @@ -832,7 +832,7 @@ static void changed_submodule_data_clear(struct changed_submodule_data *cs_data) } static void collect_changed_submodules_cb(struct diff_queue_struct *q, - struct diff_options *options, + struct diff_options *options UNUSED, void *data) { struct collect_changed_submodules_cb_data *me = data; diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh index 5d2d56c445..8f59e9dff8 100644 --- a/t/lib-httpd.sh +++ b/t/lib-httpd.sh @@ -283,11 +283,11 @@ expect_askpass() { none) ;; pass) - echo "askpass: Password for 'http://$2@$dest': " + echo "askpass: Password for '$HTTPD_PROTO://$2@$dest': " ;; both) - echo "askpass: Username for 'http://$dest': " - echo "askpass: Password for 'http://$2@$dest': " + echo "askpass: Username for '$HTTPD_PROTO://$dest': " + echo "askpass: Password for '$HTTPD_PROTO://$2@$dest': " ;; *) false diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf index 51a4fbcf62..693b75e0ae 100644 --- a/t/lib-httpd/apache.conf +++ b/t/lib-httpd/apache.conf @@ -31,7 +31,7 @@ ErrorLog error.log <IfDefine HTTP2> LoadModule http2_module modules/mod_http2.so -Protocols h2c +Protocols h2 h2c </IfDefine> <IfModule !mod_auth_basic.c> diff --git a/t/t0066-dir-iterator.sh b/t/t0066-dir-iterator.sh index 63a1a45cd3..04b811622b 100755 --- a/t/t0066-dir-iterator.sh +++ b/t/t0066-dir-iterator.sh @@ -110,7 +110,9 @@ test_expect_success SYMLINKS 'setup dirs with symlinks' ' mkdir -p dir5/a/c && ln -s ../c dir5/a/b/d && ln -s ../ dir5/a/b/e && - ln -s ../../ dir5/a/b/f + ln -s ../../ dir5/a/b/f && + + ln -s dir4 dir6 ' test_expect_success SYMLINKS 'dir-iterator should not follow symlinks by default' ' @@ -146,4 +148,27 @@ test_expect_success SYMLINKS 'dir-iterator should follow symlinks w/ follow flag test_cmp expected-follow-sorted-output actual-follow-sorted-output ' +test_expect_success SYMLINKS 'dir-iterator does not resolve top-level symlinks' ' + test_must_fail test-tool dir-iterator ./dir6 >out && + + grep "ENOTDIR" out +' + +test_expect_success SYMLINKS 'dir-iterator resolves top-level symlinks w/ follow flag' ' + cat >expected-follow-sorted-output <<-EOF && + [d] (a) [a] ./dir6/a + [d] (a/f) [f] ./dir6/a/f + [d] (a/f/c) [c] ./dir6/a/f/c + [d] (b) [b] ./dir6/b + [d] (b/c) [c] ./dir6/b/c + [f] (a/d) [d] ./dir6/a/d + [f] (a/e) [e] ./dir6/a/e + EOF + + test-tool dir-iterator --follow-symlinks ./dir6 >out && + sort out >actual-follow-sorted-output && + + test_cmp expected-follow-sorted-output actual-follow-sorted-output +' + test_done diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh index b563d6c263..627267be15 100755 --- a/t/t1091-sparse-checkout-builtin.sh +++ b/t/t1091-sparse-checkout-builtin.sh @@ -238,7 +238,7 @@ test_expect_success 'cone mode: match patterns' ' test_expect_success 'cone mode: warn on bad pattern' ' test_when_finished mv sparse-checkout repo/.git/info/ && cp repo/.git/info/sparse-checkout . && - echo "!/deep/deeper/*" >>repo/.git/info/sparse-checkout && + echo "!/deep/deeper/*/" >>repo/.git/info/sparse-checkout && git -C repo read-tree -mu HEAD 2>err && test_i18ngrep "unrecognized negative pattern" err ' @@ -667,6 +667,15 @@ test_expect_success 'pattern-checks: starting "*"' ' check_read_tree_errors repo "a deep" "disabling cone pattern matching" ' +test_expect_success 'pattern-checks: non directory pattern' ' + cat >repo/.git/info/sparse-checkout <<-\EOF && + /deep/deeper1/a + EOF + check_read_tree_errors repo deep "disabling cone pattern matching" && + check_files repo/deep deeper1 && + check_files repo/deep/deeper1 a +' + test_expect_success 'pattern-checks: contained glob characters' ' for c in "[a]" "\\" "?" "*" do diff --git a/t/t1300-config.sh b/t/t1300-config.sh index 2575279ab8..f1d42b62b0 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -617,6 +617,36 @@ test_expect_success 'renaming to bogus section is rejected' ' test_must_fail git config --rename-section branch.zwei "bogus name" ' +test_expect_success 'renaming a section with a long line' ' + { + printf "[b]\\n" && + printf " c = d %1024s [a] e = f\\n" " " && + printf "[a] g = h\\n" + } >y && + git config -f y --rename-section a xyz && + test_must_fail git config -f y b.e +' + +test_expect_success 'renaming an embedded section with a long line' ' + { + printf "[b]\\n" && + printf " c = d %1024s [a] [foo] e = f\\n" " " && + printf "[a] g = h\\n" + } >y && + git config -f y --rename-section a xyz && + test_must_fail git config -f y foo.e +' + +test_expect_success 'renaming a section with an overly-long line' ' + { + printf "[b]\\n" && + printf " c = d %525000s e" " " && + printf "[a] g = h\\n" + } >y && + test_must_fail git config -f y --rename-section a xyz 2>err && + grep "refusing to work with overly long line in .y. on line 2" err +' + cat >> .git/config << EOF [branch "zwei"] a = 1 [branch "vier"] EOF diff --git a/t/t3104-ls-tree-format.sh b/t/t3104-ls-tree-format.sh index 383896667b..805b30f403 100755 --- a/t/t3104-ls-tree-format.sh +++ b/t/t3104-ls-tree-format.sh @@ -36,6 +36,12 @@ test_ls_tree_format () { ' } +test_expect_success "ls-tree --format='%(path) %(path) %(path)' HEAD top-file" ' + git ls-tree --format="%(path) %(path) %(path)" HEAD top-file.t >actual && + echo top-file.t top-file.t top-file.t >expect && + test_cmp expect actual +' + test_ls_tree_format \ "%(objectmode) %(objecttype) %(objectname)%x09%(path)" \ "" diff --git a/t/t3204-branch-name-interpretation.sh b/t/t3204-branch-name-interpretation.sh index 793bf4d269..3399344f25 100755 --- a/t/t3204-branch-name-interpretation.sh +++ b/t/t3204-branch-name-interpretation.sh @@ -57,6 +57,16 @@ test_expect_success 'create branch with pseudo-qualified name' ' expect_branch refs/heads/refs/heads/qualified two ' +test_expect_success 'force-copy a branch to itself via @{-1} is no-op' ' + git branch -t copiable main && + git checkout copiable && + git checkout - && + git branch -C @{-1} copiable && + git config --get-all branch.copiable.merge >actual && + echo refs/heads/main >expect && + test_cmp expect actual +' + test_expect_success 'delete branch via @{-1}' ' git branch previous-del && diff --git a/t/t3920-crlf-messages.sh b/t/t3920-crlf-messages.sh index 4c661d4d54..67fd2345af 100755 --- a/t/t3920-crlf-messages.sh +++ b/t/t3920-crlf-messages.sh @@ -12,7 +12,7 @@ create_crlf_ref () { cat >.crlf-orig-$branch.txt && cat .crlf-orig-$branch.txt | append_cr >.crlf-message-$branch.txt && grep 'Subject' .crlf-orig-$branch.txt | tr '\n' ' ' | sed 's/[ ]*$//' | tr -d '\n' >.crlf-subject-$branch.txt && - grep 'Body' .crlf-message-$branch.txt >.crlf-body-$branch.txt || true && + grep 'Body' .crlf-orig-$branch.txt | append_cr >.crlf-body-$branch.txt && LIB_CRLF_BRANCHES="${LIB_CRLF_BRANCHES} ${branch}" && test_tick && hash=$(git commit-tree HEAD^{tree} -p HEAD -F .crlf-message-${branch}.txt) && diff --git a/t/t4023-diff-rename-typechange.sh b/t/t4023-diff-rename-typechange.sh index 7cb9909293..787605ce3f 100755 --- a/t/t4023-diff-rename-typechange.sh +++ b/t/t4023-diff-rename-typechange.sh @@ -52,8 +52,8 @@ test_expect_success setup ' ' test_expect_success 'cross renames to be detected for regular files' ' - - git diff-tree five six -r --name-status -B -M | sort >actual && + git diff-tree five six -r --name-status -B -M >out && + sort out >actual && { echo "R100 foo bar" && echo "R100 bar foo" @@ -63,8 +63,8 @@ test_expect_success 'cross renames to be detected for regular files' ' ' test_expect_success 'cross renames to be detected for typechange' ' - - git diff-tree one two -r --name-status -B -M | sort >actual && + git diff-tree one two -r --name-status -B -M >out && + sort out >actual && { echo "R100 foo bar" && echo "R100 bar foo" @@ -74,8 +74,8 @@ test_expect_success 'cross renames to be detected for typechange' ' ' test_expect_success 'moves and renames' ' - - git diff-tree three four -r --name-status -B -M | sort >actual && + git diff-tree three four -r --name-status -B -M >out && + sort out >actual && { # see -B -M (#6) in t4008 echo "C100 foo bar" && diff --git a/t/t4045-diff-relative.sh b/t/t4045-diff-relative.sh index fab351b48a..5e1bbb57e7 100755 --- a/t/t4045-diff-relative.sh +++ b/t/t4045-diff-relative.sh @@ -162,6 +162,35 @@ check_diff_relative_option subdir file2 true --no-relative --relative check_diff_relative_option . file2 false --no-relative --relative=subdir check_diff_relative_option . file2 true --no-relative --relative=subdir +test_expect_success 'external diff with --relative' ' + test_when_finished "git reset --hard" && + echo changed >file1 && + echo changed >subdir/file2 && + + write_script mydiff <<-\EOF && + # hacky pretend diff; the goal here is just to make sure we got + # passed sensible input that we _could_ diff, without relying on + # the specific output of a system diff tool. + echo "diff a/$1 b/$1" && + echo "--- a/$1" && + echo "+++ b/$1" && + echo "@@ -1 +0,0 @@" && + sed "s/^/-/" "$2" && + sed "s/^/+/" "$5" + EOF + + cat >expect <<-\EOF && + diff a/file2 b/file2 + --- a/file2 + +++ b/file2 + @@ -1 +0,0 @@ + -other content + +changed + EOF + GIT_EXTERNAL_DIFF=./mydiff git diff --relative=subdir >actual && + test_cmp expect actual +' + test_expect_success 'setup diff --relative unmerged' ' test_commit zero file0 && test_commit base subdir/file0 && diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh index d0f3edef54..e95e6d4e7d 100755 --- a/t/t4115-apply-symlink.sh +++ b/t/t4115-apply-symlink.sh @@ -45,4 +45,100 @@ test_expect_success 'apply --index symlink patch' ' ' +test_expect_success 'symlink setup' ' + ln -s .git symlink && + git add symlink && + git commit -m "add symlink" +' + +test_expect_success SYMLINKS 'symlink escape when creating new files' ' + test_when_finished "git reset --hard && git clean -dfx" && + + cat >patch <<-EOF && + diff --git a/symlink b/renamed-symlink + similarity index 100% + rename from symlink + rename to renamed-symlink + -- + diff --git /dev/null b/renamed-symlink/create-me + new file mode 100644 + index 0000000..039727e + --- /dev/null + +++ b/renamed-symlink/create-me + @@ -0,0 +1,1 @@ + +busted + EOF + + test_must_fail git apply patch 2>stderr && + cat >expected_stderr <<-EOF && + error: affected file ${SQ}renamed-symlink/create-me${SQ} is beyond a symbolic link + EOF + test_cmp expected_stderr stderr && + ! test_path_exists .git/create-me +' + +test_expect_success SYMLINKS 'symlink escape when modifying file' ' + test_when_finished "git reset --hard && git clean -dfx" && + touch .git/modify-me && + + cat >patch <<-EOF && + diff --git a/symlink b/renamed-symlink + similarity index 100% + rename from symlink + rename to renamed-symlink + -- + diff --git a/renamed-symlink/modify-me b/renamed-symlink/modify-me + index 1111111..2222222 100644 + --- a/renamed-symlink/modify-me + +++ b/renamed-symlink/modify-me + @@ -0,0 +1,1 @@ + +busted + EOF + + test_must_fail git apply patch 2>stderr && + cat >expected_stderr <<-EOF && + error: renamed-symlink/modify-me: No such file or directory + EOF + test_cmp expected_stderr stderr && + test_must_be_empty .git/modify-me +' + +test_expect_success SYMLINKS 'symlink escape when deleting file' ' + test_when_finished "git reset --hard && git clean -dfx && rm .git/delete-me" && + touch .git/delete-me && + + cat >patch <<-EOF && + diff --git a/symlink b/renamed-symlink + similarity index 100% + rename from symlink + rename to renamed-symlink + -- + diff --git a/renamed-symlink/delete-me b/renamed-symlink/delete-me + deleted file mode 100644 + index 1111111..0000000 100644 + EOF + + test_must_fail git apply patch 2>stderr && + cat >expected_stderr <<-EOF && + error: renamed-symlink/delete-me: No such file or directory + EOF + test_cmp expected_stderr stderr && + test_path_is_file .git/delete-me +' + +test_expect_success SYMLINKS '--reject removes .rej symlink if it exists' ' + test_when_finished "git reset --hard && git clean -dfx" && + + test_commit file && + echo modified >file.t && + git diff -- file.t >patch && + echo modified-again >file.t && + + ln -s foo file.t.rej && + test_must_fail git apply patch --reject 2>err && + test_i18ngrep "Rejected hunk" err && + test_path_is_missing foo && + test_path_is_file file.t.rej +' + test_done diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh index fedb7ca749..3e7ad9d5de 100755 --- a/t/t4205-log-pretty-formats.sh +++ b/t/t4205-log-pretty-formats.sh @@ -156,7 +156,7 @@ test_expect_success 'NUL termination with --reflog --pretty=oneline' ' for r in $revs do git show -s --pretty=oneline "$r" >raw && - cat raw | lf_to_nul || exit 1 + cat raw | lf_to_nul || return 1 done >expect && # the trailing NUL is already produced so we do not need to # output another one diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh index ac9e4d0928..c6540e822f 100755 --- a/t/t4211-line-log.sh +++ b/t/t4211-line-log.sh @@ -315,4 +315,26 @@ test_expect_success 'line-log with --before' ' test_cmp expect actual ' +test_expect_success 'setup tests for zero-width regular expressions' ' + cat >expect <<-EOF + Modify func1() in file.c + Add func1() and func2() in file.c + EOF +' + +test_expect_success 'zero-width regex $ matches any function name' ' + git log --format="%s" --no-patch "-L:$:file.c" >actual && + test_cmp expect actual +' + +test_expect_success 'zero-width regex ^ matches any function name' ' + git log --format="%s" --no-patch "-L:^:file.c" >actual && + test_cmp expect actual +' + +test_expect_success 'zero-width regex .* matches any function name' ' + git log --format="%s" --no-patch "-L:.*:file.c" >actual && + test_cmp expect actual +' + test_done diff --git a/t/t5314-pack-cycle-detection.sh b/t/t5314-pack-cycle-detection.sh index 73a241743a..82734b9a3c 100755 --- a/t/t5314-pack-cycle-detection.sh +++ b/t/t5314-pack-cycle-detection.sh @@ -63,13 +63,16 @@ TEST_PASSES_SANITIZE_LEAK=true # Note that the two variants of "file" must be similar enough to convince git # to create the delta. make_pack () { - { - printf '%s\n' "-$(git rev-parse $2)" - printf '%s dummy\n' "$(git rev-parse $1:dummy)" - printf '%s file\n' "$(git rev-parse $1:file)" - } | - git pack-objects --stdout | - git index-pack --stdin --fix-thin + ln1=$(git rev-parse "$2") && + ln2=$(git rev-parse "$1:dummy") && + ln3=$(git rev-parse "$1:file") && + cat >list <<-EOF + -$ln1 + $ln2 dummy + $ln3 file + EOF + git pack-objects --stdout <list >pack && + git index-pack --stdin --fix-thin <pack } test_expect_success 'setup' ' diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh index fbad2d5ff5..d0211cd8be 100755 --- a/t/t5541-http-push-smart.sh +++ b/t/t5541-http-push-smart.sh @@ -36,28 +36,6 @@ test_expect_success 'setup remote repository' ' setup_askpass_helper -cat >exp <<EOF -GET /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200 -POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200 -EOF -test_expect_success 'no empty path components' ' - # Clear the log, so that it does not affect the "used receive-pack - # service" test which reads the log too. - test_when_finished ">\"\$HTTPD_ROOT_PATH\"/access.log" && - - # In the URL, add a trailing slash, and see if git appends yet another - # slash. - cd "$ROOT_PATH" && - git clone $HTTPD_URL/smart/test_repo.git/ test_repo_clone && - - # NEEDSWORK: If the overspecification of the expected result is reduced, we - # might be able to run this test in all protocol versions. - if test "$GIT_TEST_PROTOCOL_VERSION" = 0 - then - check_access_log exp - fi -' - test_expect_success 'clone remote repository' ' rm -rf test_repo_clone && git clone $HTTPD_URL/smart/test_repo.git test_repo_clone && @@ -67,6 +45,10 @@ test_expect_success 'clone remote repository' ' ' test_expect_success 'push to remote repository (standard)' ' + # Clear the log, so that the "used receive-pack service" test below + # sees just what we did here. + >"$HTTPD_ROOT_PATH"/access.log && + cd "$ROOT_PATH"/test_repo_clone && : >path2 && git add path2 && @@ -80,6 +62,15 @@ test_expect_success 'push to remote repository (standard)' ' test $HEAD = $(git rev-parse --verify HEAD)) ' +test_expect_success 'used receive-pack service' ' + cat >exp <<-\EOF && + GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200 + POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200 + EOF + + check_access_log exp +' + test_expect_success 'push to remote repository (standard) with sending Accept-Language' ' cat >exp <<-\EOF && => Send header: Accept-Language: ko-KR, *;q=0.9 @@ -141,28 +132,6 @@ test_expect_success 'rejected update prints status' ' ' rm -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update" -cat >exp <<EOF -GET /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200 -POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200 -GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200 -POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200 -GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200 -GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200 -POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200 -GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200 -POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200 -GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200 -POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200 -EOF -test_expect_success 'used receive-pack service' ' - # NEEDSWORK: If the overspecification of the expected result is reduced, we - # might be able to run this test in all protocol versions. - if test "$GIT_TEST_PROTOCOL_VERSION" = 0 - then - check_access_log exp - fi -' - test_http_push_nonff "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \ "$ROOT_PATH"/test_repo_clone main success diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh index bc0719a4fc..0908534f25 100755 --- a/t/t5551-http-fetch-smart.sh +++ b/t/t5551-http-fetch-smart.sh @@ -1,6 +1,6 @@ #!/bin/sh -: ${HTTP_PROTO:=HTTP} +: ${HTTP_PROTO:=HTTP/1.1} test_description="test smart fetching over http via http-backend ($HTTP_PROTO)" GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME @@ -33,35 +33,71 @@ test_expect_success 'create http-accessible bare repository' ' setup_askpass_helper test_expect_success 'clone http repository' ' - cat >exp <<-\EOF && - > GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 - > Accept: */* - > Accept-Encoding: ENCODINGS - > Accept-Language: ko-KR, *;q=0.9 - > Pragma: no-cache - < HTTP/1.1 200 OK - < Pragma: no-cache - < Cache-Control: no-cache, max-age=0, must-revalidate - < Content-Type: application/x-git-upload-pack-advertisement - > POST /smart/repo.git/git-upload-pack HTTP/1.1 - > Accept-Encoding: ENCODINGS - > Content-Type: application/x-git-upload-pack-request - > Accept: application/x-git-upload-pack-result - > Accept-Language: ko-KR, *;q=0.9 - > Content-Length: xxx - < HTTP/1.1 200 OK - < Pragma: no-cache - < Cache-Control: no-cache, max-age=0, must-revalidate - < Content-Type: application/x-git-upload-pack-result + if test_have_prereq HTTP2 && test "$HTTPD_PROTO" = "https" + then + # ALPN lets us immediately use HTTP/2; likewise, POSTs with + # bodies can use it because they do not need to upgrade + INITIAL_PROTO=HTTP/2 + else + # either we are not using HTTP/2, or the initial + # request is sent via HTTP/1.1 and asks for upgrade + INITIAL_PROTO=HTTP/1.1 + fi && + + cat >exp.raw <<-EOF && + > GET /smart/repo.git/info/refs?service=git-upload-pack $INITIAL_PROTO + > accept: */* + > accept-encoding: ENCODINGS + > accept-language: ko-KR, *;q=0.9 + > pragma: no-cache + {V2} > git-protocol: version=2 + < $HTTP_PROTO 200 OK + < pragma: no-cache + < cache-control: no-cache, max-age=0, must-revalidate + < content-type: application/x-git-upload-pack-advertisement + > POST /smart/repo.git/git-upload-pack $INITIAL_PROTO + > accept-encoding: ENCODINGS + > content-type: application/x-git-upload-pack-request + > accept: application/x-git-upload-pack-result + > accept-language: ko-KR, *;q=0.9 + {V2} > git-protocol: version=2 + > content-length: xxx + < $INITIAL_PROTO 200 OK + < pragma: no-cache + < cache-control: no-cache, max-age=0, must-revalidate + < content-type: application/x-git-upload-pack-result + {V2} > POST /smart/repo.git/git-upload-pack $INITIAL_PROTO + {V2} > accept-encoding: ENCODINGS + {V2} > content-type: application/x-git-upload-pack-request + {V2} > accept: application/x-git-upload-pack-result + {V2} > accept-language: ko-KR, *;q=0.9 + {V2} > git-protocol: version=2 + {V2} > content-length: xxx + {V2} < $INITIAL_PROTO 200 OK + {V2} < pragma: no-cache + {V2} < cache-control: no-cache, max-age=0, must-revalidate + {V2} < content-type: application/x-git-upload-pack-result EOF - GIT_TRACE_CURL=true GIT_TEST_PROTOCOL_VERSION=0 LANGUAGE="ko_KR.UTF-8" \ + if test "$GIT_TEST_PROTOCOL_VERSION" = 0 + then + sed "/^{V2}/d" <exp.raw >exp + else + sed "s/^{V2} //" <exp.raw >exp + fi && + + GIT_TRACE_CURL=true LANGUAGE="ko_KR.UTF-8" \ git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err && test_cmp file clone/file && tr '\''\015'\'' Q <err | + perl -pe '\'' + s/(Send|Recv) header: ([A-Za-z0-9-]+):/ + "$1 header: " . lc($2) . ":" + /e; + '\'' | sed -e " s/Q\$// - /^[*] /d + /^[^<=]/d /^== Info:/d /^=> Send header, /d /^=> Send header:$/d @@ -71,6 +107,8 @@ test_expect_success 'clone http repository' ' s/= Recv header:// /^<= Recv data/d /^=> Send data/d + /^<= Recv SSL data/d + /^=> Send SSL data/d /^$/d /^< $/d @@ -78,36 +116,35 @@ test_expect_success 'clone http repository' ' s/^/> / } - /^> User-Agent: /d - /^> Host: /d + /^< HTTP/ { + s/200$/200 OK/ + } + /^< HTTP\\/1.1 101/d + /^[><] connection: /d + /^[><] upgrade: /d + /^> http2-settings: /d + + /^> user-agent: /d + /^> host: /d /^> POST /,$ { /^> Accept: [*]\\/[*]/d } - s/^> Content-Length: .*/> Content-Length: xxx/ + s/^> content-length: .*/> content-length: xxx/ /^> 00..want /d /^> 00.*done/d - /^< Server: /d - /^< Expires: /d - /^< Date: /d - /^< Content-Length: /d - /^< Transfer-Encoding: /d + /^< server: /d + /^< expires: /d + /^< date: /d + /^< content-length: /d + /^< transfer-encoding: /d " >actual && - # NEEDSWORK: If the overspecification of the expected result is reduced, we - # might be able to run this test in all protocol versions. - if test "$GIT_TEST_PROTOCOL_VERSION" = 0 - then - sed -e "s/^> Accept-Encoding: .*/> Accept-Encoding: ENCODINGS/" \ - actual >actual.smudged && - test_cmp exp actual.smudged && - - grep "Accept-Encoding:.*gzip" actual >actual.gzip && - test_line_count = 2 actual.gzip && + sed -e "s/^> accept-encoding: .*/> accept-encoding: ENCODINGS/" \ + actual >actual.smudged && + test_cmp exp actual.smudged && - grep "Accept-Language: ko-KR, *" actual >actual.language && - test_line_count = 2 actual.language - fi + grep "accept-encoding:.*gzip" actual >actual.gzip ' test_expect_success 'fetch changes via http' ' @@ -119,19 +156,9 @@ test_expect_success 'fetch changes via http' ' ' test_expect_success 'used upload-pack service' ' - cat >exp <<-\EOF && - GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200 - POST /smart/repo.git/git-upload-pack HTTP/1.1 200 - GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200 - POST /smart/repo.git/git-upload-pack HTTP/1.1 200 - EOF - - # NEEDSWORK: If the overspecification of the expected result is reduced, we - # might be able to run this test in all protocol versions. - if test "$GIT_TEST_PROTOCOL_VERSION" = 0 - then - check_access_log exp - fi + strip_access_log >log && + grep "GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/[0-9.]* 200" log && + grep "POST /smart/repo.git/git-upload-pack HTTP/[0-9.]* 200" log ' test_expect_success 'follow redirects (301)' ' @@ -280,21 +307,23 @@ test_expect_success 'cookies stored in http.cookiefile when http.savecookies set 127.0.0.1 FALSE /smart_cookies/ FALSE 0 othername othervalue EOF sort >expect_cookies.txt <<-\EOF && - 127.0.0.1 FALSE /smart_cookies/ FALSE 0 othername othervalue + 127.0.0.1 FALSE /smart_cookies/repo.git/ FALSE 0 name value 127.0.0.1 FALSE /smart_cookies/repo.git/info/ FALSE 0 name value EOF git config http.cookiefile cookies.txt && git config http.savecookies true && - git ls-remote $HTTPD_URL/smart_cookies/repo.git main && - # NEEDSWORK: If the overspecification of the expected result is reduced, we - # might be able to run this test in all protocol versions. - if test "$GIT_TEST_PROTOCOL_VERSION" = 0 - then - tail -3 cookies.txt | sort >cookies_tail.txt && - test_cmp expect_cookies.txt cookies_tail.txt - fi + test_when_finished " + git --git-dir=\"\$HTTPD_DOCUMENT_ROOT_PATH/repo.git\" \ + tag -d cookie-tag + " && + git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \ + tag -m "foo" cookie-tag && + git fetch $HTTPD_URL/smart_cookies/repo.git cookie-tag && + + grep "^[^#]" cookies.txt | sort >cookies_stripped.txt && + test_cmp expect_cookies.txt cookies_stripped.txt ' test_expect_success 'transfer.hiderefs works over smart-http' ' @@ -666,4 +695,13 @@ test_expect_success 'push warns or fails when using username:password' ' test_line_count -ge 1 warnings ' +test_expect_success 'no empty path components' ' + # In the URL, add a trailing slash, and see if git appends yet another + # slash. + git clone $HTTPD_URL/smart/repo.git/ clone-with-slash && + + strip_access_log >log && + ! grep "//" log +' + test_done diff --git a/t/t5559-http-fetch-smart-http2.sh b/t/t5559-http-fetch-smart-http2.sh index 9eece71c2c..54aa9d3bff 100755 --- a/t/t5559-http-fetch-smart-http2.sh +++ b/t/t5559-http-fetch-smart-http2.sh @@ -1,4 +1,5 @@ #!/bin/sh HTTP_PROTO=HTTP/2 +LIB_HTTPD_SSL=1 . ./t5551-http-fetch-smart.sh diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh index 2734e37e88..7ccebb40c3 100755 --- a/t/t5604-clone-reference.sh +++ b/t/t5604-clone-reference.sh @@ -344,4 +344,20 @@ test_expect_success SYMLINKS 'clone repo with symlinked or unknown files at obje test_must_be_empty T--shared.objects-symlinks.raw ' +test_expect_success SYMLINKS 'clone repo with symlinked objects directory' ' + test_when_finished "rm -fr sensitive malicious" && + + mkdir -p sensitive && + echo "secret" >sensitive/file && + + git init malicious && + rm -fr malicious/.git/objects && + ln -s "$(pwd)/sensitive" ./malicious/.git/objects && + + test_must_fail git clone --local malicious clone 2>err && + + test_path_is_missing clone && + grep "failed to start iterator over" err +' + test_done diff --git a/t/t5619-clone-local-ambiguous-transport.sh b/t/t5619-clone-local-ambiguous-transport.sh new file mode 100755 index 0000000000..cce62bf78d --- /dev/null +++ b/t/t5619-clone-local-ambiguous-transport.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +test_description='test local clone with ambiguous transport' + +. ./test-lib.sh +. "$TEST_DIRECTORY/lib-httpd.sh" + +if ! test_have_prereq SYMLINKS +then + skip_all='skipping test, symlink support unavailable' + test_done +fi + +start_httpd + +REPO="$HTTPD_DOCUMENT_ROOT_PATH/sub.git" +URI="$HTTPD_URL/dumb/sub.git" + +test_expect_success 'setup' ' + mkdir -p sensitive && + echo "secret" >sensitive/secret && + + git init --bare "$REPO" && + test_commit_bulk -C "$REPO" --ref=main 1 && + + git -C "$REPO" update-ref HEAD main && + git -C "$REPO" update-server-info && + + git init malicious && + ( + cd malicious && + + git submodule add "$URI" && + + mkdir -p repo/refs && + touch repo/refs/.gitkeep && + printf "ref: refs/heads/a" >repo/HEAD && + ln -s "$(cd .. && pwd)/sensitive" repo/objects && + + mkdir -p "$HTTPD_URL/dumb" && + ln -s "../../../.git/modules/sub/../../../repo/" "$URI" && + + git add . && + git commit -m "initial commit" + ) && + + # Delete all of the references in our malicious submodule to + # avoid the client attempting to checkout any objects (which + # will be missing, and thus will cause the clone to fail before + # we can trigger the exploit). + git -C "$REPO" for-each-ref --format="delete %(refname)" >in && + git -C "$REPO" update-ref --stdin <in && + git -C "$REPO" update-server-info +' + +test_expect_success 'ambiguous transport does not lead to arbitrary file-inclusion' ' + git clone malicious clone && + test_must_fail git -C clone submodule update --init 2>err && + + test_path_is_missing clone/.git/modules/sub/objects/secret && + # We would actually expect "transport .file. not allowed" here, + # but due to quirks of the URL detection in Git, we mis-parse + # the absolute path as a bogus URL and die before that step. + # + # This works for now, and if we ever fix the URL detection, it + # is OK to change this to detect the transport error. + grep "protocol .* is not supported" err +' + +test_done diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh index 833205125a..3a1cf30b1d 100755 --- a/t/t6020-bundle-misc.sh +++ b/t/t6020-bundle-misc.sh @@ -11,6 +11,13 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh . "$TEST_DIRECTORY"/lib-bundle.sh +for cmd in create verify list-heads unbundle +do + test_expect_success "usage: git bundle $cmd needs an argument" ' + test_expect_code 129 git bundle $cmd + ' +done + # Create a commit or tag and set the variable with the object ID. test_commit_setvar () { notick= diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index 7c3f6ed994..060e145957 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -105,7 +105,7 @@ verify_mergeheads () { test_write_lines "$@" >mergehead.expected && while read sha1 rest do - git rev-parse $sha1 + git rev-parse $sha1 || return 1 done <.git/MERGE_HEAD >mergehead.actual && test_cmp mergehead.expected mergehead.actual } diff --git a/unpack-trees.c b/unpack-trees.c index 8a762aa077..d11bef96bf 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -19,7 +19,6 @@ #include "promisor-remote.h" #include "entry.h" #include "parallel-checkout.h" -#include "sparse-index.h" /* * Error messages expected by scripts out of plumbing commands such as diff --git a/userdiff.c b/userdiff.c index 151d9a5278..e25356a061 100644 --- a/userdiff.c +++ b/userdiff.c @@ -315,7 +315,8 @@ struct find_by_namelen_data { }; static int userdiff_find_by_namelen_cb(struct userdiff_driver *driver, - enum userdiff_driver_type type, void *priv) + enum userdiff_driver_type type UNUSED, + void *priv) { struct find_by_namelen_data *cb_data = priv; @@ -252,7 +252,7 @@ unsigned ws_check(const char *line, int len, unsigned ws_rule) return ws_check_emit_1(line, len, ws_rule, NULL, NULL, NULL, NULL); } -int ws_blank_line(const char *line, int len, unsigned ws_rule) +int ws_blank_line(const char *line, int len) { /* * We _might_ want to treat CR differently from other diff --git a/wt-status.c b/wt-status.c index 5813174896..76e37a8088 100644 --- a/wt-status.c +++ b/wt-status.c @@ -438,7 +438,7 @@ static char short_submodule_status(struct wt_status_change_data *d) } static void wt_status_collect_changed_cb(struct diff_queue_struct *q, - struct diff_options *options, + struct diff_options *options UNUSED, void *data) { struct wt_status *s = data; @@ -525,7 +525,7 @@ static int unmerged_mask(struct index_state *istate, const char *path) } static void wt_status_collect_updated_cb(struct diff_queue_struct *q, - struct diff_options *options, + struct diff_options *options UNUSED, void *data) { struct wt_status *s = data; diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c index 32652ded2d..344c2dfc3e 100644 --- a/xdiff/xdiffi.c +++ b/xdiff/xdiffi.c @@ -973,7 +973,7 @@ void xdl_free_script(xdchange_t *xscr) { } } -static int xdl_call_hunk_func(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, +static int xdl_call_hunk_func(xdfenv_t *xe UNUSED, xdchange_t *xscr, xdemitcb_t *ecb, xdemitconf_t const *xecfg) { xdchange_t *xch, *xche; diff --git a/xdiff/xemit.c b/xdiff/xemit.c index c4ccd68d47..75f0fe4986 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -95,7 +95,7 @@ xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg) } -static long def_ff(const char *rec, long len, char *buf, long sz, void *priv) +static long def_ff(const char *rec, long len, char *buf, long sz) { if (len > 0 && (isalpha((unsigned char)*rec) || /* identifier? */ @@ -117,7 +117,7 @@ static long match_func_rec(xdfile_t *xdf, xdemitconf_t const *xecfg, long ri, const char *rec; long len = xdl_get_rec(xdf, ri, &rec); if (!xecfg->find_func) - return def_ff(rec, len, buf, sz, xecfg->find_func_priv); + return def_ff(rec, len, buf, sz); return xecfg->find_func(rec, len, buf, sz, xecfg->find_func_priv); } |
