From 133a9732f0d03a899dd264131ebf343ce3983425 Mon Sep 17 00:00:00 2001 From: Frielbot <183542010+friel-openai@users.noreply.github.com> Date: Wed, 21 Oct 2026 20:48:09 +0000 Subject: [PATCH 1/2] fetch-pack: keep tracking refs consistent with wanted-refs A source-only fetch such as "git fetch origin main" can create separate ref entries for FETCH_HEAD and a configured remote-tracking destination. fetch_pack() deduplicates its sought array by source name. If a protocol-v2 wanted-refs response selects an object different from ls-refs, only the retained entry receives the selected object ID. The tracking entry keeps the discovery object ID. This can leave FETCH_HEAD and the tracking ref inconsistent after a successful fetch. If the selected ref has moved to divergent history and the discovery object is absent locally, connectivity checking can fail because it still includes the stale tracking entry. Retain the original sought pointers and copy each resolved source object's ID back to all entries after fetching. Keep one wire want per source name and preserve the independent local expected-old values used for ref transactions. Exercise source-only fetches, multiple destinations, multiple named refs, and a divergent selected tip that does not include the discovery object. Retain controls for an unmatched tracking mapping and disabled ref-in-want. Signed-off-by: Frielbot <183542010+friel-openai@users.noreply.github.com> --- fetch-pack.c | 17 ++++++ t/t5703-upload-pack-ref-in-want.sh | 98 ++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/fetch-pack.c b/fetch-pack.c index 5d0296f970e464..21dbe93307907e 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -2143,10 +2143,14 @@ struct ref *fetch_pack(struct fetch_pack_args *args, enum protocol_version version) { struct ref *ref_cpy; + struct ref **original_sought; + int original_nr_sought = nr_sought; + int i; struct shallow_info si; struct oid_array shallows_scratch = OID_ARRAY_INIT; fetch_pack_setup(); + DUP_ARRAY(original_sought, sought, nr_sought); if (nr_sought) nr_sought = remove_duplicates_in_refs(sought, nr_sought); @@ -2166,6 +2170,19 @@ struct ref *fetch_pack(struct fetch_pack_args *args, ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought, &si, pack_lockfiles); } + + /* + * Callers can use distinct ref objects for FETCH_HEAD and each tracking + * destination. A wanted-refs response updates the deduplicated entry; + * propagate its object ID to every original entry before callers use it. + */ + for (i = 0; i < original_nr_sought; i++) { + struct ref **found = bsearch(original_sought[i]->name, sought, + nr_sought, sizeof(*sought), cmp_name_ref); + if (found) + oidcpy(&original_sought[i]->old_oid, &(*found)->old_oid); + } + free(original_sought); odb_reprepare(the_repository->objects); if (!args->cloning && args->deepen) { diff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh index 330d049b2c05b5..ab4575d67ec19e 100755 --- a/t/t5703-upload-pack-ref-in-want.sh +++ b/t/t5703-upload-pack-ref-in-want.sh @@ -522,6 +522,104 @@ test_expect_success PERL_TEST_HELPERS 'server is initially behind - ref in want' test_cmp expected actual ' +test_expect_success PERL_TEST_HELPERS 'moving want-ref updates FETCH_HEAD and tracking ref' ' + git -C "$REPO" config uploadpack.allowRefInWant true && + rm -rf local && + cp -r "$LOCAL_PRISTINE" local && + inconsistency main "main^" && + git -C local fetch origin main && + + git -C "$REPO" rev-parse main main >expected && + git -C local rev-parse FETCH_HEAD refs/remotes/origin/main >actual && + test_cmp expected actual +' + +test_expect_success PERL_TEST_HELPERS 'moving want-ref updates every mapped destination' ' + git -C "$REPO" config uploadpack.allowRefInWant true && + rm -rf local && + cp -r "$LOCAL_PRISTINE" local && + inconsistency main "main^" && + git -C local fetch origin main:refs/heads/actual main:refs/heads/extra && + + git -C "$REPO" rev-parse main main main main >expected && + git -C local rev-parse FETCH_HEAD refs/heads/actual refs/heads/extra \ + refs/remotes/origin/main >actual && + test_cmp expected actual +' + +test_expect_success PERL_TEST_HELPERS 'moving want-ref without a tracking mapping' ' + git -C "$REPO" config uploadpack.allowRefInWant true && + rm -rf local && + cp -r "$LOCAL_PRISTINE" local && + git -C local config remote.origin.fetch "+refs/heads/other:refs/remotes/origin/other" && + git -C local rev-parse refs/remotes/origin/main >before && + inconsistency main "main^" && + git -C local fetch origin main && + + git -C "$REPO" rev-parse main >expected && + git -C local rev-parse FETCH_HEAD >actual && + test_cmp expected actual && + git -C local rev-parse refs/remotes/origin/main >after && + test_cmp before after +' + +test_expect_success PERL_TEST_HELPERS 'moving ref without ref-in-want keeps the discovery OID' ' + git -C "$REPO" config uploadpack.allowRefInWant false && + rm -rf local && + cp -r "$LOCAL_PRISTINE" local && + inconsistency main "main^" && + git -C local fetch origin main && + + git -C "$REPO" rev-parse "main^" "main^" >expected && + git -C local rev-parse FETCH_HEAD refs/remotes/origin/main >actual && + test_cmp expected actual +' + +test_expect_success PERL_TEST_HELPERS 'setup a divergent ref' ' + git -C "$REPO" checkout -b divergent "main~2" && + test_commit -C "$REPO" divergent-tip && + git -C "$REPO" tag -d divergent-tip && + git -C "$REPO" checkout main +' + +test_expect_success PERL_TEST_HELPERS 'moving want-ref does not require the discovery object' ' + git -C "$REPO" config uploadpack.allowRefInWant true && + rm -rf local && + cp -r "$LOCAL_PRISTINE" local && + discovery=$(git -C "$REPO" rev-parse "main^") && + test_must_fail git -C local cat-file -e "$discovery" && + inconsistency divergent "main^" && + git -C local fetch origin divergent && + + git -C "$REPO" rev-parse divergent divergent >expected && + git -C local rev-parse FETCH_HEAD refs/remotes/origin/divergent >actual && + test_cmp expected actual && + test_must_fail git -C local cat-file -e "$discovery" && + git -C local fsck --no-dangling +' + +test_expect_success PERL_TEST_HELPERS 'moving want-refs update their own tracking refs' ' + git -C "$REPO" config uploadpack.allowRefInWant true && + rm -rf local && + cp -r "$LOCAL_PRISTINE" local && + main=$(git -C "$REPO" rev-parse main) && + divergent=$(git -C "$REPO" rev-parse divergent) && + discovery=$(git -C "$REPO" rev-parse "main^") && + write_script "$HTTPD_ROOT_PATH/one-time-script" <<-EOF && + sed -e "s/$main/$discovery/" -e "s/$divergent/$discovery/" "\$1" + EOF + git -C local fetch origin main divergent && + + git -C "$REPO" rev-parse main divergent >expected && + git -C local rev-parse refs/remotes/origin/main \ + refs/remotes/origin/divergent >actual && + test_cmp expected actual && + sort expected >expected_heads && + cut -f1 local/.git/FETCH_HEAD | sort >actual_heads && + test_cmp expected_heads actual_heads && + git -C local fsck --no-dangling +' + test_expect_success PERL_TEST_HELPERS 'server loses a ref - ref in want' ' git -C "$REPO" config uploadpack.allowRefInWant true && rm -rf local && From 29984c5974da5c9ed61480c29e1ec5f3620ca001 Mon Sep 17 00:00:00 2001 From: Frielbot <183542010+friel-openai@users.noreply.github.com> Date: Wed, 21 Oct 2026 20:48:46 +0000 Subject: [PATCH 2/2] ci: retain reviewed action pins for topic validation Use the three workflow blobs already admitted by the Codex controller so this topic can run CI under the repository's full-SHA action policy. Signed-off-by: Frielbot <183542010+friel-openai@users.noreply.github.com> --- .github/workflows/check-style.yml | 2 +- .github/workflows/check-whitespace.yml | 2 +- .github/workflows/main.yml | 78 ++++++++++++++------------ 3 files changed, 45 insertions(+), 37 deletions(-) diff --git a/.github/workflows/check-style.yml b/.github/workflows/check-style.yml index 108a2de903310c..b265fe35cbfc51 100644 --- a/.github/workflows/check-style.yml +++ b/.github/workflows/check-style.yml @@ -20,7 +20,7 @@ jobs: jobname: ClangFormat runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 with: fetch-depth: 0 diff --git a/.github/workflows/check-whitespace.yml b/.github/workflows/check-whitespace.yml index ea6f49f742108e..3379f89a814abd 100644 --- a/.github/workflows/check-whitespace.yml +++ b/.github/workflows/check-whitespace.yml @@ -19,7 +19,7 @@ jobs: check-whitespace: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 with: fetch-depth: 0 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 205325eb33b064..44337a67422e01 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -63,7 +63,7 @@ jobs: 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@v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 if: steps.check-ref.outputs.enabled == 'yes' with: github-token: ${{secrets.GITHUB_TOKEN}} @@ -112,8 +112,10 @@ jobs: group: windows-build-${{ github.ref }} cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - - uses: actions/checkout@v6 - - uses: git-for-windows/setup-git-for-windows-sdk@v2 + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 + - uses: git-for-windows/setup-git-for-windows-sdk@aed153d1258c311b680b81584a72a1a4807401f0 # v2.2.1 + with: + architecture: mingw64 - name: build shell: bash env: @@ -123,7 +125,7 @@ jobs: - name: zip up tracked files run: git archive -o artifacts/tracked.tar.gz HEAD - name: upload tracked files and build artifacts - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: windows-artifacts path: artifacts @@ -140,14 +142,16 @@ jobs: cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - name: download tracked files and build artifacts - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: name: windows-artifacts path: ${{github.workspace}} - name: extract tracked files and build artifacts shell: bash run: tar xf artifacts.tar.gz && tar xf tracked.tar.gz - - uses: git-for-windows/setup-git-for-windows-sdk@v2 + - uses: git-for-windows/setup-git-for-windows-sdk@aed153d1258c311b680b81584a72a1a4807401f0 # v2.2.1 + with: + architecture: mingw64 - name: test shell: bash run: . /etc/profile && ci/run-test-slice.sh $((${{matrix.nr}} + 1)) 10 @@ -157,7 +161,7 @@ jobs: run: ci/print-test-failures.sh - name: Upload failed tests' directories if: failure() && env.FAILED_TEST_ARTIFACTS != '' - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: failed-tests-windows-${{ matrix.nr }} path: ${{env.FAILED_TEST_ARTIFACTS}} @@ -173,20 +177,22 @@ jobs: group: vs-build-${{ github.ref }} cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - - uses: actions/checkout@v6 - - uses: git-for-windows/setup-git-for-windows-sdk@v2 + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 + - uses: git-for-windows/setup-git-for-windows-sdk@aed153d1258c311b680b81584a72a1a4807401f0 # v2.2.1 + with: + architecture: mingw64 - name: initialize vcpkg - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 with: repository: 'microsoft/vcpkg' path: 'compat/vcbuild/vcpkg' - name: download vcpkg artifacts - uses: git-for-windows/get-azure-pipelines-artifact@v0 + uses: git-for-windows/get-azure-pipelines-artifact@2e424b98e1251b725d6064c5f1a9f854a33e5b88 # v0 with: repository: git/git definitionId: 9 - name: add msbuild to PATH - uses: microsoft/setup-msbuild@v3 + uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # v3 - name: copy dlls to root shell: cmd run: compat\vcbuild\vcpkg_copy_dlls.bat release @@ -208,7 +214,7 @@ jobs: - name: zip up tracked files run: git archive -o artifacts/tracked.tar.gz HEAD - name: upload tracked files and build artifacts - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: vs-artifacts path: artifacts @@ -224,9 +230,11 @@ jobs: 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@v2 + - uses: git-for-windows/setup-git-for-windows-sdk@aed153d1258c311b680b81584a72a1a4807401f0 # v2.2.1 + with: + architecture: mingw64 - name: download tracked files and build artifacts - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: name: vs-artifacts path: ${{github.workspace}} @@ -244,7 +252,7 @@ jobs: run: ci/print-test-failures.sh - name: Upload failed tests' directories if: failure() && env.FAILED_TEST_ARTIFACTS != '' - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: failed-tests-windows-vs-${{ matrix.nr }} path: ${{env.FAILED_TEST_ARTIFACTS}} @@ -258,8 +266,8 @@ jobs: group: windows-meson-build-${{ github.ref }} cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 - name: Set up dependencies shell: pwsh run: pip install meson ninja @@ -270,7 +278,7 @@ jobs: shell: pwsh run: meson compile -C build - name: Upload build artifacts - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: windows-meson-artifacts path: build @@ -286,13 +294,13 @@ jobs: group: windows-meson-test-${{ matrix.nr }}-${{ github.ref }} cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 - name: Set up dependencies shell: pwsh run: pip install meson ninja - name: Download build artifacts - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: name: windows-meson-artifacts path: build @@ -305,7 +313,7 @@ jobs: run: ci/print-test-failures.sh - name: Upload failed tests' directories if: failure() && env.FAILED_TEST_ARTIFACTS != '' - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: failed-tests-windows-meson-${{ matrix.nr }} path: ${{env.FAILED_TEST_ARTIFACTS}} @@ -341,7 +349,7 @@ jobs: TEST_OUTPUT_DIRECTORY: ${{github.workspace}}/t runs-on: ${{matrix.vector.pool}} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - run: ci/install-dependencies.sh - run: ci/run-build-and-tests.sh - name: print test failures @@ -349,7 +357,7 @@ jobs: run: ci/print-test-failures.sh - name: Upload failed tests' directories if: failure() && env.FAILED_TEST_ARTIFACTS != '' - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: failed-tests-${{matrix.vector.jobname}} path: ${{env.FAILED_TEST_ARTIFACTS}} @@ -362,7 +370,7 @@ jobs: CI_JOB_IMAGE: ubuntu-latest runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - run: ci/install-dependencies.sh - run: ci/run-build-and-minimal-fuzzers.sh dockerized: @@ -411,9 +419,9 @@ jobs: # A RHEL 8 compatible distro. Supported until 2029-05-31. - jobname: almalinux-8 image: almalinux:8 - # Supported until 2026-08-31. - - jobname: debian-11 - image: debian:11 + # Supported until 2028-06-30. + - jobname: debian-12 + image: debian:12 env: jobname: ${{matrix.vector.jobname}} CC: ${{matrix.vector.cc}} @@ -441,7 +449,7 @@ jobs: else apt-get -q update && apt-get -q -y install git fi - - uses: actions/checkout@v6 + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - run: ci/install-dependencies.sh - run: useradd builder --create-home - run: chown -R builder . @@ -451,7 +459,7 @@ jobs: run: sudo --preserve-env --set-home --user=builder ci/print-test-failures.sh - name: Upload failed tests' directories if: failure() && env.FAILED_TEST_ARTIFACTS != '' - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: failed-tests-${{matrix.vector.jobname}} path: ${{env.FAILED_TEST_ARTIFACTS}} @@ -466,7 +474,7 @@ jobs: group: static-analysis-${{ github.ref }} cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - run: ci/install-dependencies.sh - run: ci/run-static-analysis.sh - run: ci/check-directional-formatting.bash @@ -482,7 +490,7 @@ jobs: group: rust-analysis-${{ github.ref }} cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - run: ci/install-dependencies.sh - run: ci/run-rust-checks.sh sparse: @@ -496,7 +504,7 @@ jobs: group: sparse-${{ github.ref }} cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - name: Install other dependencies run: ci/install-dependencies.sh - run: make sparse @@ -512,6 +520,6 @@ jobs: CI_JOB_IMAGE: ubuntu-latest runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - run: ci/install-dependencies.sh - run: ci/test-documentation.sh