From 9f088edd3a558a4c5068d1f65127eefad9115c30 Mon Sep 17 00:00:00 2001 From: Karthik Nayak Date: Thu, 18 Sep 2025 11:53:37 +0200 Subject: [PATCH 1/2] EDITME: cover title for 583-git-for-each-ref-start-after # Describe the purpose of this series. The information you put here # will be used by the project maintainer to make a decision whether # your patches should be reviewed, and in what priority order. Please be # very detailed and link to any relevant discussions or sites that the # maintainer can review to better understand your proposed changes. If you # only have a single patch in your series, the contents of the cover # letter will be appended to the "under-the-cut" portion of the patch. # Lines starting with # will be removed from the cover letter. You can # use them to add notes or reminders to yourself. If you want to use # markdown headers in your cover letter, start the line with ">#". # You can add trailers to the cover letter. Any email addresses found in # these trailers will be added to the addresses specified/generated # during the b4 send stage. You can also run "b4 prep --auto-to-cc" to # auto-populate the To: and Cc: trailers based on the code being # modified. Signed-off-by: Karthik Nayak --- Changes in v2: - EDITME: describe what is new in this series revision. - EDITME: use bulletpoints and terse descriptions. - Link to v1: https://lore.kernel.org/r/20250924-583-git-for-each-ref-start-after-v1-1-c73be2b5db5a@gmail.com --- b4-submit-tracking --- # This section is used internally by b4 prep for tracking purposes. { "series": { "revision": 2, "change-id": "20250918-583-git-for-each-ref-start-after-fba7b9f59882", "prefixes": [], "history": { "v1": [ "20250924-583-git-for-each-ref-start-after-v1-1-c73be2b5db5a@gmail.com" ] } } } -- GitLab From e68d297313660c169f52cef21a4c5d301939101a Mon Sep 17 00:00:00 2001 From: Karthik Nayak Date: Thu, 18 Sep 2025 13:26:03 +0200 Subject: [PATCH 2/2] refs/ref-cache: fix SEGFAULT when seeking in empty directories The 'cache_ref_iterator_seek()' function is used to seek the `ref_iterator` to the desired reference in the ref-cache mechanism. We use the seeking functionality to implement the '--start-after' flag in 'git-for-each-ref(1)'. When using the files-backend with packed-refs, it is possible that some of the refs directories are empty. For e.g. just after repacking, the 'refs/heads' directory would be empty. The ref-cache seek mechanism doesn't take this into consideration, causing SEGFAULT as we try to access entries within the directory. Fix this by breaking out of the loop when we enter an empty directory. Add tests which simulate this behavior and also provide coverage over using the feature over packed-refs. Signed-off-by: Karthik Nayak --- refs/ref-cache.c | 2 +- t/t6302-for-each-ref-filter.sh | 65 ++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/refs/ref-cache.c b/refs/ref-cache.c index c180e0aad74..e5e5df16d85 100644 --- a/refs/ref-cache.c +++ b/refs/ref-cache.c @@ -539,7 +539,7 @@ static int cache_ref_iterator_seek(struct ref_iterator *ref_iterator, */ break; } - } while (slash); + } while (slash && dir->nr); } return 0; diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh index 9b80ea1e3b7..157b8e52431 100755 --- a/t/t6302-for-each-ref-filter.sh +++ b/t/t6302-for-each-ref-filter.sh @@ -754,4 +754,69 @@ test_expect_success 'start after used with custom sort order' ' test_cmp expect actual ' +test_expect_success 'start after with packed refs' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit default && + + git update-ref --stdin <<-\EOF && + create refs/heads/branch @ + create refs/heads/side @ + create refs/odd/spot @ + create refs/tags/one @ + create refs/tags/two @ + commit + EOF + + cat >expect <<-\EOF && + refs/tags/default + refs/tags/one + refs/tags/two + EOF + + git pack-refs --all && + git for-each-ref --format="%(refname)" --start-after=refs/odd/spot >actual && + test_cmp expect actual + ) +' + +test_expect_success 'start after with packed refs and some loose refs' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit default && + + git update-ref --stdin <<-\EOF && + create refs/heads/branch @ + create refs/heads/side @ + create refs/odd/spot @ + create refs/tags/one @ + create refs/tags/two @ + commit + EOF + + git pack-refs --all && + + git update-ref --stdin <<-EOF && + create refs/heads/foo @ + create refs/odd/tee @ + commit + EOF + + cat >expect <<-\EOF && + refs/odd/tee + refs/tags/default + refs/tags/one + refs/tags/two + EOF + + + git for-each-ref --format="%(refname)" --start-after=refs/odd/spot >actual && + test_cmp expect actual + ) +' + test_done -- GitLab