{"thread":{"id":"62999","subject":"[PATCH] bundle-uri: copy all bundle references ino the refs/bundle space","startedAt":"2025-02-25T13:19:48Z","lastAt":"2025-04-29T09:00:22Z","messageCount":37,"participants":["Scott Chacon via GitGitGadget","Junio C Hamano","Derrick Stolee","Scott Chacon","Phillip Wood","Taylor Blau","Toon Claes"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"513012","messageId":"pull.1897.git.git.1740489585344.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":null,"subject":"[PATCH] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-02-25T13:19:45Z","receivedAt":"2025-02-25T13:19:48Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"From: Scott Chacon <schacon@gmail.com>\n\nWhen downloading bundles via the bundle-uri functionality, we only copy the\nreferences from refs/heads into the refs/bundle space. I'm not sure why this\nrefspec is hardcoded to be so limited, but it makes the ref negotiation on\nthe subsequent fetch suboptimal, since it won't use objects that are\nreferenced outside of the current heads of the bundled repository.\n\nThis change to copy everything in refs/ in the bundle to refs/bundles/\nsignificantly helps the subsequent fetch, since nearly all the references\nare now included in the negotiation.\n\nSigned-off-by: Scott Chacon <schacon@gmail.com>\n---\n    bundle-uri: copy all bundle references ino the refs/bundle space\n    \n    This patch probably isn't meant for inclusion, but I wanted to see if\n    I'm crazy here or missing something.\n    \n    It appears that the bundle-uri functionality has an issue with ref\n    negotiation. I hit this because I assumed all the objects I bundled\n    would be seen in the negotiation, but since only references under\n    refs/heads are copied to refs/bundles, they are the only ones that are\n    seen for negotiation, so it's quite inefficient.\n    \n    I did several experiments trying to create a bundle where the subsequent\n    fetch was almost a no-op and it was frustratingly impossible and it took\n    me a while to figure out why it kept trying to get tons of other\n    objects.\n    \n    Furthermore, when I bundled just a tag (thinking it would have most\n    reachable objects) it completely failed to work because there were no\n    refs/heads/ available for negotiation - so it downloaded a huge file and\n    then still started from scratch on the fetch.\n    \n    However, if I copy all the refs in the bundle, it makes a big\n    difference.\n    \n    Here are some benchmarks from the gitlab oss repo.\n    \n    A normal clone pulls down 3,005,985 objects:\n    \n    ❯  time git clone https://gitlab.com/gitlab-org/gitlab-foss.git gl5\n    Cloning into 'gl5'...\n    remote: Enumerating objects: 3005985, done.\n    remote: Counting objects: 100% (314617/314617), done.\n    remote: Compressing objects: 100% (64278/64278), done.\n    remote: Total 3005985 (delta 244429), reused 311002 (delta 241404), pack-reused 2691368 (from 1)\n    Receiving objects: 100% (3005985/3005985), 1.35 GiB | 23.91 MiB/s, done.\n    Resolving deltas: 100% (2361484/2361484), done.\n    Updating files: 100% (59972/59972), done.\n    (*) 162.93s user 37.94s system 128% cpu 2:36.49 total\n    \n    \n    Then, I tried to bundle everything from a fresh clone, including all the\n    refs.\n    \n     ❯  git bundle create gitlab-base.bundle --all\n    \n    \n    This creates a 1.4G bundle, which I uploaded to a CDN and cloned again\n    with the bundle-uri:\n    \n    ❯  time git clone --bundle-uri=https://[cdn]/bundle/gitlab-base.bundle https://gitlab.com/gitlab-org/gitlab-foss.git gl4\n    Cloning into 'gl4'...\n    remote: Enumerating objects: 1092703, done.\n    remote: Counting objects: 100% (973405/973405), done.\n    remote: Compressing objects: 100% (385827/385827), done.\n    remote: Total 959773 (delta 710976), reused 766809 (delta 554276), pack-reused 0 (from 0)\n    Receiving objects: 100% (959773/959773), 366.94 MiB | 20.87 MiB/s, done.\n    Resolving deltas: 100% (710976/710976), completed with 9081 local objects.\n    Checking objects: 100% (4194304/4194304), done.\n    Checking connectivity: 959668, done.\n    Updating files: 100% (59972/59972), done.\n    (*) 181.98s user 40.23s system 110% cpu 3:20.89 total\n    \n    \n    Which is better from an \"objects from the server\" perspective, but still\n    has to download 959,773 objects, so 32% of the total. But it also takes\n    quite a lot longer, because it's redownloading most of those objects for\n    a second time.\n    \n    If I apply this patch where I change the refspec for the bundle ref copy\n    from refs/heads/ to just refs/ and clone with this patched version, it's\n    much better:\n    \n    ❯  time ./git clone --bundle-uri=https://[cdn]/bundle/gitlab-base.bundle https://gitlab.com/gitlab-org/gitlab-foss.git gl3\n    Cloning into 'gl3'...\n    remote: Enumerating objects: 65538, done.\n    remote: Counting objects: 100% (56054/56054), done.\n    remote: Compressing objects: 100% (28950/28950), done.\n    remote: Total 43877 (delta 27401), reused 25170 (delta 13546), pack-reused 0 (from 0)\n    Receiving objects: 100% (43877/43877), 40.42 MiB | 22.27 MiB/s, done.\n    Resolving deltas: 100% (27401/27401), completed with 8564 local objects.\n    Updating files: 100% (59972/59972), done.\n    (*) 143.45s user 29.33s system 124% cpu 2:19.27 total\n    \n    \n    Now I'm only getting an extra 43k objects, so 1% of the original total,\n    and the entire operation is a bit faster as well.\n    \n    I'm not sure if there is a downside here, it seems clearly how you would\n    want the negotiation to go. It ends up with way more refs under\n    refs/bundle (now there is refs/bundle/origin/master, etc) but that's\n    being polluted by the head refs anyhow, right?\n    \n    Is this a reasonable change?\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1897%2Fschacon%2Fsc-more-bundle-refs-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1897/schacon/sc-more-bundle-refs-v1\nPull-Request: https://github.com/git/git/pull/1897\n\n bundle-uri.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/bundle-uri.c b/bundle-uri.c\nindex 744257c49c1..3371d56f4ce 100644\n--- a/bundle-uri.c\n+++ b/bundle-uri.c\n@@ -403,7 +403,7 @@ static int unbundle_from_file(struct repository *r, const char *file)\n \t\tconst char *branch_name;\n \t\tint has_old;\n \n-\t\tif (!skip_prefix(refname->string, \"refs/heads/\", &branch_name))\n+\t\tif (!skip_prefix(refname->string, \"refs/\", &branch_name))\n \t\t\tcontinue;\n \n \t\tstrbuf_setlen(&bundle_ref, bundle_prefix_len);\n\nbase-commit: 2d2a71ce85026edcc40f469678a1035df0dfcf57\n-- \ngitgitgadget\n"},{"id":"513032","messageId":"xmqqv7sxki36.fsf@gitster.g","threadId":"62999","inReplyTo":"pull.1897.git.git.1740489585344.gitgitgadget@gmail.com","subject":"Re: [PATCH] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-02-25T18:14:05Z","receivedAt":"2025-02-25T18:14:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Scott Chacon via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n>     Furthermore, when I bundled just a tag (thinking it would have most\n>     reachable objects) it completely failed to work because there were no\n>     refs/heads/ available for negotiation - so it downloaded a huge file and\n>     then still started from scratch on the fetch.\n\nNice finding.\n\n>     Now I'm only getting an extra 43k objects, so 1% of the original total,\n>     and the entire operation is a bit faster as well.\n\nThat makes all sense.\n\n>     I'm not sure if there is a downside here, it seems clearly how you would\n>     want the negotiation to go. It ends up with way more refs under\n>     refs/bundle (now there is refs/bundle/origin/master, etc) but that's\n>     being polluted by the head refs anyhow, right?\n\nI am not sure what you mean by \"being polluted by the head refs\nanyhow\", but we should be equipped to deal with a repository with\ntons of local branches, so having the comparable number of\nremote-tracking branches instead of local branches now exposed in\nrefs/bundle/remotes/* hierarchy should work equally as well, or we\nwould have something we need to fix.  So in principle I do not see\na problem with this approach.\n\nThe mapping used to be \"refs/heads/foo\" to \"refs/bundles/foo\", but\nnow \"refs/heads/foo\" is mapped to \"refs/bundles/heads/foo\", so that\nyou would presumably be mapping \"refs/remotes/origin/master\" to\n\"refs/bundles/remotes/origin/master\", right?  I hope existing users\nare *not* looking at their resulting refs/bundles/ hierarchy and\nsomehow assuming the original mapping.\n\nThis is not something this \"fix\" changes, but unbundle_all_bundles()\napparently is prepared to handle more than one bundles.  I wonder\nwhat happens when multiple bundles expose the same branch pointing\nat different objects?  The way I read unbundle_from_file() is that\na new one overwrites the previous value, so even though we may have\nall unbundled many bundles, the objects from earlier bundles may\nlose their anchors, subject to be garbage-collected.\n\nImagine creating a bundle with two refs, refs/heads and\nrefs/remotes, and append that bundle as the last bundle of a bunch\nof bundles full of local and remote-tracking branches, that have\npopulated refs/bundles/ hierarchy with tons of refs.  Now the last\nbundle is unbundled, and these two phoney refs would nuke everything\nthat used to be under refs/bundles/heads/* and refs/bundles/remotes/*\nleft by unpacking previous bundles, right?\n\n>     Is this a reasonable change?\n\nThis is mostly Stolee's design, IIRC, so I have CC'ed; the work is\nmostly from 53a50892 (bundle-uri: create basic file-copy logic,\n2022-08-09) that is more than 2 years ago.\n\n> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1897%2Fschacon%2Fsc-more-bundle-refs-v1\n> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1897/schacon/sc-more-bundle-refs-v1\n> Pull-Request: https://github.com/git/git/pull/1897\n>\n>  bundle-uri.c | 2 +-\n>  1 file changed, 1 insertion(+), 1 deletion(-)\n>\n> diff --git a/bundle-uri.c b/bundle-uri.c\n> index 744257c49c1..3371d56f4ce 100644\n> --- a/bundle-uri.c\n> +++ b/bundle-uri.c\n> @@ -403,7 +403,7 @@ static int unbundle_from_file(struct repository *r, const char *file)\n>  \t\tconst char *branch_name;\n>  \t\tint has_old;\n>  \n> -\t\tif (!skip_prefix(refname->string, \"refs/heads/\", &branch_name))\n> +\t\tif (!skip_prefix(refname->string, \"refs/\", &branch_name))\n>  \t\t\tcontinue;\n\nBy skipping only \"refs/\", \"branch_name\" is no longer a branch name,\nwhich may be something we may want to fix, but if we were to address\nthe \"names from later bundles seem to overwrite names used by\nprevious boundles, and unanchor objects obtained from them\" problem,\nI suspect we'd rather want to create new and unique names there,\nwithout assuming or relying on that the names used by these bundles\nare reasonably unique, so this part of the code may have to change\nanyway, so we may not care too deeply at this point.\n\n"},{"id":"513038","messageId":"3a180cca-0573-474a-8835-8015dbe09541@gmail.com","threadId":"62999","inReplyTo":"xmqqv7sxki36.fsf@gitster.g","subject":"Re: [PATCH] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2025-02-25T23:36:44Z","receivedAt":"2025-02-25T23:36:46Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 2/25/25 1:14 PM, Junio C Hamano wrote:\n> \"Scott Chacon via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n> \n>>      Furthermore, when I bundled just a tag (thinking it would have most\n>>      reachable objects) it completely failed to work because there were no\n>>      refs/heads/ available for negotiation - so it downloaded a huge file and\n>>      then still started from scratch on the fetch.\n> \n> Nice finding.\n\nThis is an interesting case that I had not considered in the original\nimplementation.\n\nThe intention of the design is to avoid having the bundle URI fetch\nchanging tag refs, especially annotated tags. Those tag updates are\nexpected to be advertised in the \"git fetch\" output. It would probably\nbe best to peel the tag refs to a commit and then create a fake branch\nfor the bundle.\n\n>>      Now I'm only getting an extra 43k objects, so 1% of the original total,\n>>      and the entire operation is a bit faster as well.\n> \n> That makes all sense.\n> \n>>      I'm not sure if there is a downside here, it seems clearly how you would\n>>      want the negotiation to go. It ends up with way more refs under\n>>      refs/bundle (now there is refs/bundle/origin/master, etc) but that's\n>>      being polluted by the head refs anyhow, right?\n> \n> I am not sure what you mean by \"being polluted by the head refs\n> anyhow\", but we should be equipped to deal with a repository with\n> tons of local branches, so having the comparable number of\n> remote-tracking branches instead of local branches now exposed in\n> refs/bundle/remotes/* hierarchy should work equally as well, or we\n> would have something we need to fix.  So in principle I do not see\n> a problem with this approach.\n> \n> The mapping used to be \"refs/heads/foo\" to \"refs/bundles/foo\", but\n> now \"refs/heads/foo\" is mapped to \"refs/bundles/heads/foo\", so that\n> you would presumably be mapping \"refs/remotes/origin/master\" to\n> \"refs/bundles/remotes/origin/master\", right?  I hope existing users\n> are *not* looking at their resulting refs/bundles/ hierarchy and\n> somehow assuming the original mapping.\n> \n> This is not something this \"fix\" changes, but unbundle_all_bundles()\n> apparently is prepared to handle more than one bundles.  I wonder\n> what happens when multiple bundles expose the same branch pointing\n> at different objects?  The way I read unbundle_from_file() is that\n> a new one overwrites the previous value, so even though we may have\n> all unbundled many bundles, the objects from earlier bundles may\n> lose their anchors, subject to be garbage-collected.\n> \n> Imagine creating a bundle with two refs, refs/heads and\n> refs/remotes, and append that bundle as the last bundle of a bunch\n> of bundles full of local and remote-tracking branches, that have\n> populated refs/bundles/ hierarchy with tons of refs.  Now the last\n> bundle is unbundled, and these two phoney refs would nuke everything\n> that used to be under refs/bundles/heads/* and refs/bundles/remotes/*\n> left by unpacking previous bundles, right?\n> \n>>      Is this a reasonable change?\n> \n> This is mostly Stolee's design, IIRC, so I have CC'ed; the work is\n> mostly from 53a50892 (bundle-uri: create basic file-copy logic,\n> 2022-08-09) that is more than 2 years ago.\n\nThe biggest question I had (and tried to get ahead of on the PR) is\nthe use of a test to demonstrate what kind of bundle files cause this\nissue. It would be important to demosntrate that the repo is still\nusable if \"refs/bundles/tags/v1.0\" exists and points to a tag object.\n\n>> -\t\tif (!skip_prefix(refname->string, \"refs/heads/\", &branch_name))\n>> +\t\tif (!skip_prefix(refname->string, \"refs/\", &branch_name))\n>>   \t\t\tcontinue;\n\nSo I'm OK with relaxing this to be more flexible, but I'm not sure\nwhy the bundles couldn't be created using \"refs/heads/\", possibly via\nchanging the ref names during bundle creation.\n\n> By skipping only \"refs/\", \"branch_name\" is no longer a branch name,\n> which may be something we may want to fix, but if we were to address\n> the \"names from later bundles seem to overwrite names used by\n> previous boundles, and unanchor objects obtained from them\" problem,\n> I suspect we'd rather want to create new and unique names there,\n> without assuming or relying on that the names used by these bundles\n> are reasonably unique, so this part of the code may have to change\n> anyway, so we may not care too deeply at this point.\n\nThanks,\n-Stolee\n\n"},{"id":"513323","messageId":"CAP2yMa+YoxRaf48mS7mUbNnsfCm2Z=FT5Gohq_oWz0Q8XnH_eQ@mail.gmail.com","threadId":"62999","inReplyTo":"3a180cca-0573-474a-8835-8015dbe09541@gmail.com","subject":"Re: [PATCH] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Scott Chacon","fromEmail":"schacon@gmail.com","sentAt":"2025-03-01T10:23:08Z","receivedAt":"2025-03-01T10:23:22Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"Hey,\n\nOn Wed, Feb 26, 2025 at 12:36 AM Derrick Stolee <stolee@gmail.com> wrote:\n>\n> The intention of the design is to avoid having the bundle URI fetch\n> changing tag refs, especially annotated tags. Those tag updates are\n> expected to be advertised in the \"git fetch\" output. It would probably\n> be best to peel the tag refs to a commit and then create a fake branch\n> for the bundle.\n\nThe issue for this and also for the other suggestion you have later on\nis that I'm not sure how this can be easily done with the bundle\ncommand. It seems like everyone would have to write some sort of\nscript to create a special type of bundle so that all these objects\nare referenced in a way that makes the bundle-uri helper actually get\nmost of the objects that are needed.\n\nIs there some option to rev-list that does this? Or are you saying\nit's better to write a script?\n\n> The biggest question I had (and tried to get ahead of on the PR) is\n> the use of a test to demonstrate what kind of bundle files cause this\n> issue. It would be important to demosntrate that the repo is still\n> usable if \"refs/bundles/tags/v1.0\" exists and points to a tag object.\n\nI have written a test and I'll submit the new series in a minute, but\nI'm not sure what you mean by 'usable' in this context. Is there a\nsituation where Git gets mad if there are annotated tags that aren't\nunder refs/tags?\n\nI have done these test clones and nothing bad seems to happen having\nthem in refs/bundle/tags/v1.0 that I notice, but I don't know how to\nwrite a test that specifically verifies that.\n\n> So I'm OK with relaxing this to be more flexible, but I'm not sure\n> why the bundles couldn't be created using \"refs/heads/\", possibly via\n> changing the ref names during bundle creation.\n\nSo same point here. I think the bundle-uri functionality isn't\nparticularly effective if the creation of the bundle needs special\nscripts to create in a way that is expected.\n\nOne other approach would be to add an option to `git bundle` that does\nthis sanitization (unpeeling things into fake branch heads), like some\n`--bundle-for-uri`, but I feel like just using `--all` and having the\nclone handle it in the way I proposed might be much simpler and more\nusable.\n\nWe could also immediately delete everything under `refs/bundle/tags`\nafter the fetch if we don't like them there, but still having them be\navailable for the fetch negotiation.\n\nI'll send a new series with the existing tests updated to look for\n`refs/bundle/heads/*` instead of `refs/bundle/*` and adding a very\nsimple test to see that the tags were unpacked as the next step.\n\nScott\n"},{"id":"513324","messageId":"pull.1897.v2.git.git.1740825238.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.git.git.1740489585344.gitgitgadget@gmail.com","subject":"[PATCH v2 0/3] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-03-01T10:33:55Z","receivedAt":"2025-03-01T10:34:01Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"Updating the series by fixing the tests to look in the new space that heads\nare placed and added a small test to check for tags.\n\nScott Chacon (3):\n  bundle-uri: copy all bundle references ino the refs/bundle space\n  bundle-uri: update bundle clone tests with new refspec path\n  bundle-uri: add test for bundle-uri clones with tags\n\n bundle-uri.c                |   2 +-\n t/t5558-clone-bundle-uri.sh | 203 +++++++++++++++++++++---------------\n 2 files changed, 118 insertions(+), 87 deletions(-)\n\n\nbase-commit: cb0ae672aeabefca9704477ea8018ac94f523970\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1897%2Fschacon%2Fsc-more-bundle-refs-v2\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1897/schacon/sc-more-bundle-refs-v2\nPull-Request: https://github.com/git/git/pull/1897\n\nRange-diff vs v1:\n\n 1:  96d78614214 = 1:  b36bc876fe1 bundle-uri: copy all bundle references ino the refs/bundle space\n -:  ----------- > 2:  5e198ba5c66 bundle-uri: update bundle clone tests with new refspec path\n -:  ----------- > 3:  ea204679cb0 bundle-uri: add test for bundle-uri clones with tags\n\n-- \ngitgitgadget\n"},{"id":"513325","messageId":"b36bc876fe1facbb278de0a58262843e5c88738c.1740825238.git.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v2.git.git.1740825238.gitgitgadget@gmail.com","subject":"[PATCH v2 1/3] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-03-01T10:33:56Z","receivedAt":"2025-03-01T10:34:02Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"From: Scott Chacon <schacon@gmail.com>\n\nWhen downloading bundles via the bundle-uri functionality, we only copy the\nreferences from refs/heads into the refs/bundle space. I'm not sure why this\nrefspec is hardcoded to be so limited, but it makes the ref negotiation on\nthe subsequent fetch suboptimal, since it won't use objects that are\nreferenced outside of the current heads of the bundled repository.\n\nThis change to copy everything in refs/ in the bundle to refs/bundles/\nsignificantly helps the subsequent fetch, since nearly all the references\nare now included in the negotiation.\n\nSigned-off-by: Scott Chacon <schacon@gmail.com>\n---\n bundle-uri.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/bundle-uri.c b/bundle-uri.c\nindex 744257c49c1..3371d56f4ce 100644\n--- a/bundle-uri.c\n+++ b/bundle-uri.c\n@@ -403,7 +403,7 @@ static int unbundle_from_file(struct repository *r, const char *file)\n \t\tconst char *branch_name;\n \t\tint has_old;\n \n-\t\tif (!skip_prefix(refname->string, \"refs/heads/\", &branch_name))\n+\t\tif (!skip_prefix(refname->string, \"refs/\", &branch_name))\n \t\t\tcontinue;\n \n \t\tstrbuf_setlen(&bundle_ref, bundle_prefix_len);\n-- \ngitgitgadget\n\n"},{"id":"513326","messageId":"5e198ba5c663cc42ac4dc54413fc5d367486d7c0.1740825238.git.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v2.git.git.1740825238.gitgitgadget@gmail.com","subject":"[PATCH v2 2/3] bundle-uri: update bundle clone tests with new refspec path","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-03-01T10:33:57Z","receivedAt":"2025-03-01T10:34:03Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"From: Scott Chacon <schacon@gmail.com>\n\nThe update to the bundle-uri unbundling refspec puts all the heads from a\nbundle file into refs/bundle/heads instead of directly into refs/bundle/ so\nthe tests need to be updated to look in the new heirarchy.\n\nSigned-off-by: Scott Chacon <schacon@gmail.com>\n---\n t/t5558-clone-bundle-uri.sh | 172 ++++++++++++++++++------------------\n 1 file changed, 86 insertions(+), 86 deletions(-)\n\ndiff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh\nindex 3816ed5058d..33a7009e9a2 100755\n--- a/t/t5558-clone-bundle-uri.sh\n+++ b/t/t5558-clone-bundle-uri.sh\n@@ -58,7 +58,7 @@ test_expect_success 'create bundle' '\n test_expect_success 'clone with path bundle' '\n \tgit clone --bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from clone-path &&\n-\tgit -C clone-path rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-path rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -68,9 +68,9 @@ test_expect_success 'clone with bundle that has bad header' '\n \tgit clone --bundle-uri=\"clone-from/bad-header.bundle\" \\\n \t\tclone-from clone-bad-header 2>err &&\n \tcommit_b=$(git -C clone-from rev-parse B) &&\n-\ttest_grep \"trying to write ref '\\''refs/bundles/topic'\\'' with nonexistent object $commit_b\" err &&\n+\ttest_grep \"trying to write ref '\\''refs/bundles/heads/topic'\\'' with nonexistent object $commit_b\" err &&\n \tgit -C clone-bad-header for-each-ref --format=\"%(refname)\" >refs &&\n-\ttest_grep ! \"refs/bundles/\" refs\n+\ttest_grep ! \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone with bundle that has bad object' '\n@@ -78,8 +78,8 @@ test_expect_success 'clone with bundle that has bad object' '\n \tgit clone --bundle-uri=\"clone-from/bad-object.bundle\" \\\n \t\tclone-from clone-bad-object-no-fsck &&\n \tgit -C clone-bad-object-no-fsck for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/bad >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/bad >expect &&\n \ttest_cmp expect actual &&\n \n \t# Unbundle fails with fsckObjects set true, but clone can still proceed.\n@@ -87,14 +87,14 @@ test_expect_success 'clone with bundle that has bad object' '\n \t\tclone-from clone-bad-object-fsck 2>err &&\n \ttest_grep \"missingEmail\" err &&\n \tgit -C clone-bad-object-fsck for-each-ref --format=\"%(refname)\" >refs &&\n-\ttest_grep ! \"refs/bundles/\" refs\n+\ttest_grep ! \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone with path bundle and non-default hash' '\n \ttest_when_finished \"rm -rf clone-path-non-default-hash\" &&\n \tGIT_DEFAULT_HASH=sha256 git clone --bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from clone-path-non-default-hash &&\n-\tgit -C clone-path-non-default-hash rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-path-non-default-hash rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -102,7 +102,7 @@ test_expect_success 'clone with path bundle and non-default hash' '\n test_expect_success 'clone with file:// bundle' '\n \tgit clone --bundle-uri=\"file://$(pwd)/clone-from/B.bundle\" \\\n \t\tclone-from clone-file &&\n-\tgit -C clone-file rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-file rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -173,12 +173,12 @@ test_expect_success 'clone bundle list (file, no heuristic)' '\n \tgit -C clone-list-file cat-file --batch-check <oids &&\n \n \tgit -C clone-list-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -220,10 +220,10 @@ test_expect_success 'clone bundle list (file, all mode, some failures)' '\n \tgit -C clone-all-some cat-file --batch-check <oids &&\n \n \tgit -C clone-all-some for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -253,7 +253,7 @@ test_expect_success 'clone bundle list (file, all mode, all failures)' '\n \tgit -C clone-all-fail cat-file --batch-check <oids &&\n \n \tgit -C clone-all-fail for-each-ref --format=\"%(refname)\" >refs &&\n-\t! grep \"refs/bundles/\" refs\n+\t! grep \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone bundle list (file, any mode)' '\n@@ -282,9 +282,9 @@ test_expect_success 'clone bundle list (file, any mode)' '\n \tgit -C clone-any-file cat-file --batch-check <oids &&\n \n \tgit -C clone-any-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -313,7 +313,7 @@ test_expect_success 'clone bundle list (file, any mode, all failures)' '\n \tgit -C clone-any-fail cat-file --batch-check <oids &&\n \n \tgit -C clone-any-fail for-each-ref --format=\"%(refname)\" >refs &&\n-\t! grep \"refs/bundles/\" refs\n+\t! grep \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'negotiation: bundle with part of wanted commits' '\n@@ -322,10 +322,10 @@ test_expect_success 'negotiation: bundle with part of wanted commits' '\n \tgit clone --no-local --bundle-uri=\"clone-from/A.bundle\" \\\n \t\tclone-from nego-bundle-part &&\n \tgit -C nego-bundle-part for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/topic >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/topic >expect &&\n \ttest_cmp expect actual &&\n-\t# Ensure that refs/bundles/topic are sent as \"have\".\n+\t# Ensure that refs/bundles/heads/topic are sent as \"have\".\n \ttip=$(git -C clone-from rev-parse A) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n@@ -337,8 +337,8 @@ test_expect_success 'negotiation: bundle with all wanted commits' '\n \t\t--bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from nego-bundle-all &&\n \tgit -C nego-bundle-all for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/topic >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/topic >expect &&\n \ttest_cmp expect actual &&\n \t# We already have all needed commits so no \"want\" needed.\n \ttest_grep ! \"clone> want \" trace-packet.txt\n@@ -363,13 +363,13 @@ test_expect_success 'negotiation: bundle list (no heuristic)' '\n \t\tclone-from nego-bundle-list-no-heuristic &&\n \n \tgit -C nego-bundle-list-no-heuristic for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n-\ttip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/left) &&\n+\ttip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/heads/left) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n \n@@ -395,13 +395,13 @@ test_expect_success 'negotiation: bundle list (creationToken)' '\n \t\tclone-from nego-bundle-list-heuristic &&\n \n \tgit -C nego-bundle-list-heuristic for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n-\ttip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/left) &&\n+\ttip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/heads/left) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n \n@@ -428,10 +428,10 @@ test_expect_success 'negotiation: bundle list with all wanted commits' '\n \t\tclone-from nego-bundle-list-all &&\n \n \tgit -C nego-bundle-list-all for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n \t# We already have all needed commits so no \"want\" needed.\n@@ -465,7 +465,7 @@ test_expect_success 'clone HTTP bundle' '\n \n \tgit clone --bundle-uri=\"$HTTPD_URL/B.bundle\" \\\n \t\t\"$HTTPD_URL/smart/fetch.git\" clone-http &&\n-\tgit -C clone-http rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-http rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual &&\n \n@@ -476,7 +476,7 @@ test_expect_success 'clone HTTP bundle with non-default hash' '\n \ttest_when_finished \"rm -rf clone-http-non-default-hash\" &&\n \tGIT_DEFAULT_HASH=sha256 git clone --bundle-uri=\"$HTTPD_URL/B.bundle\" \\\n \t\t\"$HTTPD_URL/smart/fetch.git\" clone-http-non-default-hash &&\n-\tgit -C clone-http-non-default-hash rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-http-non-default-hash rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -553,12 +553,12 @@ test_expect_success 'clone bundle list (HTTP, any mode)' '\n \tgit -C clone-any-http cat-file --batch-check <oids &&\n \n \tgit -C clone-list-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -641,9 +641,9 @@ test_expect_success 'clone incomplete bundle list (http, creationToken)' '\n \ttest_cmp expect actual &&\n \n \t# We now have only one bundle ref.\n-\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -679,13 +679,13 @@ test_expect_success 'clone incomplete bundle list (http, creationToken)' '\n \ttest_cmp expect actual &&\n \n \t# We now have all bundle refs.\n-\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs\n '\n@@ -721,9 +721,9 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \ttest_cmp expect actual &&\n \n \t# only received base ref from bundle-1\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -749,10 +749,10 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \ttest_cmp expect actual &&\n \n \t# received left from bundle-2\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -795,12 +795,12 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \n \t# received merge ref from bundle-4, but right is missing\n \t# because we did not download bundle-3.\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -862,7 +862,7 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# All bundles failed to unbundle\n-\tgit -C download-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \ttest_must_be_empty refs &&\n \n \t# Case 2: middle bundle does not exist, only two bundles can unbundle\n@@ -909,10 +909,10 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# bundle-1 and bundle-3 could unbundle, but bundle-4 could not\n-\tgit -C download-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -961,11 +961,11 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# fake.bundle did not unbundle, but the others did.\n-\tgit -C download-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs\n '\n@@ -1083,15 +1083,15 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/lefter\n-\trefs/bundles/merge\n-\trefs/bundles/right\n-\trefs/bundles/righter\n-\trefs/bundles/top\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/lefter\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n+\trefs/bundles/heads/righter\n+\trefs/bundles/heads/top\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -1144,12 +1144,12 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -1204,13 +1204,13 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/lefter\n-\trefs/bundles/right\n-\trefs/bundles/righter\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/lefter\n+\trefs/bundles/heads/right\n+\trefs/bundles/heads/righter\n \tEOF\n \ttest_cmp expect refs\n '\n-- \ngitgitgadget\n\n"},{"id":"513327","messageId":"ea204679cb0e6e11bb9e034baf1dbf75fea2516a.1740825238.git.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v2.git.git.1740825238.gitgitgadget@gmail.com","subject":"[PATCH v2 3/3] bundle-uri: add test for bundle-uri clones with tags","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-03-01T10:33:58Z","receivedAt":"2025-03-01T10:34:04Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"From: Scott Chacon <schacon@gmail.com>\n\nThe change to the bundle-uri unbundling refspec now includes tags, so this\nadds a simple test to make sure that tags in a bundle are properly added to\nthe cloned repository and will be included in ref negotiation with the\nsubsequent fetch.\n\nSigned-off-by: Scott Chacon <schacon@gmail.com>\n---\n t/t5558-clone-bundle-uri.sh | 31 +++++++++++++++++++++++++++++++\n 1 file changed, 31 insertions(+)\n\ndiff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh\nindex 33a7009e9a2..b1276ba295c 100755\n--- a/t/t5558-clone-bundle-uri.sh\n+++ b/t/t5558-clone-bundle-uri.sh\n@@ -107,6 +107,37 @@ test_expect_success 'clone with file:// bundle' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'create bundle with tags' '\n+\tgit init clone-from-tags &&\n+\t(\n+\t\tcd clone-from-tags &&\n+\t\tgit checkout -b base &&\n+\t\tgit checkout -b topic &&\n+\n+\t\ttest_commit A &&\n+\t\tgit tag tag-A &&\n+\t\tgit checkout -b base &&\n+\t\tgit branch -d topic &&\n+\t\ttest_commit B &&\n+\n+\t\tgit bundle create ALL.bundle --all &&\n+\t\tgit bundle verify ALL.bundle\n+\t)\n+'\n+\n+test_expect_success 'clone with tags bundle' '\n+\tgit clone --bundle-uri=\"clone-from-tags/ALL.bundle\" \\\n+\t\tclone-from-tags clone-tags-path &&\n+\tgit -C clone-tags-path for-each-ref --format=\"%(refname)\" >refs &&\n+\tgrep \"refs/bundles/tags/\" refs >actual &&\n+\tcat >expect <<-\\EOF &&\n+\trefs/bundles/tags/A\n+\trefs/bundles/tags/B\n+\trefs/bundles/tags/tag-A\n+\tEOF\n+\ttest_cmp expect actual\n+'\n+\n # To get interesting tests for bundle lists, we need to construct a\n # somewhat-interesting commit history.\n #\n-- \ngitgitgadget\n"},{"id":"513417","messageId":"xmqqfrjuvy18.fsf@gitster.g","threadId":"62999","inReplyTo":"CAP2yMa+YoxRaf48mS7mUbNnsfCm2Z=FT5Gohq_oWz0Q8XnH_eQ@mail.gmail.com","subject":"Re: [PATCH] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-03-03T17:12:19Z","receivedAt":"2025-03-03T17:12:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Scott Chacon <schacon@gmail.com> writes:\n\n> Hey,\n>\n> On Wed, Feb 26, 2025 at 12:36 AM Derrick Stolee <stolee@gmail.com> wrote:\n>>\n>> The intention of the design is to avoid having the bundle URI fetch\n>> changing tag refs, especially annotated tags. Those tag updates are\n>> expected to be advertised in the \"git fetch\" output. It would probably\n>> be best to peel the tag refs to a commit and then create a fake branch\n>> for the bundle.\n\nI am not sure where that need to avoid including tags comes from.\n\n>> The biggest question I had (and tried to get ahead of on the PR) is\n>> the use of a test to demonstrate what kind of bundle files cause this\n>> issue. It would be important to demosntrate that the repo is still\n>> usable if \"refs/bundles/tags/v1.0\" exists and points to a tag object.\n>\n> I have written a test and I'll submit the new series in a minute, but\n> I'm not sure what you mean by 'usable' in this context. Is there a\n> situation where Git gets mad if there are annotated tags that aren't\n> under refs/tags?\n\nI do not know of any at least for a local consumption of these tags.\n\n> I have done these test clones and nothing bad seems to happen having\n> them in refs/bundle/tags/v1.0 that I notice, but I don't know how to\n> write a test that specifically verifies that.\n\nCan it be some brittleness Derrick is worried about auto-following\nof tags during future \"git fetch\"?  You store a tag that a regular\nfetch may want to store at refs/tags/v1.0 in refs/bundles/tags/v1.0\ntaken from the bundle, and then a later fetch may advance the\nhistory based on you extracted from the bundle---without having to\nrun an explicit \"git fetch --tags\" or \"git fetch origin v1.0\", would\nwe ever obtain \"refs/tags/v1.0\" with only the usual auto-following\nwhen we have the same tag elsewhere?\n\nIn any case, instead of me speculating, I'd prefer to hear from\nDerrick, who is a lot more familiar with the mechanism under\ndiscussion, what the issues are that we want to limit ourselves to\nlocal branches.\n\nThanks.\n"},{"id":"513421","messageId":"1d946797-e4d9-4c53-a728-ef80657e1431@gmail.com","threadId":"62999","inReplyTo":"xmqqfrjuvy18.fsf@gitster.g","subject":"Re: [PATCH] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2025-03-03T18:46:52Z","receivedAt":"2025-03-03T18:46:55Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 3/3/25 12:12 PM, Junio C Hamano wrote:\n> Scott Chacon <schacon@gmail.com> writes:\n> \n>> Hey,\n>>\n>> On Wed, Feb 26, 2025 at 12:36 AM Derrick Stolee <stolee@gmail.com> wrote:\n>>>\n>>> The intention of the design is to avoid having the bundle URI fetch\n>>> changing tag refs, especially annotated tags. Those tag updates are\n>>> expected to be advertised in the \"git fetch\" output. It would probably\n>>> be best to peel the tag refs to a commit and then create a fake branch\n>>> for the bundle.\n> \n> I am not sure where that need to avoid including tags comes from.\n> \n>>> The biggest question I had (and tried to get ahead of on the PR) is\n>>> the use of a test to demonstrate what kind of bundle files cause this\n>>> issue. It would be important to demosntrate that the repo is still\n>>> usable if \"refs/bundles/tags/v1.0\" exists and points to a tag object.\n>>\n>> I have written a test and I'll submit the new series in a minute, but\n>> I'm not sure what you mean by 'usable' in this context. Is there a\n>> situation where Git gets mad if there are annotated tags that aren't\n>> under refs/tags?\n> \n> I do not know of any at least for a local consumption of these tags.\n\nThese ideas about avoiding annotated tags outside of refs/tags/ is\nlikely an invention of my own, and must not be a firm expectation of\nthe Git tool.\n\n>> I have done these test clones and nothing bad seems to happen having\n>> them in refs/bundle/tags/v1.0 that I notice, but I don't know how to\n>> write a test that specifically verifies that.\n> \n> Can it be some brittleness Derrick is worried about auto-following\n> of tags during future \"git fetch\"?  You store a tag that a regular\n> fetch may want to store at refs/tags/v1.0 in refs/bundles/tags/v1.0\n> taken from the bundle, and then a later fetch may advance the\n> history based on you extracted from the bundle---without having to\n> run an explicit \"git fetch --tags\" or \"git fetch origin v1.0\", would\n> we ever obtain \"refs/tags/v1.0\" with only the usual auto-following\n> when we have the same tag elsewhere?\n> \n> In any case, instead of me speculating, I'd prefer to hear from\n> Derrick, who is a lot more familiar with the mechanism under\n> discussion, what the issues are that we want to limit ourselves to\n> local branches.\nMy thinking here is similar to the prefetch maintenance task: we want\nusers who run \"git fetch [origin]\" to see the refs that are being\nupdated by that action in the normal foreground messages. This includes\nnew tag messages, such as in my local copy of the Git repository:\n\n$ git fetch origin\nremote: Enumerating objects: 186, done.\nremote: Counting objects: 100% (168/168), done.\nremote: Compressing objects: 100% (51/51), done.\nremote: Total 186 (delta 120), reused 162 (delta 117), pack-reused 18 (from 2)\nReceiving objects: 100% (186/186), 118.04 KiB | 10.73 MiB/s, done.\nResolving deltas: 100% (122/122), completed with 24 local objects.\n From github.com:git/git\n    b838bf19389..db91954e186  master      -> origin/master\n    2feabab25ac..627208d89de  next        -> origin/next\n  + 9b2be6f7989...39dfbbf0521 seen        -> origin/seen  (forced update)\n    5fa232d8520..fb8899337a8  todo        -> origin/todo\n  * [new tag]                 v2.49.0-rc0 -> v2.49.0-rc0\n\nAs long as these messages are still appearing, then I'm fine with\nthese annotated tags being added to the object database earlier by\nthe bundle URI mechanism.\n\nScott: You also asked about the intended design for bundle URIs and\nthings, and the best places to look are Git's technical docs [1] and\nthe bundle server reference implementation docs [2]. CC Victoria who\nimplemented the reference implementation and wrote those docs.\n\n[1] https://github.com/git/git/blob/master/Documentation/technical/bundle-uri.adoc\n\n[2] \nhttps://github.com/git-ecosystem/git-bundle-server/blob/main/docs/technical/architecture.md\n\nThanks,\n-Stolee\n"},{"id":"513422","messageId":"6bd6f655-4726-4f59-add4-643190a2d086@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v2.git.git.1740825238.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 0/3] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2025-03-03T18:49:14Z","receivedAt":"2025-03-03T18:49:16Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 3/1/25 5:33 AM, Scott Chacon via GitGitGadget wrote:\n> Updating the series by fixing the tests to look in the new space that heads\n> are placed and added a small test to check for tags.\n> \n> Scott Chacon (3):\n>    bundle-uri: copy all bundle references ino the refs/bundle space\n>    bundle-uri: update bundle clone tests with new refspec path\n\nThanks for updating these tests. While I appreciate a small commit, we do\nwant to make sure that each commit passes the test suite whenever possible,\nso these two should be squashed together.\n\n>    bundle-uri: add test for bundle-uri clones with tags\n\nThis new test is good to stay isolated into its own commit for easier review.\n\nThanks,\n-Stolee\n\n"},{"id":"514531","messageId":"pull.1897.v3.git.git.1742312173.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v2.git.git.1740825238.gitgitgadget@gmail.com","subject":"[PATCH v3 0/2] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-03-18T15:36:11Z","receivedAt":"2025-03-18T15:36:16Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"Rebased the series onto current master and squashed the patch that modified\nthe existing test into the main patch.\n\n> bundle-uri: copy all bundle references ino the refs/bundle space\n> bundle-uri: update bundle clone tests with new refspec path\n\nScott Chacon (2):\n  bundle-uri: copy all bundle references ino the refs/bundle space\n  bundle-uri: add test for bundle-uri clones with tags\n\n bundle-uri.c                |   2 +-\n t/t5558-clone-bundle-uri.sh | 203 +++++++++++++++++++++---------------\n 2 files changed, 118 insertions(+), 87 deletions(-)\n\n\nbase-commit: 683c54c999c301c2cd6f715c411407c413b1d84e\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1897%2Fschacon%2Fsc-more-bundle-refs-v3\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1897/schacon/sc-more-bundle-refs-v3\nPull-Request: https://github.com/git/git/pull/1897\n\nRange-diff vs v2:\n\n 1:  b36bc876fe1 < -:  ----------- bundle-uri: copy all bundle references ino the refs/bundle space\n 2:  5e198ba5c66 ! 1:  2ccbfdcc2dc bundle-uri: update bundle clone tests with new refspec path\n     @@ Metadata\n      Author: Scott Chacon <schacon@gmail.com>\n      \n       ## Commit message ##\n     -    bundle-uri: update bundle clone tests with new refspec path\n     +    bundle-uri: copy all bundle references ino the refs/bundle space\n     +\n     +    When downloading bundles via the bundle-uri functionality, we only copy the\n     +    references from refs/heads into the refs/bundle space. I'm not sure why this\n     +    refspec is hardcoded to be so limited, but it makes the ref negotiation on\n     +    the subsequent fetch suboptimal, since it won't use objects that are\n     +    referenced outside of the current heads of the bundled repository.\n     +\n     +    This change to copy everything in refs/ in the bundle to refs/bundles/\n     +    significantly helps the subsequent fetch, since nearly all the references\n     +    are now included in the negotiation.\n      \n          The update to the bundle-uri unbundling refspec puts all the heads from a\n          bundle file into refs/bundle/heads instead of directly into refs/bundle/ so\n     -    the tests need to be updated to look in the new heirarchy.\n     +    the tests also need to be updated to look in the new heirarchy.\n      \n          Signed-off-by: Scott Chacon <schacon@gmail.com>\n      \n     + ## bundle-uri.c ##\n     +@@ bundle-uri.c: static int unbundle_from_file(struct repository *r, const char *file)\n     + \t\tconst char *branch_name;\n     + \t\tint has_old;\n     + \n     +-\t\tif (!skip_prefix(refname->string, \"refs/heads/\", &branch_name))\n     ++\t\tif (!skip_prefix(refname->string, \"refs/\", &branch_name))\n     + \t\t\tcontinue;\n     + \n     + \t\tstrbuf_setlen(&bundle_ref, bundle_prefix_len);\n     +\n       ## t/t5558-clone-bundle-uri.sh ##\n      @@ t/t5558-clone-bundle-uri.sh: test_expect_success 'create bundle' '\n       test_expect_success 'clone with path bundle' '\n 3:  ea204679cb0 = 2:  d148b14c390 bundle-uri: add test for bundle-uri clones with tags\n\n-- \ngitgitgadget\n"},{"id":"514529","messageId":"2ccbfdcc2dcc77aa33aabce3886ca8690b9253ac.1742312173.git.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v3.git.git.1742312173.gitgitgadget@gmail.com","subject":"[PATCH v3 1/2] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-03-18T15:36:12Z","receivedAt":"2025-03-18T15:36:18Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"From: Scott Chacon <schacon@gmail.com>\n\nWhen downloading bundles via the bundle-uri functionality, we only copy the\nreferences from refs/heads into the refs/bundle space. I'm not sure why this\nrefspec is hardcoded to be so limited, but it makes the ref negotiation on\nthe subsequent fetch suboptimal, since it won't use objects that are\nreferenced outside of the current heads of the bundled repository.\n\nThis change to copy everything in refs/ in the bundle to refs/bundles/\nsignificantly helps the subsequent fetch, since nearly all the references\nare now included in the negotiation.\n\nThe update to the bundle-uri unbundling refspec puts all the heads from a\nbundle file into refs/bundle/heads instead of directly into refs/bundle/ so\nthe tests also need to be updated to look in the new heirarchy.\n\nSigned-off-by: Scott Chacon <schacon@gmail.com>\n---\n bundle-uri.c                |   2 +-\n t/t5558-clone-bundle-uri.sh | 172 ++++++++++++++++++------------------\n 2 files changed, 87 insertions(+), 87 deletions(-)\n\ndiff --git a/bundle-uri.c b/bundle-uri.c\nindex 744257c49c1..3371d56f4ce 100644\n--- a/bundle-uri.c\n+++ b/bundle-uri.c\n@@ -403,7 +403,7 @@ static int unbundle_from_file(struct repository *r, const char *file)\n \t\tconst char *branch_name;\n \t\tint has_old;\n \n-\t\tif (!skip_prefix(refname->string, \"refs/heads/\", &branch_name))\n+\t\tif (!skip_prefix(refname->string, \"refs/\", &branch_name))\n \t\t\tcontinue;\n \n \t\tstrbuf_setlen(&bundle_ref, bundle_prefix_len);\ndiff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh\nindex 3816ed5058d..33a7009e9a2 100755\n--- a/t/t5558-clone-bundle-uri.sh\n+++ b/t/t5558-clone-bundle-uri.sh\n@@ -58,7 +58,7 @@ test_expect_success 'create bundle' '\n test_expect_success 'clone with path bundle' '\n \tgit clone --bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from clone-path &&\n-\tgit -C clone-path rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-path rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -68,9 +68,9 @@ test_expect_success 'clone with bundle that has bad header' '\n \tgit clone --bundle-uri=\"clone-from/bad-header.bundle\" \\\n \t\tclone-from clone-bad-header 2>err &&\n \tcommit_b=$(git -C clone-from rev-parse B) &&\n-\ttest_grep \"trying to write ref '\\''refs/bundles/topic'\\'' with nonexistent object $commit_b\" err &&\n+\ttest_grep \"trying to write ref '\\''refs/bundles/heads/topic'\\'' with nonexistent object $commit_b\" err &&\n \tgit -C clone-bad-header for-each-ref --format=\"%(refname)\" >refs &&\n-\ttest_grep ! \"refs/bundles/\" refs\n+\ttest_grep ! \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone with bundle that has bad object' '\n@@ -78,8 +78,8 @@ test_expect_success 'clone with bundle that has bad object' '\n \tgit clone --bundle-uri=\"clone-from/bad-object.bundle\" \\\n \t\tclone-from clone-bad-object-no-fsck &&\n \tgit -C clone-bad-object-no-fsck for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/bad >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/bad >expect &&\n \ttest_cmp expect actual &&\n \n \t# Unbundle fails with fsckObjects set true, but clone can still proceed.\n@@ -87,14 +87,14 @@ test_expect_success 'clone with bundle that has bad object' '\n \t\tclone-from clone-bad-object-fsck 2>err &&\n \ttest_grep \"missingEmail\" err &&\n \tgit -C clone-bad-object-fsck for-each-ref --format=\"%(refname)\" >refs &&\n-\ttest_grep ! \"refs/bundles/\" refs\n+\ttest_grep ! \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone with path bundle and non-default hash' '\n \ttest_when_finished \"rm -rf clone-path-non-default-hash\" &&\n \tGIT_DEFAULT_HASH=sha256 git clone --bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from clone-path-non-default-hash &&\n-\tgit -C clone-path-non-default-hash rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-path-non-default-hash rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -102,7 +102,7 @@ test_expect_success 'clone with path bundle and non-default hash' '\n test_expect_success 'clone with file:// bundle' '\n \tgit clone --bundle-uri=\"file://$(pwd)/clone-from/B.bundle\" \\\n \t\tclone-from clone-file &&\n-\tgit -C clone-file rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-file rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -173,12 +173,12 @@ test_expect_success 'clone bundle list (file, no heuristic)' '\n \tgit -C clone-list-file cat-file --batch-check <oids &&\n \n \tgit -C clone-list-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -220,10 +220,10 @@ test_expect_success 'clone bundle list (file, all mode, some failures)' '\n \tgit -C clone-all-some cat-file --batch-check <oids &&\n \n \tgit -C clone-all-some for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -253,7 +253,7 @@ test_expect_success 'clone bundle list (file, all mode, all failures)' '\n \tgit -C clone-all-fail cat-file --batch-check <oids &&\n \n \tgit -C clone-all-fail for-each-ref --format=\"%(refname)\" >refs &&\n-\t! grep \"refs/bundles/\" refs\n+\t! grep \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone bundle list (file, any mode)' '\n@@ -282,9 +282,9 @@ test_expect_success 'clone bundle list (file, any mode)' '\n \tgit -C clone-any-file cat-file --batch-check <oids &&\n \n \tgit -C clone-any-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -313,7 +313,7 @@ test_expect_success 'clone bundle list (file, any mode, all failures)' '\n \tgit -C clone-any-fail cat-file --batch-check <oids &&\n \n \tgit -C clone-any-fail for-each-ref --format=\"%(refname)\" >refs &&\n-\t! grep \"refs/bundles/\" refs\n+\t! grep \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'negotiation: bundle with part of wanted commits' '\n@@ -322,10 +322,10 @@ test_expect_success 'negotiation: bundle with part of wanted commits' '\n \tgit clone --no-local --bundle-uri=\"clone-from/A.bundle\" \\\n \t\tclone-from nego-bundle-part &&\n \tgit -C nego-bundle-part for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/topic >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/topic >expect &&\n \ttest_cmp expect actual &&\n-\t# Ensure that refs/bundles/topic are sent as \"have\".\n+\t# Ensure that refs/bundles/heads/topic are sent as \"have\".\n \ttip=$(git -C clone-from rev-parse A) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n@@ -337,8 +337,8 @@ test_expect_success 'negotiation: bundle with all wanted commits' '\n \t\t--bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from nego-bundle-all &&\n \tgit -C nego-bundle-all for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/topic >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/topic >expect &&\n \ttest_cmp expect actual &&\n \t# We already have all needed commits so no \"want\" needed.\n \ttest_grep ! \"clone> want \" trace-packet.txt\n@@ -363,13 +363,13 @@ test_expect_success 'negotiation: bundle list (no heuristic)' '\n \t\tclone-from nego-bundle-list-no-heuristic &&\n \n \tgit -C nego-bundle-list-no-heuristic for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n-\ttip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/left) &&\n+\ttip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/heads/left) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n \n@@ -395,13 +395,13 @@ test_expect_success 'negotiation: bundle list (creationToken)' '\n \t\tclone-from nego-bundle-list-heuristic &&\n \n \tgit -C nego-bundle-list-heuristic for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n-\ttip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/left) &&\n+\ttip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/heads/left) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n \n@@ -428,10 +428,10 @@ test_expect_success 'negotiation: bundle list with all wanted commits' '\n \t\tclone-from nego-bundle-list-all &&\n \n \tgit -C nego-bundle-list-all for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n \t# We already have all needed commits so no \"want\" needed.\n@@ -465,7 +465,7 @@ test_expect_success 'clone HTTP bundle' '\n \n \tgit clone --bundle-uri=\"$HTTPD_URL/B.bundle\" \\\n \t\t\"$HTTPD_URL/smart/fetch.git\" clone-http &&\n-\tgit -C clone-http rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-http rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual &&\n \n@@ -476,7 +476,7 @@ test_expect_success 'clone HTTP bundle with non-default hash' '\n \ttest_when_finished \"rm -rf clone-http-non-default-hash\" &&\n \tGIT_DEFAULT_HASH=sha256 git clone --bundle-uri=\"$HTTPD_URL/B.bundle\" \\\n \t\t\"$HTTPD_URL/smart/fetch.git\" clone-http-non-default-hash &&\n-\tgit -C clone-http-non-default-hash rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-http-non-default-hash rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -553,12 +553,12 @@ test_expect_success 'clone bundle list (HTTP, any mode)' '\n \tgit -C clone-any-http cat-file --batch-check <oids &&\n \n \tgit -C clone-list-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -641,9 +641,9 @@ test_expect_success 'clone incomplete bundle list (http, creationToken)' '\n \ttest_cmp expect actual &&\n \n \t# We now have only one bundle ref.\n-\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -679,13 +679,13 @@ test_expect_success 'clone incomplete bundle list (http, creationToken)' '\n \ttest_cmp expect actual &&\n \n \t# We now have all bundle refs.\n-\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs\n '\n@@ -721,9 +721,9 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \ttest_cmp expect actual &&\n \n \t# only received base ref from bundle-1\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -749,10 +749,10 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \ttest_cmp expect actual &&\n \n \t# received left from bundle-2\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -795,12 +795,12 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \n \t# received merge ref from bundle-4, but right is missing\n \t# because we did not download bundle-3.\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -862,7 +862,7 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# All bundles failed to unbundle\n-\tgit -C download-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \ttest_must_be_empty refs &&\n \n \t# Case 2: middle bundle does not exist, only two bundles can unbundle\n@@ -909,10 +909,10 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# bundle-1 and bundle-3 could unbundle, but bundle-4 could not\n-\tgit -C download-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -961,11 +961,11 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# fake.bundle did not unbundle, but the others did.\n-\tgit -C download-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs\n '\n@@ -1083,15 +1083,15 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/lefter\n-\trefs/bundles/merge\n-\trefs/bundles/right\n-\trefs/bundles/righter\n-\trefs/bundles/top\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/lefter\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n+\trefs/bundles/heads/righter\n+\trefs/bundles/heads/top\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -1144,12 +1144,12 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -1204,13 +1204,13 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/lefter\n-\trefs/bundles/right\n-\trefs/bundles/righter\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/lefter\n+\trefs/bundles/heads/right\n+\trefs/bundles/heads/righter\n \tEOF\n \ttest_cmp expect refs\n '\n-- \ngitgitgadget\n\n"},{"id":"514530","messageId":"d148b14c390f74e86bfa14c05e9e186fdcecbeb8.1742312173.git.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v3.git.git.1742312173.gitgitgadget@gmail.com","subject":"[PATCH v3 2/2] bundle-uri: add test for bundle-uri clones with tags","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-03-18T15:36:13Z","receivedAt":"2025-03-18T15:36:18Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"From: Scott Chacon <schacon@gmail.com>\n\nThe change to the bundle-uri unbundling refspec now includes tags, so this\nadds a simple test to make sure that tags in a bundle are properly added to\nthe cloned repository and will be included in ref negotiation with the\nsubsequent fetch.\n\nSigned-off-by: Scott Chacon <schacon@gmail.com>\n---\n t/t5558-clone-bundle-uri.sh | 31 +++++++++++++++++++++++++++++++\n 1 file changed, 31 insertions(+)\n\ndiff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh\nindex 33a7009e9a2..b1276ba295c 100755\n--- a/t/t5558-clone-bundle-uri.sh\n+++ b/t/t5558-clone-bundle-uri.sh\n@@ -107,6 +107,37 @@ test_expect_success 'clone with file:// bundle' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'create bundle with tags' '\n+\tgit init clone-from-tags &&\n+\t(\n+\t\tcd clone-from-tags &&\n+\t\tgit checkout -b base &&\n+\t\tgit checkout -b topic &&\n+\n+\t\ttest_commit A &&\n+\t\tgit tag tag-A &&\n+\t\tgit checkout -b base &&\n+\t\tgit branch -d topic &&\n+\t\ttest_commit B &&\n+\n+\t\tgit bundle create ALL.bundle --all &&\n+\t\tgit bundle verify ALL.bundle\n+\t)\n+'\n+\n+test_expect_success 'clone with tags bundle' '\n+\tgit clone --bundle-uri=\"clone-from-tags/ALL.bundle\" \\\n+\t\tclone-from-tags clone-tags-path &&\n+\tgit -C clone-tags-path for-each-ref --format=\"%(refname)\" >refs &&\n+\tgrep \"refs/bundles/tags/\" refs >actual &&\n+\tcat >expect <<-\\EOF &&\n+\trefs/bundles/tags/A\n+\trefs/bundles/tags/B\n+\trefs/bundles/tags/tag-A\n+\tEOF\n+\ttest_cmp expect actual\n+'\n+\n # To get interesting tests for bundle lists, we need to construct a\n # somewhat-interesting commit history.\n #\n-- \ngitgitgadget\n"},{"id":"514631","messageId":"56d8bd34-1301-40d6-8151-f85fb1d7560b@gmail.com","threadId":"62999","inReplyTo":"2ccbfdcc2dcc77aa33aabce3886ca8690b9253ac.1742312173.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v3 1/2] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2025-03-19T10:24:32Z","receivedAt":"2025-03-19T10:24:41Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Scott\n\nOn 18/03/2025 15:36, Scott Chacon via GitGitGadget wrote:\n> From: Scott Chacon <schacon@gmail.com>\n> \n> When downloading bundles via the bundle-uri functionality, we only copy the\n> references from refs/heads into the refs/bundle space. I'm not sure why this\n> refspec is hardcoded to be so limited, but it makes the ref negotiation on\n> the subsequent fetch suboptimal, since it won't use objects that are\n> referenced outside of the current heads of the bundled repository.\n> \n> This change to copy everything in refs/ in the bundle to refs/bundles/\n> significantly helps the subsequent fetch, since nearly all the references\n> are now included in the negotiation.\n> \n> The update to the bundle-uri unbundling refspec puts all the heads from a\n> bundle file into refs/bundle/heads instead of directly into refs/bundle/ so\n> the tests also need to be updated to look in the new heirarchy.\n\nI've not used the bundle-uri feature but this change sounds sensible. \nThe refspec that's changed here is documented in \nDocumentation/technical/bundle-uri.adoc (see item 2 in the list under \n\"Cloning with Bundle URIs\") so we should update that. That document as \nsays this refspec is configurable but it seems that was never \nimplemented so it would be nice to fix that at the same time.\n\nThanks\n\nPhillip\n\n> Signed-off-by: Scott Chacon <schacon@gmail.com>\n> ---\n>   bundle-uri.c                |   2 +-\n>   t/t5558-clone-bundle-uri.sh | 172 ++++++++++++++++++------------------\n>   2 files changed, 87 insertions(+), 87 deletions(-)\n> \n> diff --git a/bundle-uri.c b/bundle-uri.c\n> index 744257c49c1..3371d56f4ce 100644\n> --- a/bundle-uri.c\n> +++ b/bundle-uri.c\n> @@ -403,7 +403,7 @@ static int unbundle_from_file(struct repository *r, const char *file)\n>   \t\tconst char *branch_name;\n>   \t\tint has_old;\n>   \n> -\t\tif (!skip_prefix(refname->string, \"refs/heads/\", &branch_name))\n> +\t\tif (!skip_prefix(refname->string, \"refs/\", &branch_name))\n>   \t\t\tcontinue;\n>   \n>   \t\tstrbuf_setlen(&bundle_ref, bundle_prefix_len);\n> diff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh\n> index 3816ed5058d..33a7009e9a2 100755\n> --- a/t/t5558-clone-bundle-uri.sh\n> +++ b/t/t5558-clone-bundle-uri.sh\n> @@ -58,7 +58,7 @@ test_expect_success 'create bundle' '\n>   test_expect_success 'clone with path bundle' '\n>   \tgit clone --bundle-uri=\"clone-from/B.bundle\" \\\n>   \t\tclone-from clone-path &&\n> -\tgit -C clone-path rev-parse refs/bundles/topic >actual &&\n> +\tgit -C clone-path rev-parse refs/bundles/heads/topic >actual &&\n>   \tgit -C clone-from rev-parse topic >expect &&\n>   \ttest_cmp expect actual\n>   '\n> @@ -68,9 +68,9 @@ test_expect_success 'clone with bundle that has bad header' '\n>   \tgit clone --bundle-uri=\"clone-from/bad-header.bundle\" \\\n>   \t\tclone-from clone-bad-header 2>err &&\n>   \tcommit_b=$(git -C clone-from rev-parse B) &&\n> -\ttest_grep \"trying to write ref '\\''refs/bundles/topic'\\'' with nonexistent object $commit_b\" err &&\n> +\ttest_grep \"trying to write ref '\\''refs/bundles/heads/topic'\\'' with nonexistent object $commit_b\" err &&\n>   \tgit -C clone-bad-header for-each-ref --format=\"%(refname)\" >refs &&\n> -\ttest_grep ! \"refs/bundles/\" refs\n> +\ttest_grep ! \"refs/bundles/heads/\" refs\n>   '\n>   \n>   test_expect_success 'clone with bundle that has bad object' '\n> @@ -78,8 +78,8 @@ test_expect_success 'clone with bundle that has bad object' '\n>   \tgit clone --bundle-uri=\"clone-from/bad-object.bundle\" \\\n>   \t\tclone-from clone-bad-object-no-fsck &&\n>   \tgit -C clone-bad-object-no-fsck for-each-ref --format=\"%(refname)\" >refs &&\n> -\tgrep \"refs/bundles/\" refs >actual &&\n> -\ttest_write_lines refs/bundles/bad >expect &&\n> +\tgrep \"refs/bundles/heads/\" refs >actual &&\n> +\ttest_write_lines refs/bundles/heads/bad >expect &&\n>   \ttest_cmp expect actual &&\n>   \n>   \t# Unbundle fails with fsckObjects set true, but clone can still proceed.\n> @@ -87,14 +87,14 @@ test_expect_success 'clone with bundle that has bad object' '\n>   \t\tclone-from clone-bad-object-fsck 2>err &&\n>   \ttest_grep \"missingEmail\" err &&\n>   \tgit -C clone-bad-object-fsck for-each-ref --format=\"%(refname)\" >refs &&\n> -\ttest_grep ! \"refs/bundles/\" refs\n> +\ttest_grep ! \"refs/bundles/heads/\" refs\n>   '\n>   \n>   test_expect_success 'clone with path bundle and non-default hash' '\n>   \ttest_when_finished \"rm -rf clone-path-non-default-hash\" &&\n>   \tGIT_DEFAULT_HASH=sha256 git clone --bundle-uri=\"clone-from/B.bundle\" \\\n>   \t\tclone-from clone-path-non-default-hash &&\n> -\tgit -C clone-path-non-default-hash rev-parse refs/bundles/topic >actual &&\n> +\tgit -C clone-path-non-default-hash rev-parse refs/bundles/heads/topic >actual &&\n>   \tgit -C clone-from rev-parse topic >expect &&\n>   \ttest_cmp expect actual\n>   '\n> @@ -102,7 +102,7 @@ test_expect_success 'clone with path bundle and non-default hash' '\n>   test_expect_success 'clone with file:// bundle' '\n>   \tgit clone --bundle-uri=\"file://$(pwd)/clone-from/B.bundle\" \\\n>   \t\tclone-from clone-file &&\n> -\tgit -C clone-file rev-parse refs/bundles/topic >actual &&\n> +\tgit -C clone-file rev-parse refs/bundles/heads/topic >actual &&\n>   \tgit -C clone-from rev-parse topic >expect &&\n>   \ttest_cmp expect actual\n>   '\n> @@ -173,12 +173,12 @@ test_expect_success 'clone bundle list (file, no heuristic)' '\n>   \tgit -C clone-list-file cat-file --batch-check <oids &&\n>   \n>   \tgit -C clone-list-file for-each-ref --format=\"%(refname)\" >refs &&\n> -\tgrep \"refs/bundles/\" refs >actual &&\n> +\tgrep \"refs/bundles/heads/\" refs >actual &&\n>   \tcat >expect <<-\\EOF &&\n> -\trefs/bundles/base\n> -\trefs/bundles/left\n> -\trefs/bundles/merge\n> -\trefs/bundles/right\n> +\trefs/bundles/heads/base\n> +\trefs/bundles/heads/left\n> +\trefs/bundles/heads/merge\n> +\trefs/bundles/heads/right\n>   \tEOF\n>   \ttest_cmp expect actual\n>   '\n> @@ -220,10 +220,10 @@ test_expect_success 'clone bundle list (file, all mode, some failures)' '\n>   \tgit -C clone-all-some cat-file --batch-check <oids &&\n>   \n>   \tgit -C clone-all-some for-each-ref --format=\"%(refname)\" >refs &&\n> -\tgrep \"refs/bundles/\" refs >actual &&\n> +\tgrep \"refs/bundles/heads/\" refs >actual &&\n>   \tcat >expect <<-\\EOF &&\n> -\trefs/bundles/base\n> -\trefs/bundles/left\n> +\trefs/bundles/heads/base\n> +\trefs/bundles/heads/left\n>   \tEOF\n>   \ttest_cmp expect actual\n>   '\n> @@ -253,7 +253,7 @@ test_expect_success 'clone bundle list (file, all mode, all failures)' '\n>   \tgit -C clone-all-fail cat-file --batch-check <oids &&\n>   \n>   \tgit -C clone-all-fail for-each-ref --format=\"%(refname)\" >refs &&\n> -\t! grep \"refs/bundles/\" refs\n> +\t! grep \"refs/bundles/heads/\" refs\n>   '\n>   \n>   test_expect_success 'clone bundle list (file, any mode)' '\n> @@ -282,9 +282,9 @@ test_expect_success 'clone bundle list (file, any mode)' '\n>   \tgit -C clone-any-file cat-file --batch-check <oids &&\n>   \n>   \tgit -C clone-any-file for-each-ref --format=\"%(refname)\" >refs &&\n> -\tgrep \"refs/bundles/\" refs >actual &&\n> +\tgrep \"refs/bundles/heads/\" refs >actual &&\n>   \tcat >expect <<-\\EOF &&\n> -\trefs/bundles/base\n> +\trefs/bundles/heads/base\n>   \tEOF\n>   \ttest_cmp expect actual\n>   '\n> @@ -313,7 +313,7 @@ test_expect_success 'clone bundle list (file, any mode, all failures)' '\n>   \tgit -C clone-any-fail cat-file --batch-check <oids &&\n>   \n>   \tgit -C clone-any-fail for-each-ref --format=\"%(refname)\" >refs &&\n> -\t! grep \"refs/bundles/\" refs\n> +\t! grep \"refs/bundles/heads/\" refs\n>   '\n>   \n>   test_expect_success 'negotiation: bundle with part of wanted commits' '\n> @@ -322,10 +322,10 @@ test_expect_success 'negotiation: bundle with part of wanted commits' '\n>   \tgit clone --no-local --bundle-uri=\"clone-from/A.bundle\" \\\n>   \t\tclone-from nego-bundle-part &&\n>   \tgit -C nego-bundle-part for-each-ref --format=\"%(refname)\" >refs &&\n> -\tgrep \"refs/bundles/\" refs >actual &&\n> -\ttest_write_lines refs/bundles/topic >expect &&\n> +\tgrep \"refs/bundles/heads/\" refs >actual &&\n> +\ttest_write_lines refs/bundles/heads/topic >expect &&\n>   \ttest_cmp expect actual &&\n> -\t# Ensure that refs/bundles/topic are sent as \"have\".\n> +\t# Ensure that refs/bundles/heads/topic are sent as \"have\".\n>   \ttip=$(git -C clone-from rev-parse A) &&\n>   \ttest_grep \"clone> have $tip\" trace-packet.txt\n>   '\n> @@ -337,8 +337,8 @@ test_expect_success 'negotiation: bundle with all wanted commits' '\n>   \t\t--bundle-uri=\"clone-from/B.bundle\" \\\n>   \t\tclone-from nego-bundle-all &&\n>   \tgit -C nego-bundle-all for-each-ref --format=\"%(refname)\" >refs &&\n> -\tgrep \"refs/bundles/\" refs >actual &&\n> -\ttest_write_lines refs/bundles/topic >expect &&\n> +\tgrep \"refs/bundles/heads/\" refs >actual &&\n> +\ttest_write_lines refs/bundles/heads/topic >expect &&\n>   \ttest_cmp expect actual &&\n>   \t# We already have all needed commits so no \"want\" needed.\n>   \ttest_grep ! \"clone> want \" trace-packet.txt\n> @@ -363,13 +363,13 @@ test_expect_success 'negotiation: bundle list (no heuristic)' '\n>   \t\tclone-from nego-bundle-list-no-heuristic &&\n>   \n>   \tgit -C nego-bundle-list-no-heuristic for-each-ref --format=\"%(refname)\" >refs &&\n> -\tgrep \"refs/bundles/\" refs >actual &&\n> +\tgrep \"refs/bundles/heads/\" refs >actual &&\n>   \tcat >expect <<-\\EOF &&\n> -\trefs/bundles/base\n> -\trefs/bundles/left\n> +\trefs/bundles/heads/base\n> +\trefs/bundles/heads/left\n>   \tEOF\n>   \ttest_cmp expect actual &&\n> -\ttip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/left) &&\n> +\ttip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/heads/left) &&\n>   \ttest_grep \"clone> have $tip\" trace-packet.txt\n>   '\n>   \n> @@ -395,13 +395,13 @@ test_expect_success 'negotiation: bundle list (creationToken)' '\n>   \t\tclone-from nego-bundle-list-heuristic &&\n>   \n>   \tgit -C nego-bundle-list-heuristic for-each-ref --format=\"%(refname)\" >refs &&\n> -\tgrep \"refs/bundles/\" refs >actual &&\n> +\tgrep \"refs/bundles/heads/\" refs >actual &&\n>   \tcat >expect <<-\\EOF &&\n> -\trefs/bundles/base\n> -\trefs/bundles/left\n> +\trefs/bundles/heads/base\n> +\trefs/bundles/heads/left\n>   \tEOF\n>   \ttest_cmp expect actual &&\n> -\ttip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/left) &&\n> +\ttip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/heads/left) &&\n>   \ttest_grep \"clone> have $tip\" trace-packet.txt\n>   '\n>   \n> @@ -428,10 +428,10 @@ test_expect_success 'negotiation: bundle list with all wanted commits' '\n>   \t\tclone-from nego-bundle-list-all &&\n>   \n>   \tgit -C nego-bundle-list-all for-each-ref --format=\"%(refname)\" >refs &&\n> -\tgrep \"refs/bundles/\" refs >actual &&\n> +\tgrep \"refs/bundles/heads/\" refs >actual &&\n>   \tcat >expect <<-\\EOF &&\n> -\trefs/bundles/base\n> -\trefs/bundles/left\n> +\trefs/bundles/heads/base\n> +\trefs/bundles/heads/left\n>   \tEOF\n>   \ttest_cmp expect actual &&\n>   \t# We already have all needed commits so no \"want\" needed.\n> @@ -465,7 +465,7 @@ test_expect_success 'clone HTTP bundle' '\n>   \n>   \tgit clone --bundle-uri=\"$HTTPD_URL/B.bundle\" \\\n>   \t\t\"$HTTPD_URL/smart/fetch.git\" clone-http &&\n> -\tgit -C clone-http rev-parse refs/bundles/topic >actual &&\n> +\tgit -C clone-http rev-parse refs/bundles/heads/topic >actual &&\n>   \tgit -C clone-from rev-parse topic >expect &&\n>   \ttest_cmp expect actual &&\n>   \n> @@ -476,7 +476,7 @@ test_expect_success 'clone HTTP bundle with non-default hash' '\n>   \ttest_when_finished \"rm -rf clone-http-non-default-hash\" &&\n>   \tGIT_DEFAULT_HASH=sha256 git clone --bundle-uri=\"$HTTPD_URL/B.bundle\" \\\n>   \t\t\"$HTTPD_URL/smart/fetch.git\" clone-http-non-default-hash &&\n> -\tgit -C clone-http-non-default-hash rev-parse refs/bundles/topic >actual &&\n> +\tgit -C clone-http-non-default-hash rev-parse refs/bundles/heads/topic >actual &&\n>   \tgit -C clone-from rev-parse topic >expect &&\n>   \ttest_cmp expect actual\n>   '\n> @@ -553,12 +553,12 @@ test_expect_success 'clone bundle list (HTTP, any mode)' '\n>   \tgit -C clone-any-http cat-file --batch-check <oids &&\n>   \n>   \tgit -C clone-list-file for-each-ref --format=\"%(refname)\" >refs &&\n> -\tgrep \"refs/bundles/\" refs >actual &&\n> +\tgrep \"refs/bundles/heads/\" refs >actual &&\n>   \tcat >expect <<-\\EOF &&\n> -\trefs/bundles/base\n> -\trefs/bundles/left\n> -\trefs/bundles/merge\n> -\trefs/bundles/right\n> +\trefs/bundles/heads/base\n> +\trefs/bundles/heads/left\n> +\trefs/bundles/heads/merge\n> +\trefs/bundles/heads/right\n>   \tEOF\n>   \ttest_cmp expect actual\n>   '\n> @@ -641,9 +641,9 @@ test_expect_success 'clone incomplete bundle list (http, creationToken)' '\n>   \ttest_cmp expect actual &&\n>   \n>   \t# We now have only one bundle ref.\n> -\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n> +\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n>   \tcat >expect <<-\\EOF &&\n> -\trefs/bundles/base\n> +\trefs/bundles/heads/base\n>   \tEOF\n>   \ttest_cmp expect refs &&\n>   \n> @@ -679,13 +679,13 @@ test_expect_success 'clone incomplete bundle list (http, creationToken)' '\n>   \ttest_cmp expect actual &&\n>   \n>   \t# We now have all bundle refs.\n> -\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n> +\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n>   \n>   \tcat >expect <<-\\EOF &&\n> -\trefs/bundles/base\n> -\trefs/bundles/left\n> -\trefs/bundles/merge\n> -\trefs/bundles/right\n> +\trefs/bundles/heads/base\n> +\trefs/bundles/heads/left\n> +\trefs/bundles/heads/merge\n> +\trefs/bundles/heads/right\n>   \tEOF\n>   \ttest_cmp expect refs\n>   '\n> @@ -721,9 +721,9 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n>   \ttest_cmp expect actual &&\n>   \n>   \t# only received base ref from bundle-1\n> -\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n> +\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n>   \tcat >expect <<-\\EOF &&\n> -\trefs/bundles/base\n> +\trefs/bundles/heads/base\n>   \tEOF\n>   \ttest_cmp expect refs &&\n>   \n> @@ -749,10 +749,10 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n>   \ttest_cmp expect actual &&\n>   \n>   \t# received left from bundle-2\n> -\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n> +\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n>   \tcat >expect <<-\\EOF &&\n> -\trefs/bundles/base\n> -\trefs/bundles/left\n> +\trefs/bundles/heads/base\n> +\trefs/bundles/heads/left\n>   \tEOF\n>   \ttest_cmp expect refs &&\n>   \n> @@ -795,12 +795,12 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n>   \n>   \t# received merge ref from bundle-4, but right is missing\n>   \t# because we did not download bundle-3.\n> -\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n> +\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n>   \n>   \tcat >expect <<-\\EOF &&\n> -\trefs/bundles/base\n> -\trefs/bundles/left\n> -\trefs/bundles/merge\n> +\trefs/bundles/heads/base\n> +\trefs/bundles/heads/left\n> +\trefs/bundles/heads/merge\n>   \tEOF\n>   \ttest_cmp expect refs &&\n>   \n> @@ -862,7 +862,7 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n>   \ttest_cmp expect actual &&\n>   \n>   \t# All bundles failed to unbundle\n> -\tgit -C download-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n> +\tgit -C download-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n>   \ttest_must_be_empty refs &&\n>   \n>   \t# Case 2: middle bundle does not exist, only two bundles can unbundle\n> @@ -909,10 +909,10 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n>   \ttest_cmp expect actual &&\n>   \n>   \t# bundle-1 and bundle-3 could unbundle, but bundle-4 could not\n> -\tgit -C download-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n> +\tgit -C download-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n>   \tcat >expect <<-EOF &&\n> -\trefs/bundles/base\n> -\trefs/bundles/right\n> +\trefs/bundles/heads/base\n> +\trefs/bundles/heads/right\n>   \tEOF\n>   \ttest_cmp expect refs &&\n>   \n> @@ -961,11 +961,11 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n>   \ttest_cmp expect actual &&\n>   \n>   \t# fake.bundle did not unbundle, but the others did.\n> -\tgit -C download-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n> +\tgit -C download-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n>   \tcat >expect <<-EOF &&\n> -\trefs/bundles/base\n> -\trefs/bundles/left\n> -\trefs/bundles/right\n> +\trefs/bundles/heads/base\n> +\trefs/bundles/heads/left\n> +\trefs/bundles/heads/right\n>   \tEOF\n>   \ttest_cmp expect refs\n>   '\n> @@ -1083,15 +1083,15 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n>   \ttest_cmp expect actual &&\n>   \n>   \t# Check which bundles have unbundled by refs\n> -\tgit -C fetch-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n> +\tgit -C fetch-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n>   \tcat >expect <<-EOF &&\n> -\trefs/bundles/base\n> -\trefs/bundles/left\n> -\trefs/bundles/lefter\n> -\trefs/bundles/merge\n> -\trefs/bundles/right\n> -\trefs/bundles/righter\n> -\trefs/bundles/top\n> +\trefs/bundles/heads/base\n> +\trefs/bundles/heads/left\n> +\trefs/bundles/heads/lefter\n> +\trefs/bundles/heads/merge\n> +\trefs/bundles/heads/right\n> +\trefs/bundles/heads/righter\n> +\trefs/bundles/heads/top\n>   \tEOF\n>   \ttest_cmp expect refs &&\n>   \n> @@ -1144,12 +1144,12 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n>   \ttest_cmp expect actual &&\n>   \n>   \t# Check which bundles have unbundled by refs\n> -\tgit -C fetch-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n> +\tgit -C fetch-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n>   \tcat >expect <<-EOF &&\n> -\trefs/bundles/base\n> -\trefs/bundles/left\n> -\trefs/bundles/merge\n> -\trefs/bundles/right\n> +\trefs/bundles/heads/base\n> +\trefs/bundles/heads/left\n> +\trefs/bundles/heads/merge\n> +\trefs/bundles/heads/right\n>   \tEOF\n>   \ttest_cmp expect refs &&\n>   \n> @@ -1204,13 +1204,13 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n>   \ttest_cmp expect actual &&\n>   \n>   \t# Check which bundles have unbundled by refs\n> -\tgit -C fetch-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n> +\tgit -C fetch-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n>   \tcat >expect <<-EOF &&\n> -\trefs/bundles/base\n> -\trefs/bundles/left\n> -\trefs/bundles/lefter\n> -\trefs/bundles/right\n> -\trefs/bundles/righter\n> +\trefs/bundles/heads/base\n> +\trefs/bundles/heads/left\n> +\trefs/bundles/heads/lefter\n> +\trefs/bundles/heads/right\n> +\trefs/bundles/heads/righter\n>   \tEOF\n>   \ttest_cmp expect refs\n>   '\n\n"},{"id":"514632","messageId":"e4244e04-d2f3-43ab-88cf-58d9804731b8@gmail.com","threadId":"62999","inReplyTo":"d148b14c390f74e86bfa14c05e9e186fdcecbeb8.1742312173.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v3 2/2] bundle-uri: add test for bundle-uri clones with tags","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2025-03-19T10:33:48Z","receivedAt":"2025-03-19T10:33:51Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Scott\n\nOn 18/03/2025 15:36, Scott Chacon via GitGitGadget wrote:\n> From: Scott Chacon <schacon@gmail.com>\n> \n> +test_expect_success 'clone with tags bundle' '\n> +\tgit clone --bundle-uri=\"clone-from-tags/ALL.bundle\" \\\n> +\t\tclone-from-tags clone-tags-path &&\n> +\tgit -C clone-tags-path for-each-ref --format=\"%(refname)\" >refs &&\n> +\tgrep \"refs/bundles/tags/\" refs >actual &&\n\nThanks for adding this test. Calling \"git for-each-ref\" followed by \n\"grep\" follows the pattern of the existing tests but I'm not sure why \nthey don't just pass the pattern to \"for-each-ref\" and avoid the extra \nprocess.\n\nDo we want to just test for tags or are we really interested to see all \nthe bundle refs created when cloning? This applies to the previous patch \nas well - we obviously need to change the expected output but I'm not \nsure changing the ref pattern is necessarily a good idea. After all the \npoint of this series is to create refs under refs/bundles for all the \nrefs in the bundle.\n\nBest Wishes\n\nPhillip\n\n> +\tcat >expect <<-\\EOF &&\n> +\trefs/bundles/tags/A\n> +\trefs/bundles/tags/B\n> +\trefs/bundles/tags/tag-A\n> +\tEOF\n> +\ttest_cmp expect actual\n> +'\n> +\n>   # To get interesting tests for bundle lists, we need to construct a\n>   # somewhat-interesting commit history.\n>   #\n\n"},{"id":"514671","messageId":"Z9sD63+d+EQKSMXM@nand.local","threadId":"62999","inReplyTo":"e4244e04-d2f3-43ab-88cf-58d9804731b8@gmail.com","subject":"Re: [PATCH v3 2/2] bundle-uri: add test for bundle-uri clones with tags","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2025-03-19T17:50:35Z","receivedAt":"2025-03-19T17:50:38Z","isPatch":true,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"On Wed, Mar 19, 2025 at 10:33:48AM +0000, Phillip Wood wrote:\n> Hi Scott\n>\n> On 18/03/2025 15:36, Scott Chacon via GitGitGadget wrote:\n> > From: Scott Chacon <schacon@gmail.com>\n> >\n> > +test_expect_success 'clone with tags bundle' '\n> > +\tgit clone --bundle-uri=\"clone-from-tags/ALL.bundle\" \\\n> > +\t\tclone-from-tags clone-tags-path &&\n> > +\tgit -C clone-tags-path for-each-ref --format=\"%(refname)\" >refs &&\n> > +\tgrep \"refs/bundles/tags/\" refs >actual &&\n>\n> Thanks for adding this test. Calling \"git for-each-ref\" followed by \"grep\"\n> follows the pattern of the existing tests but I'm not sure why they don't\n> just pass the pattern to \"for-each-ref\" and avoid the extra process.\n\nIndeed.\n\n> Do we want to just test for tags or are we really interested to see all the\n> bundle refs created when cloning? This applies to the previous patch as well\n> - we obviously need to change the expected output but I'm not sure changing\n> the ref pattern is necessarily a good idea. After all the point of this\n> series is to create refs under refs/bundles for all the refs in the bundle.\n\nI think we should be testing that all of the refs we expect to have made\nit over actually did so. This diff (applied on top of your series) does\nthat:\n\n--- 8< ---\ndiff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh\nindex b1276ba295..9b211a626b 100755\n--- a/t/t5558-clone-bundle-uri.sh\n+++ b/t/t5558-clone-bundle-uri.sh\n@@ -128,13 +128,12 @@ test_expect_success 'create bundle with tags' '\n test_expect_success 'clone with tags bundle' '\n \tgit clone --bundle-uri=\"clone-from-tags/ALL.bundle\" \\\n \t\tclone-from-tags clone-tags-path &&\n-\tgit -C clone-tags-path for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/tags/\" refs >actual &&\n-\tcat >expect <<-\\EOF &&\n-\trefs/bundles/tags/A\n-\trefs/bundles/tags/B\n-\trefs/bundles/tags/tag-A\n-\tEOF\n+\n+\tgit -C clone-from-tags for-each-ref --format=\"%(refname:lstrip=1)\" \\\n+\t\t>expect &&\n+\tgit -C clone-tags-path for-each-ref --format=\"%(refname:lstrip=2)\" \\\n+\t\trefs/bundles >actual &&\n+\n \ttest_cmp expect actual\n '\n--- >8 ---\n\nWhile writing the above, I wasn't quite sure how to follow the test\nsetup. It looks like it creates the following structure:\n\n    $ git log --oneline --graph\n    * d9df450 (HEAD -> base, tag: B) B\n    * 0ddfaf1 (tag: tag-A, tag: A) A\n\n, which we could do with just:\n\n    test_commit A &&\n    test_commit B\n\nBut even then, I don't think we really need to have more than one tag\nhere to exercise this functionality. So I think it would be fine to\nsimplify the test to just create a single tag, which a simple\n\"test_commit A\" should do.\n\nThanks,\nTaylor\n"},{"id":"514821","messageId":"xmqqy0wyvqr2.fsf@gitster.g","threadId":"62999","inReplyTo":"e4244e04-d2f3-43ab-88cf-58d9804731b8@gmail.com","subject":"Re: [PATCH v3 2/2] bundle-uri: add test for bundle-uri clones with tags","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-03-21T06:31:45Z","receivedAt":"2025-03-21T06:31:47Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> Hi Scott\n>\n> On 18/03/2025 15:36, Scott Chacon via GitGitGadget wrote:\n>> From: Scott Chacon <schacon@gmail.com>\n>> +test_expect_success 'clone with tags bundle' '\n>> +\tgit clone --bundle-uri=\"clone-from-tags/ALL.bundle\" \\\n>> +\t\tclone-from-tags clone-tags-path &&\n>> +\tgit -C clone-tags-path for-each-ref --format=\"%(refname)\" >refs &&\n>> +\tgrep \"refs/bundles/tags/\" refs >actual &&\n>\n> Thanks for adding this test. Calling \"git for-each-ref\" followed by\n> \"grep\" follows the pattern of the existing tests but I'm not sure why\n> they don't just pass the pattern to \"for-each-ref\" and avoid the extra\n> process.\n\nYup, if we really care about a single ref, we should just go in the\nclone and check with 'git show-ref'.\n\n> Do we want to just test for tags or are we really interested to see\n> all the bundle refs created when cloning? This applies to the previous\n> patch as well - we obviously need to change the expected output but\n> I'm not sure changing the ref pattern is necessarily a good\n> idea. After all the point of this series is to create refs under\n> refs/bundles for all the refs in the bundle.\n\nThe really interesting case that the original behaviour could have\nbeen \"working around existing bugs\" would be\n\n - prepare an annotated tag.\n\n - include that annotated tag in the bundle specified by the\n   bundle-uri feature (whose SOLE purpose is to speed up the main\n   part of the tranfer, WITHOUT affecting the resulting remote\n   tracking refs and global tag namespace).\n\n - prepare a repository that uses that bundle as bundle-uri when\n   getting cloned (let's call it the 'origin' repository).  It\n   probably is convenient if you make this a repository  separate\n   from where you prepared the bundle above.  Make sure that this\n   repository does *not* (yet) have that annotated tag.\n\n - clone from the 'origin' repository with bundle-uri feature.  The\n   annotated tag would be held under refs/bundles/tags/ hierarchy but\n   that is *not* the interesting part.  Make sure that the annotated\n   tag does *not* appear in refs/tags/ hierarchy of the clone, since\n   it does not exist (yet) at the 'origin' repository.\n\n - Now add that annotated tag to the 'origin' repository.\n\n - fetch from the 'origin' repository again, with the default\n   configuration (i.e. allowing \"tags follow when commits they\n   reference are fetched\" feature to kick in).  As the annotated tag\n   appears in refs/tags/ of the 'origin' repository, the commit\n   pointed at by that annotated tag now appears in one of its\n   branches, and the history leading to that commit (and possibly\n   others) are transferred to refs/remotes/origin/* remote-tracking\n   branches, the tag-following feature should kick in and copy the\n   annotated tag in refs/tags/ hierarchy as well.\n\nThe interesting part to verify is that in the cloned repository the\nannotated tag does not appear in refs/tags/ immediately after\ncloneing, but does appear there after the 'origin' is updated to\nhave the tag under refs/tags/ and then fetch\n\n"},{"id":"516092","messageId":"87cydf541c.fsf@iotcl.com","threadId":"62999","inReplyTo":"Z9sD63+d+EQKSMXM@nand.local","subject":"Re: [PATCH v3 2/2] bundle-uri: add test for bundle-uri clones with tags","fromName":"Toon Claes","fromEmail":"toon@iotcl.com","sentAt":"2025-04-14T12:19:27Z","receivedAt":"2025-04-14T12:19:39Z","isPatch":true,"sender":{"key":"toon@iotcl.com","avatar":"https://avatars.githubusercontent.com/u/121621?v=4"},"body":"Taylor Blau <me@ttaylorr.com> writes:\n\n> I think we should be testing that all of the refs we expect to have made\n> it over actually did so. This diff (applied on top of your series) does\n> that:\n>\n> --- 8< ---\n> diff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh\n> index b1276ba295..9b211a626b 100755\n> --- a/t/t5558-clone-bundle-uri.sh\n> +++ b/t/t5558-clone-bundle-uri.sh\n> @@ -128,13 +128,12 @@ test_expect_success 'create bundle with tags' '\n>  test_expect_success 'clone with tags bundle' '\n>  \tgit clone --bundle-uri=\"clone-from-tags/ALL.bundle\" \\\n>  \t\tclone-from-tags clone-tags-path &&\n> -\tgit -C clone-tags-path for-each-ref --format=\"%(refname)\" >refs &&\n> -\tgrep \"refs/bundles/tags/\" refs >actual &&\n> -\tcat >expect <<-\\EOF &&\n> -\trefs/bundles/tags/A\n> -\trefs/bundles/tags/B\n> -\trefs/bundles/tags/tag-A\n> -\tEOF\n> +\n> +\tgit -C clone-from-tags for-each-ref --format=\"%(refname:lstrip=1)\" \\\n> +\t\t>expect &&\n> +\tgit -C clone-tags-path for-each-ref --format=\"%(refname:lstrip=2)\" \\\n> +\t\trefs/bundles >actual &&\n> +\n>  \ttest_cmp expect actual\n>  '\n> --- >8 ---\n>\n> While writing the above, I wasn't quite sure how to follow the test\n> setup. It looks like it creates the following structure:\n>\n>     $ git log --oneline --graph\n>     * d9df450 (HEAD -> base, tag: B) B\n>     * 0ddfaf1 (tag: tag-A, tag: A) A\n>\n> , which we could do with just:\n>\n>     test_commit A &&\n>     test_commit B\n>\n> But even then, I don't think we really need to have more than one tag\n> here to exercise this functionality. So I think it would be fine to\n> simplify the test to just create a single tag, which a simple\n> \"test_commit A\" should do.\n\nHi Scott,\n\nAre you planning to pick up this patch series again? I think it would be\nreally valuable to get this merged. The patch by Taylor above might be\nworth integrating, other than that I think it should be good to go.\n\nLet me know if I can provide any help.\n\n-- \nToon\n"},{"id":"516795","messageId":"CAP2yMaJZU2nmKezHvePaHQ780SXSvcemoDGL+n65f8yv4N+VJA@mail.gmail.com","threadId":"62999","inReplyTo":"87cydf541c.fsf@iotcl.com","subject":"Re: [PATCH v3 2/2] bundle-uri: add test for bundle-uri clones with tags","fromName":"Scott Chacon","fromEmail":"schacon@gmail.com","sentAt":"2025-04-25T13:14:48Z","receivedAt":"2025-04-25T13:15:02Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"Hey Toon,\n\nSo, I got a bit thrown by Junio's message as I'm not sure how to even\napproach writing that test case. I had a bit of a time figuring out\nthe testing structure enough to even write the tests I did.\n\nI updated my series with Taylor's patch and I'll resubmit it. Beyond\nthat I may need someone else to help me with more complicated testing\nneeds if more work is to be done.\n\nThanks,\nScott\n\n\nOn Mon, Apr 14, 2025 at 8:19 AM Toon Claes <toon@iotcl.com> wrote:\n>\n> Taylor Blau <me@ttaylorr.com> writes:\n>\n> > I think we should be testing that all of the refs we expect to have made\n> > it over actually did so. This diff (applied on top of your series) does\n> > that:\n> >\n> > --- 8< ---\n> > diff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh\n> > index b1276ba295..9b211a626b 100755\n> > --- a/t/t5558-clone-bundle-uri.sh\n> > +++ b/t/t5558-clone-bundle-uri.sh\n> > @@ -128,13 +128,12 @@ test_expect_success 'create bundle with tags' '\n> >  test_expect_success 'clone with tags bundle' '\n> >       git clone --bundle-uri=\"clone-from-tags/ALL.bundle\" \\\n> >               clone-from-tags clone-tags-path &&\n> > -     git -C clone-tags-path for-each-ref --format=\"%(refname)\" >refs &&\n> > -     grep \"refs/bundles/tags/\" refs >actual &&\n> > -     cat >expect <<-\\EOF &&\n> > -     refs/bundles/tags/A\n> > -     refs/bundles/tags/B\n> > -     refs/bundles/tags/tag-A\n> > -     EOF\n> > +\n> > +     git -C clone-from-tags for-each-ref --format=\"%(refname:lstrip=1)\" \\\n> > +             >expect &&\n> > +     git -C clone-tags-path for-each-ref --format=\"%(refname:lstrip=2)\" \\\n> > +             refs/bundles >actual &&\n> > +\n> >       test_cmp expect actual\n> >  '\n> > --- >8 ---\n> >\n> > While writing the above, I wasn't quite sure how to follow the test\n> > setup. It looks like it creates the following structure:\n> >\n> >     $ git log --oneline --graph\n> >     * d9df450 (HEAD -> base, tag: B) B\n> >     * 0ddfaf1 (tag: tag-A, tag: A) A\n> >\n> > , which we could do with just:\n> >\n> >     test_commit A &&\n> >     test_commit B\n> >\n> > But even then, I don't think we really need to have more than one tag\n> > here to exercise this functionality. So I think it would be fine to\n> > simplify the test to just create a single tag, which a simple\n> > \"test_commit A\" should do.\n>\n> Hi Scott,\n>\n> Are you planning to pick up this patch series again? I think it would be\n> really valuable to get this merged. The patch by Taylor above might be\n> worth integrating, other than that I think it should be good to go.\n>\n> Let me know if I can provide any help.\n>\n> --\n> Toon\n"},{"id":"516796","messageId":"pull.1897.v4.git.git.1745587067.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v3.git.git.1742312173.gitgitgadget@gmail.com","subject":"[PATCH v4 0/2] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-04-25T13:17:45Z","receivedAt":"2025-04-25T13:17:51Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"Updated the test with Taylor's patch.\n\n> bundle-uri: copy all bundle references ino the refs/bundle space\n> bundle-uri: update bundle clone tests with new refspec path\n\nScott Chacon (2):\n  bundle-uri: copy all bundle references ino the refs/bundle space\n  bundle-uri: add test for bundle-uri clones with tags\n\n bundle-uri.c                |   2 +-\n t/t5558-clone-bundle-uri.sh | 202 +++++++++++++++++++++---------------\n 2 files changed, 117 insertions(+), 87 deletions(-)\n\n\nbase-commit: f65182a99e545d2f2bc22e6c1c2da192133b16a3\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1897%2Fschacon%2Fsc-more-bundle-refs-v4\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1897/schacon/sc-more-bundle-refs-v4\nPull-Request: https://github.com/git/git/pull/1897\n\nRange-diff vs v3:\n\n 1:  2ccbfdcc2dc = 1:  6957ee2fed2 bundle-uri: copy all bundle references ino the refs/bundle space\n 2:  d148b14c390 ! 2:  d9a114915a3 bundle-uri: add test for bundle-uri clones with tags\n     @@ Commit message\n          bundle-uri: add test for bundle-uri clones with tags\n      \n          The change to the bundle-uri unbundling refspec now includes tags, so this\n     -    adds a simple test to make sure that tags in a bundle are properly added to\n     -    the cloned repository and will be included in ref negotiation with the\n     -    subsequent fetch.\n     +    adds a very, very simple test to make sure that tags in a bundle are\n     +    properly added to the cloned repository and will be included in ref\n     +    negotiation with the subsequent fetch. ok, now it's right. christ.\n      \n          Signed-off-by: Scott Chacon <schacon@gmail.com>\n      \n     @@ t/t5558-clone-bundle-uri.sh: test_expect_success 'clone with file:// bundle' '\n      +test_expect_success 'clone with tags bundle' '\n      +\tgit clone --bundle-uri=\"clone-from-tags/ALL.bundle\" \\\n      +\t\tclone-from-tags clone-tags-path &&\n     -+\tgit -C clone-tags-path for-each-ref --format=\"%(refname)\" >refs &&\n     -+\tgrep \"refs/bundles/tags/\" refs >actual &&\n     -+\tcat >expect <<-\\EOF &&\n     -+\trefs/bundles/tags/A\n     -+\trefs/bundles/tags/B\n     -+\trefs/bundles/tags/tag-A\n     -+\tEOF\n     ++\n     ++\tgit -C clone-from-tags for-each-ref --format=\"%(refname:lstrip=1)\" \\\n     ++\t\t>expect &&\n     ++\tgit -C clone-tags-path for-each-ref --format=\"%(refname:lstrip=2)\" \\\n     ++\t\trefs/bundles >actual &&\n     ++\n      +\ttest_cmp expect actual\n      +'\n      +\n\n-- \ngitgitgadget\n"},{"id":"516797","messageId":"6957ee2fed2f04ad7cd02e5785eb89a1a55f81f5.1745587067.git.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v4.git.git.1745587067.gitgitgadget@gmail.com","subject":"[PATCH v4 1/2] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-04-25T13:17:46Z","receivedAt":"2025-04-25T13:17:52Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"From: Scott Chacon <schacon@gmail.com>\n\nWhen downloading bundles via the bundle-uri functionality, we only copy the\nreferences from refs/heads into the refs/bundle space. I'm not sure why this\nrefspec is hardcoded to be so limited, but it makes the ref negotiation on\nthe subsequent fetch suboptimal, since it won't use objects that are\nreferenced outside of the current heads of the bundled repository.\n\nThis change to copy everything in refs/ in the bundle to refs/bundles/\nsignificantly helps the subsequent fetch, since nearly all the references\nare now included in the negotiation.\n\nThe update to the bundle-uri unbundling refspec puts all the heads from a\nbundle file into refs/bundle/heads instead of directly into refs/bundle/ so\nthe tests also need to be updated to look in the new heirarchy.\n\nSigned-off-by: Scott Chacon <schacon@gmail.com>\n---\n bundle-uri.c                |   2 +-\n t/t5558-clone-bundle-uri.sh | 172 ++++++++++++++++++------------------\n 2 files changed, 87 insertions(+), 87 deletions(-)\n\ndiff --git a/bundle-uri.c b/bundle-uri.c\nindex 96d2ba726d9..dc120664d1e 100644\n--- a/bundle-uri.c\n+++ b/bundle-uri.c\n@@ -403,7 +403,7 @@ static int unbundle_from_file(struct repository *r, const char *file)\n \t\tconst char *branch_name;\n \t\tint has_old;\n \n-\t\tif (!skip_prefix(refname->string, \"refs/heads/\", &branch_name))\n+\t\tif (!skip_prefix(refname->string, \"refs/\", &branch_name))\n \t\t\tcontinue;\n \n \t\tstrbuf_setlen(&bundle_ref, bundle_prefix_len);\ndiff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh\nindex 3816ed5058d..33a7009e9a2 100755\n--- a/t/t5558-clone-bundle-uri.sh\n+++ b/t/t5558-clone-bundle-uri.sh\n@@ -58,7 +58,7 @@ test_expect_success 'create bundle' '\n test_expect_success 'clone with path bundle' '\n \tgit clone --bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from clone-path &&\n-\tgit -C clone-path rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-path rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -68,9 +68,9 @@ test_expect_success 'clone with bundle that has bad header' '\n \tgit clone --bundle-uri=\"clone-from/bad-header.bundle\" \\\n \t\tclone-from clone-bad-header 2>err &&\n \tcommit_b=$(git -C clone-from rev-parse B) &&\n-\ttest_grep \"trying to write ref '\\''refs/bundles/topic'\\'' with nonexistent object $commit_b\" err &&\n+\ttest_grep \"trying to write ref '\\''refs/bundles/heads/topic'\\'' with nonexistent object $commit_b\" err &&\n \tgit -C clone-bad-header for-each-ref --format=\"%(refname)\" >refs &&\n-\ttest_grep ! \"refs/bundles/\" refs\n+\ttest_grep ! \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone with bundle that has bad object' '\n@@ -78,8 +78,8 @@ test_expect_success 'clone with bundle that has bad object' '\n \tgit clone --bundle-uri=\"clone-from/bad-object.bundle\" \\\n \t\tclone-from clone-bad-object-no-fsck &&\n \tgit -C clone-bad-object-no-fsck for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/bad >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/bad >expect &&\n \ttest_cmp expect actual &&\n \n \t# Unbundle fails with fsckObjects set true, but clone can still proceed.\n@@ -87,14 +87,14 @@ test_expect_success 'clone with bundle that has bad object' '\n \t\tclone-from clone-bad-object-fsck 2>err &&\n \ttest_grep \"missingEmail\" err &&\n \tgit -C clone-bad-object-fsck for-each-ref --format=\"%(refname)\" >refs &&\n-\ttest_grep ! \"refs/bundles/\" refs\n+\ttest_grep ! \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone with path bundle and non-default hash' '\n \ttest_when_finished \"rm -rf clone-path-non-default-hash\" &&\n \tGIT_DEFAULT_HASH=sha256 git clone --bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from clone-path-non-default-hash &&\n-\tgit -C clone-path-non-default-hash rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-path-non-default-hash rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -102,7 +102,7 @@ test_expect_success 'clone with path bundle and non-default hash' '\n test_expect_success 'clone with file:// bundle' '\n \tgit clone --bundle-uri=\"file://$(pwd)/clone-from/B.bundle\" \\\n \t\tclone-from clone-file &&\n-\tgit -C clone-file rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-file rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -173,12 +173,12 @@ test_expect_success 'clone bundle list (file, no heuristic)' '\n \tgit -C clone-list-file cat-file --batch-check <oids &&\n \n \tgit -C clone-list-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -220,10 +220,10 @@ test_expect_success 'clone bundle list (file, all mode, some failures)' '\n \tgit -C clone-all-some cat-file --batch-check <oids &&\n \n \tgit -C clone-all-some for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -253,7 +253,7 @@ test_expect_success 'clone bundle list (file, all mode, all failures)' '\n \tgit -C clone-all-fail cat-file --batch-check <oids &&\n \n \tgit -C clone-all-fail for-each-ref --format=\"%(refname)\" >refs &&\n-\t! grep \"refs/bundles/\" refs\n+\t! grep \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone bundle list (file, any mode)' '\n@@ -282,9 +282,9 @@ test_expect_success 'clone bundle list (file, any mode)' '\n \tgit -C clone-any-file cat-file --batch-check <oids &&\n \n \tgit -C clone-any-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -313,7 +313,7 @@ test_expect_success 'clone bundle list (file, any mode, all failures)' '\n \tgit -C clone-any-fail cat-file --batch-check <oids &&\n \n \tgit -C clone-any-fail for-each-ref --format=\"%(refname)\" >refs &&\n-\t! grep \"refs/bundles/\" refs\n+\t! grep \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'negotiation: bundle with part of wanted commits' '\n@@ -322,10 +322,10 @@ test_expect_success 'negotiation: bundle with part of wanted commits' '\n \tgit clone --no-local --bundle-uri=\"clone-from/A.bundle\" \\\n \t\tclone-from nego-bundle-part &&\n \tgit -C nego-bundle-part for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/topic >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/topic >expect &&\n \ttest_cmp expect actual &&\n-\t# Ensure that refs/bundles/topic are sent as \"have\".\n+\t# Ensure that refs/bundles/heads/topic are sent as \"have\".\n \ttip=$(git -C clone-from rev-parse A) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n@@ -337,8 +337,8 @@ test_expect_success 'negotiation: bundle with all wanted commits' '\n \t\t--bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from nego-bundle-all &&\n \tgit -C nego-bundle-all for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/topic >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/topic >expect &&\n \ttest_cmp expect actual &&\n \t# We already have all needed commits so no \"want\" needed.\n \ttest_grep ! \"clone> want \" trace-packet.txt\n@@ -363,13 +363,13 @@ test_expect_success 'negotiation: bundle list (no heuristic)' '\n \t\tclone-from nego-bundle-list-no-heuristic &&\n \n \tgit -C nego-bundle-list-no-heuristic for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n-\ttip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/left) &&\n+\ttip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/heads/left) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n \n@@ -395,13 +395,13 @@ test_expect_success 'negotiation: bundle list (creationToken)' '\n \t\tclone-from nego-bundle-list-heuristic &&\n \n \tgit -C nego-bundle-list-heuristic for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n-\ttip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/left) &&\n+\ttip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/heads/left) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n \n@@ -428,10 +428,10 @@ test_expect_success 'negotiation: bundle list with all wanted commits' '\n \t\tclone-from nego-bundle-list-all &&\n \n \tgit -C nego-bundle-list-all for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n \t# We already have all needed commits so no \"want\" needed.\n@@ -465,7 +465,7 @@ test_expect_success 'clone HTTP bundle' '\n \n \tgit clone --bundle-uri=\"$HTTPD_URL/B.bundle\" \\\n \t\t\"$HTTPD_URL/smart/fetch.git\" clone-http &&\n-\tgit -C clone-http rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-http rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual &&\n \n@@ -476,7 +476,7 @@ test_expect_success 'clone HTTP bundle with non-default hash' '\n \ttest_when_finished \"rm -rf clone-http-non-default-hash\" &&\n \tGIT_DEFAULT_HASH=sha256 git clone --bundle-uri=\"$HTTPD_URL/B.bundle\" \\\n \t\t\"$HTTPD_URL/smart/fetch.git\" clone-http-non-default-hash &&\n-\tgit -C clone-http-non-default-hash rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-http-non-default-hash rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -553,12 +553,12 @@ test_expect_success 'clone bundle list (HTTP, any mode)' '\n \tgit -C clone-any-http cat-file --batch-check <oids &&\n \n \tgit -C clone-list-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -641,9 +641,9 @@ test_expect_success 'clone incomplete bundle list (http, creationToken)' '\n \ttest_cmp expect actual &&\n \n \t# We now have only one bundle ref.\n-\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -679,13 +679,13 @@ test_expect_success 'clone incomplete bundle list (http, creationToken)' '\n \ttest_cmp expect actual &&\n \n \t# We now have all bundle refs.\n-\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs\n '\n@@ -721,9 +721,9 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \ttest_cmp expect actual &&\n \n \t# only received base ref from bundle-1\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -749,10 +749,10 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \ttest_cmp expect actual &&\n \n \t# received left from bundle-2\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -795,12 +795,12 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \n \t# received merge ref from bundle-4, but right is missing\n \t# because we did not download bundle-3.\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -862,7 +862,7 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# All bundles failed to unbundle\n-\tgit -C download-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \ttest_must_be_empty refs &&\n \n \t# Case 2: middle bundle does not exist, only two bundles can unbundle\n@@ -909,10 +909,10 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# bundle-1 and bundle-3 could unbundle, but bundle-4 could not\n-\tgit -C download-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -961,11 +961,11 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# fake.bundle did not unbundle, but the others did.\n-\tgit -C download-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs\n '\n@@ -1083,15 +1083,15 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/lefter\n-\trefs/bundles/merge\n-\trefs/bundles/right\n-\trefs/bundles/righter\n-\trefs/bundles/top\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/lefter\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n+\trefs/bundles/heads/righter\n+\trefs/bundles/heads/top\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -1144,12 +1144,12 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -1204,13 +1204,13 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/lefter\n-\trefs/bundles/right\n-\trefs/bundles/righter\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/lefter\n+\trefs/bundles/heads/right\n+\trefs/bundles/heads/righter\n \tEOF\n \ttest_cmp expect refs\n '\n-- \ngitgitgadget\n\n"},{"id":"516798","messageId":"d9a114915a30281518d6e411ee01aefa670139ad.1745587067.git.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v4.git.git.1745587067.gitgitgadget@gmail.com","subject":"[PATCH v4 2/2] bundle-uri: add test for bundle-uri clones with tags","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-04-25T13:17:47Z","receivedAt":"2025-04-25T13:17:52Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"From: Scott Chacon <schacon@gmail.com>\n\nThe change to the bundle-uri unbundling refspec now includes tags, so this\nadds a very, very simple test to make sure that tags in a bundle are\nproperly added to the cloned repository and will be included in ref\nnegotiation with the subsequent fetch. ok, now it's right. christ.\n\nSigned-off-by: Scott Chacon <schacon@gmail.com>\n---\n t/t5558-clone-bundle-uri.sh | 30 ++++++++++++++++++++++++++++++\n 1 file changed, 30 insertions(+)\n\ndiff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh\nindex 33a7009e9a2..9b211a626bd 100755\n--- a/t/t5558-clone-bundle-uri.sh\n+++ b/t/t5558-clone-bundle-uri.sh\n@@ -107,6 +107,36 @@ test_expect_success 'clone with file:// bundle' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'create bundle with tags' '\n+\tgit init clone-from-tags &&\n+\t(\n+\t\tcd clone-from-tags &&\n+\t\tgit checkout -b base &&\n+\t\tgit checkout -b topic &&\n+\n+\t\ttest_commit A &&\n+\t\tgit tag tag-A &&\n+\t\tgit checkout -b base &&\n+\t\tgit branch -d topic &&\n+\t\ttest_commit B &&\n+\n+\t\tgit bundle create ALL.bundle --all &&\n+\t\tgit bundle verify ALL.bundle\n+\t)\n+'\n+\n+test_expect_success 'clone with tags bundle' '\n+\tgit clone --bundle-uri=\"clone-from-tags/ALL.bundle\" \\\n+\t\tclone-from-tags clone-tags-path &&\n+\n+\tgit -C clone-from-tags for-each-ref --format=\"%(refname:lstrip=1)\" \\\n+\t\t>expect &&\n+\tgit -C clone-tags-path for-each-ref --format=\"%(refname:lstrip=2)\" \\\n+\t\trefs/bundles >actual &&\n+\n+\ttest_cmp expect actual\n+'\n+\n # To get interesting tests for bundle lists, we need to construct a\n # somewhat-interesting commit history.\n #\n-- \ngitgitgadget\n"},{"id":"516799","messageId":"ce33a9ad-e931-4408-92ec-1a898e908c36@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v4.git.git.1745587067.gitgitgadget@gmail.com","subject":"Re: [PATCH v4 0/2] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2025-04-25T13:53:44Z","receivedAt":"2025-04-25T13:53:47Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Scott\n\nOn 25/04/2025 14:17, Scott Chacon via GitGitGadget wrote:\n> Updated the test with Taylor's patch.\n\nThanks for updating the test, unfortunately the documentation update \nmentioned in [1] to ensure the refspec in the documentation matches the \nchanges in this series seems to have been overlooked.\n\nBest Wishes\n\nPhillip\n\n[1] \nhttps://lore.kernel.org/git/56d8bd34-1301-40d6-8151-f85fb1d7560b@gmail.com/\n\n>> bundle-uri: copy all bundle references ino the refs/bundle space\n>> bundle-uri: update bundle clone tests with new refspec path\n> \n> Scott Chacon (2):\n>    bundle-uri: copy all bundle references ino the refs/bundle space\n>    bundle-uri: add test for bundle-uri clones with tags\n> \n>   bundle-uri.c                |   2 +-\n>   t/t5558-clone-bundle-uri.sh | 202 +++++++++++++++++++++---------------\n>   2 files changed, 117 insertions(+), 87 deletions(-)\n> \n> \n> base-commit: f65182a99e545d2f2bc22e6c1c2da192133b16a3\n> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1897%2Fschacon%2Fsc-more-bundle-refs-v4\n> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1897/schacon/sc-more-bundle-refs-v4\n> Pull-Request: https://github.com/git/git/pull/1897\n> \n> Range-diff vs v3:\n> \n>   1:  2ccbfdcc2dc = 1:  6957ee2fed2 bundle-uri: copy all bundle references ino the refs/bundle space\n>   2:  d148b14c390 ! 2:  d9a114915a3 bundle-uri: add test for bundle-uri clones with tags\n>       @@ Commit message\n>            bundle-uri: add test for bundle-uri clones with tags\n>        \n>            The change to the bundle-uri unbundling refspec now includes tags, so this\n>       -    adds a simple test to make sure that tags in a bundle are properly added to\n>       -    the cloned repository and will be included in ref negotiation with the\n>       -    subsequent fetch.\n>       +    adds a very, very simple test to make sure that tags in a bundle are\n>       +    properly added to the cloned repository and will be included in ref\n>       +    negotiation with the subsequent fetch. ok, now it's right. christ.\n>        \n>            Signed-off-by: Scott Chacon <schacon@gmail.com>\n>        \n>       @@ t/t5558-clone-bundle-uri.sh: test_expect_success 'clone with file:// bundle' '\n>        +test_expect_success 'clone with tags bundle' '\n>        +\tgit clone --bundle-uri=\"clone-from-tags/ALL.bundle\" \\\n>        +\t\tclone-from-tags clone-tags-path &&\n>       -+\tgit -C clone-tags-path for-each-ref --format=\"%(refname)\" >refs &&\n>       -+\tgrep \"refs/bundles/tags/\" refs >actual &&\n>       -+\tcat >expect <<-\\EOF &&\n>       -+\trefs/bundles/tags/A\n>       -+\trefs/bundles/tags/B\n>       -+\trefs/bundles/tags/tag-A\n>       -+\tEOF\n>       ++\n>       ++\tgit -C clone-from-tags for-each-ref --format=\"%(refname:lstrip=1)\" \\\n>       ++\t\t>expect &&\n>       ++\tgit -C clone-tags-path for-each-ref --format=\"%(refname:lstrip=2)\" \\\n>       ++\t\trefs/bundles >actual &&\n>       ++\n>        +\ttest_cmp expect actual\n>        +'\n>        +\n> \n\n"},{"id":"516816","messageId":"CAP2yMaKkYdoQRJ3tH_PNrDtmw5NGfsBe6DmCYs1wwZdkAkGQDQ@mail.gmail.com","threadId":"62999","inReplyTo":"d9a114915a30281518d6e411ee01aefa670139ad.1745587067.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v4 2/2] bundle-uri: add test for bundle-uri clones with tags","fromName":"Scott Chacon","fromEmail":"schacon@gmail.com","sentAt":"2025-04-25T16:32:04Z","receivedAt":"2025-04-25T16:32:17Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"Whoops. I'm seriously sorry for the coda on this updated commit\nmessage. I was testing out a different thing for something totally\nunrelated and was just adding random text to the end of the message\nthat made me laugh. I didn't mean to submit this as the message after\ncoming back to it after a few weeks. I promise this wasn't on purpose.\n(I'm not very good at Git)\n\nRelated to the code change though, there was a comment that the\nmessage didn't match the patch somehow, but I'm afraid I don't\nunderstand how. Other than the cheeky mistaken addendum, it seems to\nme that the message still describes the new tests, no?\n\nScott\n\n\nOn Fri, Apr 25, 2025 at 9:17 AM Scott Chacon via GitGitGadget\n<gitgitgadget@gmail.com> wrote:\n>\n> From: Scott Chacon <schacon@gmail.com>\n>\n> The change to the bundle-uri unbundling refspec now includes tags, so this\n> adds a very, very simple test to make sure that tags in a bundle are\n> properly added to the cloned repository and will be included in ref\n> negotiation with the subsequent fetch. ok, now it's right. christ.\n>\n> Signed-off-by: Scott Chacon <schacon@gmail.com>\n> ---\n>  t/t5558-clone-bundle-uri.sh | 30 ++++++++++++++++++++++++++++++\n>  1 file changed, 30 insertions(+)\n>\n> diff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh\n> index 33a7009e9a2..9b211a626bd 100755\n> --- a/t/t5558-clone-bundle-uri.sh\n> +++ b/t/t5558-clone-bundle-uri.sh\n> @@ -107,6 +107,36 @@ test_expect_success 'clone with file:// bundle' '\n>         test_cmp expect actual\n>  '\n>\n> +test_expect_success 'create bundle with tags' '\n> +       git init clone-from-tags &&\n> +       (\n> +               cd clone-from-tags &&\n> +               git checkout -b base &&\n> +               git checkout -b topic &&\n> +\n> +               test_commit A &&\n> +               git tag tag-A &&\n> +               git checkout -b base &&\n> +               git branch -d topic &&\n> +               test_commit B &&\n> +\n> +               git bundle create ALL.bundle --all &&\n> +               git bundle verify ALL.bundle\n> +       )\n> +'\n> +\n> +test_expect_success 'clone with tags bundle' '\n> +       git clone --bundle-uri=\"clone-from-tags/ALL.bundle\" \\\n> +               clone-from-tags clone-tags-path &&\n> +\n> +       git -C clone-from-tags for-each-ref --format=\"%(refname:lstrip=1)\" \\\n> +               >expect &&\n> +       git -C clone-tags-path for-each-ref --format=\"%(refname:lstrip=2)\" \\\n> +               refs/bundles >actual &&\n> +\n> +       test_cmp expect actual\n> +'\n> +\n>  # To get interesting tests for bundle lists, we need to construct a\n>  # somewhat-interesting commit history.\n>  #\n> --\n> gitgitgadget\n"},{"id":"516818","messageId":"xmqq34dwuqrj.fsf@gitster.g","threadId":"62999","inReplyTo":"ce33a9ad-e931-4408-92ec-1a898e908c36@gmail.com","subject":"Re: [PATCH v4 0/2] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-04-25T16:53:20Z","receivedAt":"2025-04-25T16:53:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> Hi Scott\n>\n> On 25/04/2025 14:17, Scott Chacon via GitGitGadget wrote:\n>> Updated the test with Taylor's patch.\n>\n> Thanks for updating the test, unfortunately the documentation update\n> mentioned in [1] to ensure the refspec in the documentation matches\n> the changes in this series seems to have been overlooked.\n\nThanks for carefully keeping track of the progress of the topic.\n\nWill replace what I've queued with this iteration.\n\nThanks, both.\n"},{"id":"516829","messageId":"pull.1897.v5.git.git.1745607965.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v4.git.git.1745587067.gitgitgadget@gmail.com","subject":"[PATCH v5 0/2] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-04-25T19:06:03Z","receivedAt":"2025-04-25T19:06:08Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"Updated commit message to remove the swearing. 😂\n\n> bundle-uri: copy all bundle references ino the refs/bundle space\n> bundle-uri: update bundle clone tests with new refspec path\n\nScott Chacon (2):\n  bundle-uri: copy all bundle references ino the refs/bundle space\n  bundle-uri: add test for bundle-uri clones with tags\n\n bundle-uri.c                |   2 +-\n t/t5558-clone-bundle-uri.sh | 202 +++++++++++++++++++++---------------\n 2 files changed, 117 insertions(+), 87 deletions(-)\n\n\nbase-commit: f65182a99e545d2f2bc22e6c1c2da192133b16a3\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1897%2Fschacon%2Fsc-more-bundle-refs-v5\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1897/schacon/sc-more-bundle-refs-v5\nPull-Request: https://github.com/git/git/pull/1897\n\nRange-diff vs v4:\n\n 1:  6957ee2fed2 = 1:  6957ee2fed2 bundle-uri: copy all bundle references ino the refs/bundle space\n 2:  d9a114915a3 ! 2:  ec5d629f32b bundle-uri: add test for bundle-uri clones with tags\n     @@ Commit message\n          The change to the bundle-uri unbundling refspec now includes tags, so this\n          adds a very, very simple test to make sure that tags in a bundle are\n          properly added to the cloned repository and will be included in ref\n     -    negotiation with the subsequent fetch. ok, now it's right. christ.\n     +    negotiation with the subsequent fetch.\n      \n          Signed-off-by: Scott Chacon <schacon@gmail.com>\n      \n\n-- \ngitgitgadget\n"},{"id":"516830","messageId":"ec5d629f32befd4243e3a6a112cb818f211f147c.1745607965.git.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v5.git.git.1745607965.gitgitgadget@gmail.com","subject":"[PATCH v5 2/2] bundle-uri: add test for bundle-uri clones with tags","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-04-25T19:06:05Z","receivedAt":"2025-04-25T19:06:09Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"From: Scott Chacon <schacon@gmail.com>\n\nThe change to the bundle-uri unbundling refspec now includes tags, so this\nadds a very, very simple test to make sure that tags in a bundle are\nproperly added to the cloned repository and will be included in ref\nnegotiation with the subsequent fetch.\n\nSigned-off-by: Scott Chacon <schacon@gmail.com>\n---\n t/t5558-clone-bundle-uri.sh | 30 ++++++++++++++++++++++++++++++\n 1 file changed, 30 insertions(+)\n\ndiff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh\nindex 33a7009e9a2..9b211a626bd 100755\n--- a/t/t5558-clone-bundle-uri.sh\n+++ b/t/t5558-clone-bundle-uri.sh\n@@ -107,6 +107,36 @@ test_expect_success 'clone with file:// bundle' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'create bundle with tags' '\n+\tgit init clone-from-tags &&\n+\t(\n+\t\tcd clone-from-tags &&\n+\t\tgit checkout -b base &&\n+\t\tgit checkout -b topic &&\n+\n+\t\ttest_commit A &&\n+\t\tgit tag tag-A &&\n+\t\tgit checkout -b base &&\n+\t\tgit branch -d topic &&\n+\t\ttest_commit B &&\n+\n+\t\tgit bundle create ALL.bundle --all &&\n+\t\tgit bundle verify ALL.bundle\n+\t)\n+'\n+\n+test_expect_success 'clone with tags bundle' '\n+\tgit clone --bundle-uri=\"clone-from-tags/ALL.bundle\" \\\n+\t\tclone-from-tags clone-tags-path &&\n+\n+\tgit -C clone-from-tags for-each-ref --format=\"%(refname:lstrip=1)\" \\\n+\t\t>expect &&\n+\tgit -C clone-tags-path for-each-ref --format=\"%(refname:lstrip=2)\" \\\n+\t\trefs/bundles >actual &&\n+\n+\ttest_cmp expect actual\n+'\n+\n # To get interesting tests for bundle lists, we need to construct a\n # somewhat-interesting commit history.\n #\n-- \ngitgitgadget\n"},{"id":"516831","messageId":"6957ee2fed2f04ad7cd02e5785eb89a1a55f81f5.1745607965.git.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v5.git.git.1745607965.gitgitgadget@gmail.com","subject":"[PATCH v5 1/2] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-04-25T19:06:04Z","receivedAt":"2025-04-25T19:06:09Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"From: Scott Chacon <schacon@gmail.com>\n\nWhen downloading bundles via the bundle-uri functionality, we only copy the\nreferences from refs/heads into the refs/bundle space. I'm not sure why this\nrefspec is hardcoded to be so limited, but it makes the ref negotiation on\nthe subsequent fetch suboptimal, since it won't use objects that are\nreferenced outside of the current heads of the bundled repository.\n\nThis change to copy everything in refs/ in the bundle to refs/bundles/\nsignificantly helps the subsequent fetch, since nearly all the references\nare now included in the negotiation.\n\nThe update to the bundle-uri unbundling refspec puts all the heads from a\nbundle file into refs/bundle/heads instead of directly into refs/bundle/ so\nthe tests also need to be updated to look in the new heirarchy.\n\nSigned-off-by: Scott Chacon <schacon@gmail.com>\n---\n bundle-uri.c                |   2 +-\n t/t5558-clone-bundle-uri.sh | 172 ++++++++++++++++++------------------\n 2 files changed, 87 insertions(+), 87 deletions(-)\n\ndiff --git a/bundle-uri.c b/bundle-uri.c\nindex 96d2ba726d9..dc120664d1e 100644\n--- a/bundle-uri.c\n+++ b/bundle-uri.c\n@@ -403,7 +403,7 @@ static int unbundle_from_file(struct repository *r, const char *file)\n \t\tconst char *branch_name;\n \t\tint has_old;\n \n-\t\tif (!skip_prefix(refname->string, \"refs/heads/\", &branch_name))\n+\t\tif (!skip_prefix(refname->string, \"refs/\", &branch_name))\n \t\t\tcontinue;\n \n \t\tstrbuf_setlen(&bundle_ref, bundle_prefix_len);\ndiff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh\nindex 3816ed5058d..33a7009e9a2 100755\n--- a/t/t5558-clone-bundle-uri.sh\n+++ b/t/t5558-clone-bundle-uri.sh\n@@ -58,7 +58,7 @@ test_expect_success 'create bundle' '\n test_expect_success 'clone with path bundle' '\n \tgit clone --bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from clone-path &&\n-\tgit -C clone-path rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-path rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -68,9 +68,9 @@ test_expect_success 'clone with bundle that has bad header' '\n \tgit clone --bundle-uri=\"clone-from/bad-header.bundle\" \\\n \t\tclone-from clone-bad-header 2>err &&\n \tcommit_b=$(git -C clone-from rev-parse B) &&\n-\ttest_grep \"trying to write ref '\\''refs/bundles/topic'\\'' with nonexistent object $commit_b\" err &&\n+\ttest_grep \"trying to write ref '\\''refs/bundles/heads/topic'\\'' with nonexistent object $commit_b\" err &&\n \tgit -C clone-bad-header for-each-ref --format=\"%(refname)\" >refs &&\n-\ttest_grep ! \"refs/bundles/\" refs\n+\ttest_grep ! \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone with bundle that has bad object' '\n@@ -78,8 +78,8 @@ test_expect_success 'clone with bundle that has bad object' '\n \tgit clone --bundle-uri=\"clone-from/bad-object.bundle\" \\\n \t\tclone-from clone-bad-object-no-fsck &&\n \tgit -C clone-bad-object-no-fsck for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/bad >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/bad >expect &&\n \ttest_cmp expect actual &&\n \n \t# Unbundle fails with fsckObjects set true, but clone can still proceed.\n@@ -87,14 +87,14 @@ test_expect_success 'clone with bundle that has bad object' '\n \t\tclone-from clone-bad-object-fsck 2>err &&\n \ttest_grep \"missingEmail\" err &&\n \tgit -C clone-bad-object-fsck for-each-ref --format=\"%(refname)\" >refs &&\n-\ttest_grep ! \"refs/bundles/\" refs\n+\ttest_grep ! \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone with path bundle and non-default hash' '\n \ttest_when_finished \"rm -rf clone-path-non-default-hash\" &&\n \tGIT_DEFAULT_HASH=sha256 git clone --bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from clone-path-non-default-hash &&\n-\tgit -C clone-path-non-default-hash rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-path-non-default-hash rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -102,7 +102,7 @@ test_expect_success 'clone with path bundle and non-default hash' '\n test_expect_success 'clone with file:// bundle' '\n \tgit clone --bundle-uri=\"file://$(pwd)/clone-from/B.bundle\" \\\n \t\tclone-from clone-file &&\n-\tgit -C clone-file rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-file rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -173,12 +173,12 @@ test_expect_success 'clone bundle list (file, no heuristic)' '\n \tgit -C clone-list-file cat-file --batch-check <oids &&\n \n \tgit -C clone-list-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -220,10 +220,10 @@ test_expect_success 'clone bundle list (file, all mode, some failures)' '\n \tgit -C clone-all-some cat-file --batch-check <oids &&\n \n \tgit -C clone-all-some for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -253,7 +253,7 @@ test_expect_success 'clone bundle list (file, all mode, all failures)' '\n \tgit -C clone-all-fail cat-file --batch-check <oids &&\n \n \tgit -C clone-all-fail for-each-ref --format=\"%(refname)\" >refs &&\n-\t! grep \"refs/bundles/\" refs\n+\t! grep \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone bundle list (file, any mode)' '\n@@ -282,9 +282,9 @@ test_expect_success 'clone bundle list (file, any mode)' '\n \tgit -C clone-any-file cat-file --batch-check <oids &&\n \n \tgit -C clone-any-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -313,7 +313,7 @@ test_expect_success 'clone bundle list (file, any mode, all failures)' '\n \tgit -C clone-any-fail cat-file --batch-check <oids &&\n \n \tgit -C clone-any-fail for-each-ref --format=\"%(refname)\" >refs &&\n-\t! grep \"refs/bundles/\" refs\n+\t! grep \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'negotiation: bundle with part of wanted commits' '\n@@ -322,10 +322,10 @@ test_expect_success 'negotiation: bundle with part of wanted commits' '\n \tgit clone --no-local --bundle-uri=\"clone-from/A.bundle\" \\\n \t\tclone-from nego-bundle-part &&\n \tgit -C nego-bundle-part for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/topic >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/topic >expect &&\n \ttest_cmp expect actual &&\n-\t# Ensure that refs/bundles/topic are sent as \"have\".\n+\t# Ensure that refs/bundles/heads/topic are sent as \"have\".\n \ttip=$(git -C clone-from rev-parse A) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n@@ -337,8 +337,8 @@ test_expect_success 'negotiation: bundle with all wanted commits' '\n \t\t--bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from nego-bundle-all &&\n \tgit -C nego-bundle-all for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/topic >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/topic >expect &&\n \ttest_cmp expect actual &&\n \t# We already have all needed commits so no \"want\" needed.\n \ttest_grep ! \"clone> want \" trace-packet.txt\n@@ -363,13 +363,13 @@ test_expect_success 'negotiation: bundle list (no heuristic)' '\n \t\tclone-from nego-bundle-list-no-heuristic &&\n \n \tgit -C nego-bundle-list-no-heuristic for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n-\ttip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/left) &&\n+\ttip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/heads/left) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n \n@@ -395,13 +395,13 @@ test_expect_success 'negotiation: bundle list (creationToken)' '\n \t\tclone-from nego-bundle-list-heuristic &&\n \n \tgit -C nego-bundle-list-heuristic for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n-\ttip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/left) &&\n+\ttip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/heads/left) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n \n@@ -428,10 +428,10 @@ test_expect_success 'negotiation: bundle list with all wanted commits' '\n \t\tclone-from nego-bundle-list-all &&\n \n \tgit -C nego-bundle-list-all for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n \t# We already have all needed commits so no \"want\" needed.\n@@ -465,7 +465,7 @@ test_expect_success 'clone HTTP bundle' '\n \n \tgit clone --bundle-uri=\"$HTTPD_URL/B.bundle\" \\\n \t\t\"$HTTPD_URL/smart/fetch.git\" clone-http &&\n-\tgit -C clone-http rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-http rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual &&\n \n@@ -476,7 +476,7 @@ test_expect_success 'clone HTTP bundle with non-default hash' '\n \ttest_when_finished \"rm -rf clone-http-non-default-hash\" &&\n \tGIT_DEFAULT_HASH=sha256 git clone --bundle-uri=\"$HTTPD_URL/B.bundle\" \\\n \t\t\"$HTTPD_URL/smart/fetch.git\" clone-http-non-default-hash &&\n-\tgit -C clone-http-non-default-hash rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-http-non-default-hash rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -553,12 +553,12 @@ test_expect_success 'clone bundle list (HTTP, any mode)' '\n \tgit -C clone-any-http cat-file --batch-check <oids &&\n \n \tgit -C clone-list-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -641,9 +641,9 @@ test_expect_success 'clone incomplete bundle list (http, creationToken)' '\n \ttest_cmp expect actual &&\n \n \t# We now have only one bundle ref.\n-\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -679,13 +679,13 @@ test_expect_success 'clone incomplete bundle list (http, creationToken)' '\n \ttest_cmp expect actual &&\n \n \t# We now have all bundle refs.\n-\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs\n '\n@@ -721,9 +721,9 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \ttest_cmp expect actual &&\n \n \t# only received base ref from bundle-1\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -749,10 +749,10 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \ttest_cmp expect actual &&\n \n \t# received left from bundle-2\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -795,12 +795,12 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \n \t# received merge ref from bundle-4, but right is missing\n \t# because we did not download bundle-3.\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -862,7 +862,7 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# All bundles failed to unbundle\n-\tgit -C download-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \ttest_must_be_empty refs &&\n \n \t# Case 2: middle bundle does not exist, only two bundles can unbundle\n@@ -909,10 +909,10 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# bundle-1 and bundle-3 could unbundle, but bundle-4 could not\n-\tgit -C download-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -961,11 +961,11 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# fake.bundle did not unbundle, but the others did.\n-\tgit -C download-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs\n '\n@@ -1083,15 +1083,15 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/lefter\n-\trefs/bundles/merge\n-\trefs/bundles/right\n-\trefs/bundles/righter\n-\trefs/bundles/top\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/lefter\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n+\trefs/bundles/heads/righter\n+\trefs/bundles/heads/top\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -1144,12 +1144,12 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -1204,13 +1204,13 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/lefter\n-\trefs/bundles/right\n-\trefs/bundles/righter\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/lefter\n+\trefs/bundles/heads/right\n+\trefs/bundles/heads/righter\n \tEOF\n \ttest_cmp expect refs\n '\n-- \ngitgitgadget\n\n"},{"id":"516833","messageId":"pull.1897.v6.git.git.1745609278.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v5.git.git.1745607965.gitgitgadget@gmail.com","subject":"[PATCH v6 0/2] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-04-25T19:27:56Z","receivedAt":"2025-04-25T19:28:02Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"Edit the documentation to update the refspec and remove the untrue statement\nthat it can be configured.\n\n> bundle-uri: copy all bundle references ino the refs/bundle space\n> bundle-uri: update bundle clone tests with new refspec path\n\nScott Chacon (2):\n  bundle-uri: copy all bundle references ino the refs/bundle space\n  bundle-uri: add test for bundle-uri clones with tags\n\n Documentation/technical/bundle-uri.adoc |  14 +-\n bundle-uri.c                            |   2 +-\n t/t5558-clone-bundle-uri.sh             | 202 ++++++++++++++----------\n 3 files changed, 124 insertions(+), 94 deletions(-)\n\n\nbase-commit: f65182a99e545d2f2bc22e6c1c2da192133b16a3\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1897%2Fschacon%2Fsc-more-bundle-refs-v6\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1897/schacon/sc-more-bundle-refs-v6\nPull-Request: https://github.com/git/git/pull/1897\n\nRange-diff vs v5:\n\n 1:  6957ee2fed2 ! 1:  d6ec5c87b43 bundle-uri: copy all bundle references ino the refs/bundle space\n     @@ Commit message\n      \n          Signed-off-by: Scott Chacon <schacon@gmail.com>\n      \n     + ## Documentation/technical/bundle-uri.adoc ##\n     +@@ Documentation/technical/bundle-uri.adoc: will interact with bundle URIs according to the following flow:\n     +    are present in the client repository. If some are missing, then the\n     +    client delays unbundling until other bundles have been unbundled,\n     +    making those OIDs present. When all required OIDs are present, the\n     +-   client unbundles that data using a refspec. The default refspec is\n     +-   `+refs/heads/*:refs/bundles/*`, but this can be configured. These refs\n     +-   are stored so that later `git fetch` negotiations can communicate each\n     +-   bundled ref as a `have`, reducing the size of the fetch over the Git\n     +-   protocol. To allow pruning refs from this ref namespace, Git may\n     +-   introduce a numbered namespace (such as `refs/bundles/<i>/*`) such that\n     +-   stale bundle refs can be deleted.\n     ++   client unbundles that data using a refspec. The refspec used is\n     ++   `+refs/*:refs/bundles/*`. These refs are stored so that later \n     ++   `git fetch` negotiations can communicate each bundled ref as a `have`,\n     ++   reducing the size of the fetch over the Git protocol. To allow pruning\n     ++   refs from this ref namespace, Git may introduce a numbered namespace\n     ++   (such as `refs/bundles/<i>/*`) such that stale bundle refs can be\n     ++   deleted.\n     + \n     + 3. If the file is instead a bundle list, then the client inspects the\n     +    `bundle.mode` to see if the list is of the `all` or `any` form.\n     +\n       ## bundle-uri.c ##\n      @@ bundle-uri.c: static int unbundle_from_file(struct repository *r, const char *file)\n       \t\tconst char *branch_name;\n 2:  ec5d629f32b = 2:  825d2b01eae bundle-uri: add test for bundle-uri clones with tags\n\n-- \ngitgitgadget\n"},{"id":"516835","messageId":"d6ec5c87b433e0b0a5d1e799fe7ac937a61b7d4c.1745609278.git.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v6.git.git.1745609278.gitgitgadget@gmail.com","subject":"[PATCH v6 1/2] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-04-25T19:27:57Z","receivedAt":"2025-04-25T19:28:03Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"From: Scott Chacon <schacon@gmail.com>\n\nWhen downloading bundles via the bundle-uri functionality, we only copy the\nreferences from refs/heads into the refs/bundle space. I'm not sure why this\nrefspec is hardcoded to be so limited, but it makes the ref negotiation on\nthe subsequent fetch suboptimal, since it won't use objects that are\nreferenced outside of the current heads of the bundled repository.\n\nThis change to copy everything in refs/ in the bundle to refs/bundles/\nsignificantly helps the subsequent fetch, since nearly all the references\nare now included in the negotiation.\n\nThe update to the bundle-uri unbundling refspec puts all the heads from a\nbundle file into refs/bundle/heads instead of directly into refs/bundle/ so\nthe tests also need to be updated to look in the new heirarchy.\n\nSigned-off-by: Scott Chacon <schacon@gmail.com>\n---\n Documentation/technical/bundle-uri.adoc |  14 +-\n bundle-uri.c                            |   2 +-\n t/t5558-clone-bundle-uri.sh             | 172 ++++++++++++------------\n 3 files changed, 94 insertions(+), 94 deletions(-)\n\ndiff --git a/Documentation/technical/bundle-uri.adoc b/Documentation/technical/bundle-uri.adoc\nindex 91d3a13e327..f2551e71177 100644\n--- a/Documentation/technical/bundle-uri.adoc\n+++ b/Documentation/technical/bundle-uri.adoc\n@@ -232,13 +232,13 @@ will interact with bundle URIs according to the following flow:\n    are present in the client repository. If some are missing, then the\n    client delays unbundling until other bundles have been unbundled,\n    making those OIDs present. When all required OIDs are present, the\n-   client unbundles that data using a refspec. The default refspec is\n-   `+refs/heads/*:refs/bundles/*`, but this can be configured. These refs\n-   are stored so that later `git fetch` negotiations can communicate each\n-   bundled ref as a `have`, reducing the size of the fetch over the Git\n-   protocol. To allow pruning refs from this ref namespace, Git may\n-   introduce a numbered namespace (such as `refs/bundles/<i>/*`) such that\n-   stale bundle refs can be deleted.\n+   client unbundles that data using a refspec. The refspec used is\n+   `+refs/*:refs/bundles/*`. These refs are stored so that later \n+   `git fetch` negotiations can communicate each bundled ref as a `have`,\n+   reducing the size of the fetch over the Git protocol. To allow pruning\n+   refs from this ref namespace, Git may introduce a numbered namespace\n+   (such as `refs/bundles/<i>/*`) such that stale bundle refs can be\n+   deleted.\n \n 3. If the file is instead a bundle list, then the client inspects the\n    `bundle.mode` to see if the list is of the `all` or `any` form.\ndiff --git a/bundle-uri.c b/bundle-uri.c\nindex 96d2ba726d9..dc120664d1e 100644\n--- a/bundle-uri.c\n+++ b/bundle-uri.c\n@@ -403,7 +403,7 @@ static int unbundle_from_file(struct repository *r, const char *file)\n \t\tconst char *branch_name;\n \t\tint has_old;\n \n-\t\tif (!skip_prefix(refname->string, \"refs/heads/\", &branch_name))\n+\t\tif (!skip_prefix(refname->string, \"refs/\", &branch_name))\n \t\t\tcontinue;\n \n \t\tstrbuf_setlen(&bundle_ref, bundle_prefix_len);\ndiff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh\nindex 3816ed5058d..33a7009e9a2 100755\n--- a/t/t5558-clone-bundle-uri.sh\n+++ b/t/t5558-clone-bundle-uri.sh\n@@ -58,7 +58,7 @@ test_expect_success 'create bundle' '\n test_expect_success 'clone with path bundle' '\n \tgit clone --bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from clone-path &&\n-\tgit -C clone-path rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-path rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -68,9 +68,9 @@ test_expect_success 'clone with bundle that has bad header' '\n \tgit clone --bundle-uri=\"clone-from/bad-header.bundle\" \\\n \t\tclone-from clone-bad-header 2>err &&\n \tcommit_b=$(git -C clone-from rev-parse B) &&\n-\ttest_grep \"trying to write ref '\\''refs/bundles/topic'\\'' with nonexistent object $commit_b\" err &&\n+\ttest_grep \"trying to write ref '\\''refs/bundles/heads/topic'\\'' with nonexistent object $commit_b\" err &&\n \tgit -C clone-bad-header for-each-ref --format=\"%(refname)\" >refs &&\n-\ttest_grep ! \"refs/bundles/\" refs\n+\ttest_grep ! \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone with bundle that has bad object' '\n@@ -78,8 +78,8 @@ test_expect_success 'clone with bundle that has bad object' '\n \tgit clone --bundle-uri=\"clone-from/bad-object.bundle\" \\\n \t\tclone-from clone-bad-object-no-fsck &&\n \tgit -C clone-bad-object-no-fsck for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/bad >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/bad >expect &&\n \ttest_cmp expect actual &&\n \n \t# Unbundle fails with fsckObjects set true, but clone can still proceed.\n@@ -87,14 +87,14 @@ test_expect_success 'clone with bundle that has bad object' '\n \t\tclone-from clone-bad-object-fsck 2>err &&\n \ttest_grep \"missingEmail\" err &&\n \tgit -C clone-bad-object-fsck for-each-ref --format=\"%(refname)\" >refs &&\n-\ttest_grep ! \"refs/bundles/\" refs\n+\ttest_grep ! \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone with path bundle and non-default hash' '\n \ttest_when_finished \"rm -rf clone-path-non-default-hash\" &&\n \tGIT_DEFAULT_HASH=sha256 git clone --bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from clone-path-non-default-hash &&\n-\tgit -C clone-path-non-default-hash rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-path-non-default-hash rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -102,7 +102,7 @@ test_expect_success 'clone with path bundle and non-default hash' '\n test_expect_success 'clone with file:// bundle' '\n \tgit clone --bundle-uri=\"file://$(pwd)/clone-from/B.bundle\" \\\n \t\tclone-from clone-file &&\n-\tgit -C clone-file rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-file rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -173,12 +173,12 @@ test_expect_success 'clone bundle list (file, no heuristic)' '\n \tgit -C clone-list-file cat-file --batch-check <oids &&\n \n \tgit -C clone-list-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -220,10 +220,10 @@ test_expect_success 'clone bundle list (file, all mode, some failures)' '\n \tgit -C clone-all-some cat-file --batch-check <oids &&\n \n \tgit -C clone-all-some for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -253,7 +253,7 @@ test_expect_success 'clone bundle list (file, all mode, all failures)' '\n \tgit -C clone-all-fail cat-file --batch-check <oids &&\n \n \tgit -C clone-all-fail for-each-ref --format=\"%(refname)\" >refs &&\n-\t! grep \"refs/bundles/\" refs\n+\t! grep \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone bundle list (file, any mode)' '\n@@ -282,9 +282,9 @@ test_expect_success 'clone bundle list (file, any mode)' '\n \tgit -C clone-any-file cat-file --batch-check <oids &&\n \n \tgit -C clone-any-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -313,7 +313,7 @@ test_expect_success 'clone bundle list (file, any mode, all failures)' '\n \tgit -C clone-any-fail cat-file --batch-check <oids &&\n \n \tgit -C clone-any-fail for-each-ref --format=\"%(refname)\" >refs &&\n-\t! grep \"refs/bundles/\" refs\n+\t! grep \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'negotiation: bundle with part of wanted commits' '\n@@ -322,10 +322,10 @@ test_expect_success 'negotiation: bundle with part of wanted commits' '\n \tgit clone --no-local --bundle-uri=\"clone-from/A.bundle\" \\\n \t\tclone-from nego-bundle-part &&\n \tgit -C nego-bundle-part for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/topic >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/topic >expect &&\n \ttest_cmp expect actual &&\n-\t# Ensure that refs/bundles/topic are sent as \"have\".\n+\t# Ensure that refs/bundles/heads/topic are sent as \"have\".\n \ttip=$(git -C clone-from rev-parse A) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n@@ -337,8 +337,8 @@ test_expect_success 'negotiation: bundle with all wanted commits' '\n \t\t--bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from nego-bundle-all &&\n \tgit -C nego-bundle-all for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/topic >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/topic >expect &&\n \ttest_cmp expect actual &&\n \t# We already have all needed commits so no \"want\" needed.\n \ttest_grep ! \"clone> want \" trace-packet.txt\n@@ -363,13 +363,13 @@ test_expect_success 'negotiation: bundle list (no heuristic)' '\n \t\tclone-from nego-bundle-list-no-heuristic &&\n \n \tgit -C nego-bundle-list-no-heuristic for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n-\ttip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/left) &&\n+\ttip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/heads/left) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n \n@@ -395,13 +395,13 @@ test_expect_success 'negotiation: bundle list (creationToken)' '\n \t\tclone-from nego-bundle-list-heuristic &&\n \n \tgit -C nego-bundle-list-heuristic for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n-\ttip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/left) &&\n+\ttip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/heads/left) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n \n@@ -428,10 +428,10 @@ test_expect_success 'negotiation: bundle list with all wanted commits' '\n \t\tclone-from nego-bundle-list-all &&\n \n \tgit -C nego-bundle-list-all for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n \t# We already have all needed commits so no \"want\" needed.\n@@ -465,7 +465,7 @@ test_expect_success 'clone HTTP bundle' '\n \n \tgit clone --bundle-uri=\"$HTTPD_URL/B.bundle\" \\\n \t\t\"$HTTPD_URL/smart/fetch.git\" clone-http &&\n-\tgit -C clone-http rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-http rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual &&\n \n@@ -476,7 +476,7 @@ test_expect_success 'clone HTTP bundle with non-default hash' '\n \ttest_when_finished \"rm -rf clone-http-non-default-hash\" &&\n \tGIT_DEFAULT_HASH=sha256 git clone --bundle-uri=\"$HTTPD_URL/B.bundle\" \\\n \t\t\"$HTTPD_URL/smart/fetch.git\" clone-http-non-default-hash &&\n-\tgit -C clone-http-non-default-hash rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-http-non-default-hash rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -553,12 +553,12 @@ test_expect_success 'clone bundle list (HTTP, any mode)' '\n \tgit -C clone-any-http cat-file --batch-check <oids &&\n \n \tgit -C clone-list-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -641,9 +641,9 @@ test_expect_success 'clone incomplete bundle list (http, creationToken)' '\n \ttest_cmp expect actual &&\n \n \t# We now have only one bundle ref.\n-\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -679,13 +679,13 @@ test_expect_success 'clone incomplete bundle list (http, creationToken)' '\n \ttest_cmp expect actual &&\n \n \t# We now have all bundle refs.\n-\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs\n '\n@@ -721,9 +721,9 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \ttest_cmp expect actual &&\n \n \t# only received base ref from bundle-1\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -749,10 +749,10 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \ttest_cmp expect actual &&\n \n \t# received left from bundle-2\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -795,12 +795,12 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \n \t# received merge ref from bundle-4, but right is missing\n \t# because we did not download bundle-3.\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -862,7 +862,7 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# All bundles failed to unbundle\n-\tgit -C download-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \ttest_must_be_empty refs &&\n \n \t# Case 2: middle bundle does not exist, only two bundles can unbundle\n@@ -909,10 +909,10 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# bundle-1 and bundle-3 could unbundle, but bundle-4 could not\n-\tgit -C download-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -961,11 +961,11 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# fake.bundle did not unbundle, but the others did.\n-\tgit -C download-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs\n '\n@@ -1083,15 +1083,15 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/lefter\n-\trefs/bundles/merge\n-\trefs/bundles/right\n-\trefs/bundles/righter\n-\trefs/bundles/top\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/lefter\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n+\trefs/bundles/heads/righter\n+\trefs/bundles/heads/top\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -1144,12 +1144,12 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -1204,13 +1204,13 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/lefter\n-\trefs/bundles/right\n-\trefs/bundles/righter\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/lefter\n+\trefs/bundles/heads/right\n+\trefs/bundles/heads/righter\n \tEOF\n \ttest_cmp expect refs\n '\n-- \ngitgitgadget\n\n"},{"id":"516834","messageId":"825d2b01eaec9d75bdd0b3210816f0a9951a2503.1745609278.git.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v6.git.git.1745609278.gitgitgadget@gmail.com","subject":"[PATCH v6 2/2] bundle-uri: add test for bundle-uri clones with tags","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-04-25T19:27:58Z","receivedAt":"2025-04-25T19:28:04Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"From: Scott Chacon <schacon@gmail.com>\n\nThe change to the bundle-uri unbundling refspec now includes tags, so this\nadds a very, very simple test to make sure that tags in a bundle are\nproperly added to the cloned repository and will be included in ref\nnegotiation with the subsequent fetch.\n\nSigned-off-by: Scott Chacon <schacon@gmail.com>\n---\n t/t5558-clone-bundle-uri.sh | 30 ++++++++++++++++++++++++++++++\n 1 file changed, 30 insertions(+)\n\ndiff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh\nindex 33a7009e9a2..9b211a626bd 100755\n--- a/t/t5558-clone-bundle-uri.sh\n+++ b/t/t5558-clone-bundle-uri.sh\n@@ -107,6 +107,36 @@ test_expect_success 'clone with file:// bundle' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'create bundle with tags' '\n+\tgit init clone-from-tags &&\n+\t(\n+\t\tcd clone-from-tags &&\n+\t\tgit checkout -b base &&\n+\t\tgit checkout -b topic &&\n+\n+\t\ttest_commit A &&\n+\t\tgit tag tag-A &&\n+\t\tgit checkout -b base &&\n+\t\tgit branch -d topic &&\n+\t\ttest_commit B &&\n+\n+\t\tgit bundle create ALL.bundle --all &&\n+\t\tgit bundle verify ALL.bundle\n+\t)\n+'\n+\n+test_expect_success 'clone with tags bundle' '\n+\tgit clone --bundle-uri=\"clone-from-tags/ALL.bundle\" \\\n+\t\tclone-from-tags clone-tags-path &&\n+\n+\tgit -C clone-from-tags for-each-ref --format=\"%(refname:lstrip=1)\" \\\n+\t\t>expect &&\n+\tgit -C clone-tags-path for-each-ref --format=\"%(refname:lstrip=2)\" \\\n+\t\trefs/bundles >actual &&\n+\n+\ttest_cmp expect actual\n+'\n+\n # To get interesting tests for bundle lists, we need to construct a\n # somewhat-interesting commit history.\n #\n-- \ngitgitgadget\n"},{"id":"516836","messageId":"pull.1897.v7.git.git.1745609589.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v6.git.git.1745609278.gitgitgadget@gmail.com","subject":"[PATCH v7 0/2] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-04-25T19:33:07Z","receivedAt":"2025-04-25T19:33:12Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"Sorry everyone for the noise. There was a whitespace issue the tests\ncomplained about, hopefully this fixes it.\n\n> bundle-uri: copy all bundle references ino the refs/bundle space\n> bundle-uri: update bundle clone tests with new refspec path\n\nScott Chacon (2):\n  bundle-uri: copy all bundle references ino the refs/bundle space\n  bundle-uri: add test for bundle-uri clones with tags\n\n Documentation/technical/bundle-uri.adoc |  14 +-\n bundle-uri.c                            |   2 +-\n t/t5558-clone-bundle-uri.sh             | 202 ++++++++++++++----------\n 3 files changed, 124 insertions(+), 94 deletions(-)\n\n\nbase-commit: f65182a99e545d2f2bc22e6c1c2da192133b16a3\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1897%2Fschacon%2Fsc-more-bundle-refs-v7\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1897/schacon/sc-more-bundle-refs-v7\nPull-Request: https://github.com/git/git/pull/1897\n\nRange-diff vs v6:\n\n 1:  d6ec5c87b43 ! 1:  1cbf0787d49 bundle-uri: copy all bundle references ino the refs/bundle space\n     @@ Documentation/technical/bundle-uri.adoc: will interact with bundle URIs accordin\n      -   introduce a numbered namespace (such as `refs/bundles/<i>/*`) such that\n      -   stale bundle refs can be deleted.\n      +   client unbundles that data using a refspec. The refspec used is\n     -+   `+refs/*:refs/bundles/*`. These refs are stored so that later \n     ++   `+refs/*:refs/bundles/*`. These refs are stored so that later\n      +   `git fetch` negotiations can communicate each bundled ref as a `have`,\n      +   reducing the size of the fetch over the Git protocol. To allow pruning\n      +   refs from this ref namespace, Git may introduce a numbered namespace\n 2:  825d2b01eae = 2:  7f36484e267 bundle-uri: add test for bundle-uri clones with tags\n\n-- \ngitgitgadget\n"},{"id":"516837","messageId":"7f36484e267021bb6d3b088f3c7c8f97e655c7eb.1745609589.git.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v7.git.git.1745609589.gitgitgadget@gmail.com","subject":"[PATCH v7 2/2] bundle-uri: add test for bundle-uri clones with tags","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-04-25T19:33:09Z","receivedAt":"2025-04-25T19:33:14Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"From: Scott Chacon <schacon@gmail.com>\n\nThe change to the bundle-uri unbundling refspec now includes tags, so this\nadds a very, very simple test to make sure that tags in a bundle are\nproperly added to the cloned repository and will be included in ref\nnegotiation with the subsequent fetch.\n\nSigned-off-by: Scott Chacon <schacon@gmail.com>\n---\n t/t5558-clone-bundle-uri.sh | 30 ++++++++++++++++++++++++++++++\n 1 file changed, 30 insertions(+)\n\ndiff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh\nindex 33a7009e9a2..9b211a626bd 100755\n--- a/t/t5558-clone-bundle-uri.sh\n+++ b/t/t5558-clone-bundle-uri.sh\n@@ -107,6 +107,36 @@ test_expect_success 'clone with file:// bundle' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'create bundle with tags' '\n+\tgit init clone-from-tags &&\n+\t(\n+\t\tcd clone-from-tags &&\n+\t\tgit checkout -b base &&\n+\t\tgit checkout -b topic &&\n+\n+\t\ttest_commit A &&\n+\t\tgit tag tag-A &&\n+\t\tgit checkout -b base &&\n+\t\tgit branch -d topic &&\n+\t\ttest_commit B &&\n+\n+\t\tgit bundle create ALL.bundle --all &&\n+\t\tgit bundle verify ALL.bundle\n+\t)\n+'\n+\n+test_expect_success 'clone with tags bundle' '\n+\tgit clone --bundle-uri=\"clone-from-tags/ALL.bundle\" \\\n+\t\tclone-from-tags clone-tags-path &&\n+\n+\tgit -C clone-from-tags for-each-ref --format=\"%(refname:lstrip=1)\" \\\n+\t\t>expect &&\n+\tgit -C clone-tags-path for-each-ref --format=\"%(refname:lstrip=2)\" \\\n+\t\trefs/bundles >actual &&\n+\n+\ttest_cmp expect actual\n+'\n+\n # To get interesting tests for bundle lists, we need to construct a\n # somewhat-interesting commit history.\n #\n-- \ngitgitgadget\n"},{"id":"516838","messageId":"1cbf0787d49ba25454763a2574fd46010e0f6390.1745609589.git.gitgitgadget@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v7.git.git.1745609589.gitgitgadget@gmail.com","subject":"[PATCH v7 1/2] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Scott Chacon via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-04-25T19:33:08Z","receivedAt":"2025-04-25T19:33:14Z","isPatch":true,"sender":{"key":"schacon@gmail.com","avatar":"https://gravatar.com/avatar/9b13a8a078e1dcf8588c4eea9554445d51ebed6c41b51f56f4d96738130b05c6?d=mp&s=160"},"body":"From: Scott Chacon <schacon@gmail.com>\n\nWhen downloading bundles via the bundle-uri functionality, we only copy the\nreferences from refs/heads into the refs/bundle space. I'm not sure why this\nrefspec is hardcoded to be so limited, but it makes the ref negotiation on\nthe subsequent fetch suboptimal, since it won't use objects that are\nreferenced outside of the current heads of the bundled repository.\n\nThis change to copy everything in refs/ in the bundle to refs/bundles/\nsignificantly helps the subsequent fetch, since nearly all the references\nare now included in the negotiation.\n\nThe update to the bundle-uri unbundling refspec puts all the heads from a\nbundle file into refs/bundle/heads instead of directly into refs/bundle/ so\nthe tests also need to be updated to look in the new heirarchy.\n\nSigned-off-by: Scott Chacon <schacon@gmail.com>\n---\n Documentation/technical/bundle-uri.adoc |  14 +-\n bundle-uri.c                            |   2 +-\n t/t5558-clone-bundle-uri.sh             | 172 ++++++++++++------------\n 3 files changed, 94 insertions(+), 94 deletions(-)\n\ndiff --git a/Documentation/technical/bundle-uri.adoc b/Documentation/technical/bundle-uri.adoc\nindex 91d3a13e327..12283fa9ed5 100644\n--- a/Documentation/technical/bundle-uri.adoc\n+++ b/Documentation/technical/bundle-uri.adoc\n@@ -232,13 +232,13 @@ will interact with bundle URIs according to the following flow:\n    are present in the client repository. If some are missing, then the\n    client delays unbundling until other bundles have been unbundled,\n    making those OIDs present. When all required OIDs are present, the\n-   client unbundles that data using a refspec. The default refspec is\n-   `+refs/heads/*:refs/bundles/*`, but this can be configured. These refs\n-   are stored so that later `git fetch` negotiations can communicate each\n-   bundled ref as a `have`, reducing the size of the fetch over the Git\n-   protocol. To allow pruning refs from this ref namespace, Git may\n-   introduce a numbered namespace (such as `refs/bundles/<i>/*`) such that\n-   stale bundle refs can be deleted.\n+   client unbundles that data using a refspec. The refspec used is\n+   `+refs/*:refs/bundles/*`. These refs are stored so that later\n+   `git fetch` negotiations can communicate each bundled ref as a `have`,\n+   reducing the size of the fetch over the Git protocol. To allow pruning\n+   refs from this ref namespace, Git may introduce a numbered namespace\n+   (such as `refs/bundles/<i>/*`) such that stale bundle refs can be\n+   deleted.\n \n 3. If the file is instead a bundle list, then the client inspects the\n    `bundle.mode` to see if the list is of the `all` or `any` form.\ndiff --git a/bundle-uri.c b/bundle-uri.c\nindex 96d2ba726d9..dc120664d1e 100644\n--- a/bundle-uri.c\n+++ b/bundle-uri.c\n@@ -403,7 +403,7 @@ static int unbundle_from_file(struct repository *r, const char *file)\n \t\tconst char *branch_name;\n \t\tint has_old;\n \n-\t\tif (!skip_prefix(refname->string, \"refs/heads/\", &branch_name))\n+\t\tif (!skip_prefix(refname->string, \"refs/\", &branch_name))\n \t\t\tcontinue;\n \n \t\tstrbuf_setlen(&bundle_ref, bundle_prefix_len);\ndiff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh\nindex 3816ed5058d..33a7009e9a2 100755\n--- a/t/t5558-clone-bundle-uri.sh\n+++ b/t/t5558-clone-bundle-uri.sh\n@@ -58,7 +58,7 @@ test_expect_success 'create bundle' '\n test_expect_success 'clone with path bundle' '\n \tgit clone --bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from clone-path &&\n-\tgit -C clone-path rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-path rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -68,9 +68,9 @@ test_expect_success 'clone with bundle that has bad header' '\n \tgit clone --bundle-uri=\"clone-from/bad-header.bundle\" \\\n \t\tclone-from clone-bad-header 2>err &&\n \tcommit_b=$(git -C clone-from rev-parse B) &&\n-\ttest_grep \"trying to write ref '\\''refs/bundles/topic'\\'' with nonexistent object $commit_b\" err &&\n+\ttest_grep \"trying to write ref '\\''refs/bundles/heads/topic'\\'' with nonexistent object $commit_b\" err &&\n \tgit -C clone-bad-header for-each-ref --format=\"%(refname)\" >refs &&\n-\ttest_grep ! \"refs/bundles/\" refs\n+\ttest_grep ! \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone with bundle that has bad object' '\n@@ -78,8 +78,8 @@ test_expect_success 'clone with bundle that has bad object' '\n \tgit clone --bundle-uri=\"clone-from/bad-object.bundle\" \\\n \t\tclone-from clone-bad-object-no-fsck &&\n \tgit -C clone-bad-object-no-fsck for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/bad >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/bad >expect &&\n \ttest_cmp expect actual &&\n \n \t# Unbundle fails with fsckObjects set true, but clone can still proceed.\n@@ -87,14 +87,14 @@ test_expect_success 'clone with bundle that has bad object' '\n \t\tclone-from clone-bad-object-fsck 2>err &&\n \ttest_grep \"missingEmail\" err &&\n \tgit -C clone-bad-object-fsck for-each-ref --format=\"%(refname)\" >refs &&\n-\ttest_grep ! \"refs/bundles/\" refs\n+\ttest_grep ! \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone with path bundle and non-default hash' '\n \ttest_when_finished \"rm -rf clone-path-non-default-hash\" &&\n \tGIT_DEFAULT_HASH=sha256 git clone --bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from clone-path-non-default-hash &&\n-\tgit -C clone-path-non-default-hash rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-path-non-default-hash rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -102,7 +102,7 @@ test_expect_success 'clone with path bundle and non-default hash' '\n test_expect_success 'clone with file:// bundle' '\n \tgit clone --bundle-uri=\"file://$(pwd)/clone-from/B.bundle\" \\\n \t\tclone-from clone-file &&\n-\tgit -C clone-file rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-file rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -173,12 +173,12 @@ test_expect_success 'clone bundle list (file, no heuristic)' '\n \tgit -C clone-list-file cat-file --batch-check <oids &&\n \n \tgit -C clone-list-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -220,10 +220,10 @@ test_expect_success 'clone bundle list (file, all mode, some failures)' '\n \tgit -C clone-all-some cat-file --batch-check <oids &&\n \n \tgit -C clone-all-some for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -253,7 +253,7 @@ test_expect_success 'clone bundle list (file, all mode, all failures)' '\n \tgit -C clone-all-fail cat-file --batch-check <oids &&\n \n \tgit -C clone-all-fail for-each-ref --format=\"%(refname)\" >refs &&\n-\t! grep \"refs/bundles/\" refs\n+\t! grep \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'clone bundle list (file, any mode)' '\n@@ -282,9 +282,9 @@ test_expect_success 'clone bundle list (file, any mode)' '\n \tgit -C clone-any-file cat-file --batch-check <oids &&\n \n \tgit -C clone-any-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -313,7 +313,7 @@ test_expect_success 'clone bundle list (file, any mode, all failures)' '\n \tgit -C clone-any-fail cat-file --batch-check <oids &&\n \n \tgit -C clone-any-fail for-each-ref --format=\"%(refname)\" >refs &&\n-\t! grep \"refs/bundles/\" refs\n+\t! grep \"refs/bundles/heads/\" refs\n '\n \n test_expect_success 'negotiation: bundle with part of wanted commits' '\n@@ -322,10 +322,10 @@ test_expect_success 'negotiation: bundle with part of wanted commits' '\n \tgit clone --no-local --bundle-uri=\"clone-from/A.bundle\" \\\n \t\tclone-from nego-bundle-part &&\n \tgit -C nego-bundle-part for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/topic >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/topic >expect &&\n \ttest_cmp expect actual &&\n-\t# Ensure that refs/bundles/topic are sent as \"have\".\n+\t# Ensure that refs/bundles/heads/topic are sent as \"have\".\n \ttip=$(git -C clone-from rev-parse A) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n@@ -337,8 +337,8 @@ test_expect_success 'negotiation: bundle with all wanted commits' '\n \t\t--bundle-uri=\"clone-from/B.bundle\" \\\n \t\tclone-from nego-bundle-all &&\n \tgit -C nego-bundle-all for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n-\ttest_write_lines refs/bundles/topic >expect &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n+\ttest_write_lines refs/bundles/heads/topic >expect &&\n \ttest_cmp expect actual &&\n \t# We already have all needed commits so no \"want\" needed.\n \ttest_grep ! \"clone> want \" trace-packet.txt\n@@ -363,13 +363,13 @@ test_expect_success 'negotiation: bundle list (no heuristic)' '\n \t\tclone-from nego-bundle-list-no-heuristic &&\n \n \tgit -C nego-bundle-list-no-heuristic for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n-\ttip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/left) &&\n+\ttip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/heads/left) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n \n@@ -395,13 +395,13 @@ test_expect_success 'negotiation: bundle list (creationToken)' '\n \t\tclone-from nego-bundle-list-heuristic &&\n \n \tgit -C nego-bundle-list-heuristic for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n-\ttip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/left) &&\n+\ttip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/heads/left) &&\n \ttest_grep \"clone> have $tip\" trace-packet.txt\n '\n \n@@ -428,10 +428,10 @@ test_expect_success 'negotiation: bundle list with all wanted commits' '\n \t\tclone-from nego-bundle-list-all &&\n \n \tgit -C nego-bundle-list-all for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect actual &&\n \t# We already have all needed commits so no \"want\" needed.\n@@ -465,7 +465,7 @@ test_expect_success 'clone HTTP bundle' '\n \n \tgit clone --bundle-uri=\"$HTTPD_URL/B.bundle\" \\\n \t\t\"$HTTPD_URL/smart/fetch.git\" clone-http &&\n-\tgit -C clone-http rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-http rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual &&\n \n@@ -476,7 +476,7 @@ test_expect_success 'clone HTTP bundle with non-default hash' '\n \ttest_when_finished \"rm -rf clone-http-non-default-hash\" &&\n \tGIT_DEFAULT_HASH=sha256 git clone --bundle-uri=\"$HTTPD_URL/B.bundle\" \\\n \t\t\"$HTTPD_URL/smart/fetch.git\" clone-http-non-default-hash &&\n-\tgit -C clone-http-non-default-hash rev-parse refs/bundles/topic >actual &&\n+\tgit -C clone-http-non-default-hash rev-parse refs/bundles/heads/topic >actual &&\n \tgit -C clone-from rev-parse topic >expect &&\n \ttest_cmp expect actual\n '\n@@ -553,12 +553,12 @@ test_expect_success 'clone bundle list (HTTP, any mode)' '\n \tgit -C clone-any-http cat-file --batch-check <oids &&\n \n \tgit -C clone-list-file for-each-ref --format=\"%(refname)\" >refs &&\n-\tgrep \"refs/bundles/\" refs >actual &&\n+\tgrep \"refs/bundles/heads/\" refs >actual &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect actual\n '\n@@ -641,9 +641,9 @@ test_expect_success 'clone incomplete bundle list (http, creationToken)' '\n \ttest_cmp expect actual &&\n \n \t# We now have only one bundle ref.\n-\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -679,13 +679,13 @@ test_expect_success 'clone incomplete bundle list (http, creationToken)' '\n \ttest_cmp expect actual &&\n \n \t# We now have all bundle refs.\n-\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C clone-token-http for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs\n '\n@@ -721,9 +721,9 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \ttest_cmp expect actual &&\n \n \t# only received base ref from bundle-1\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n+\trefs/bundles/heads/base\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -749,10 +749,10 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \ttest_cmp expect actual &&\n \n \t# received left from bundle-2\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -795,12 +795,12 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '\n \n \t# received merge ref from bundle-4, but right is missing\n \t# because we did not download bundle-3.\n-\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-http-4 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \n \tcat >expect <<-\\EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -862,7 +862,7 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# All bundles failed to unbundle\n-\tgit -C download-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \ttest_must_be_empty refs &&\n \n \t# Case 2: middle bundle does not exist, only two bundles can unbundle\n@@ -909,10 +909,10 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# bundle-1 and bundle-3 could unbundle, but bundle-4 could not\n-\tgit -C download-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -961,11 +961,11 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' '\n \ttest_cmp expect actual &&\n \n \t# fake.bundle did not unbundle, but the others did.\n-\tgit -C download-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C download-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs\n '\n@@ -1083,15 +1083,15 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-1 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/lefter\n-\trefs/bundles/merge\n-\trefs/bundles/right\n-\trefs/bundles/righter\n-\trefs/bundles/top\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/lefter\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n+\trefs/bundles/heads/righter\n+\trefs/bundles/heads/top\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -1144,12 +1144,12 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-2 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/merge\n-\trefs/bundles/right\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/merge\n+\trefs/bundles/heads/right\n \tEOF\n \ttest_cmp expect refs &&\n \n@@ -1204,13 +1204,13 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' '\n \ttest_cmp expect actual &&\n \n \t# Check which bundles have unbundled by refs\n-\tgit -C fetch-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/*\" >refs &&\n+\tgit -C fetch-3 for-each-ref --format=\"%(refname)\" \"refs/bundles/heads/*\" >refs &&\n \tcat >expect <<-EOF &&\n-\trefs/bundles/base\n-\trefs/bundles/left\n-\trefs/bundles/lefter\n-\trefs/bundles/right\n-\trefs/bundles/righter\n+\trefs/bundles/heads/base\n+\trefs/bundles/heads/left\n+\trefs/bundles/heads/lefter\n+\trefs/bundles/heads/right\n+\trefs/bundles/heads/righter\n \tEOF\n \ttest_cmp expect refs\n '\n-- \ngitgitgadget\n\n"},{"id":"516842","messageId":"xmqq8qnot1kj.fsf@gitster.g","threadId":"62999","inReplyTo":"pull.1897.v7.git.git.1745609589.gitgitgadget@gmail.com","subject":"Re: [PATCH v7 0/2] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-04-25T20:42:52Z","receivedAt":"2025-04-25T20:42:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Scott Chacon via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> Sorry everyone for the noise. There was a whitespace issue the tests\n> complained about, hopefully this fixes it.\n\nThanks for being thorough.  Will replace.\n"},{"id":"516941","messageId":"d71b3fc1-d2fc-436d-876c-0bd1475a88ce@gmail.com","threadId":"62999","inReplyTo":"pull.1897.v7.git.git.1745609589.gitgitgadget@gmail.com","subject":"Re: [PATCH v7 0/2] bundle-uri: copy all bundle references ino the refs/bundle space","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2025-04-29T09:00:13Z","receivedAt":"2025-04-29T09:00:22Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Scott\n\nThank you for updating the documentation. This version looks good to me\n\nThanks\n\nPhillip\n\nOn 25/04/2025 20:33, Scott Chacon via GitGitGadget wrote:\n> Sorry everyone for the noise. There was a whitespace issue the tests\n> complained about, hopefully this fixes it.\n> \n>> bundle-uri: copy all bundle references ino the refs/bundle space\n>> bundle-uri: update bundle clone tests with new refspec path\n> \n> Scott Chacon (2):\n>    bundle-uri: copy all bundle references ino the refs/bundle space\n>    bundle-uri: add test for bundle-uri clones with tags\n> \n>   Documentation/technical/bundle-uri.adoc |  14 +-\n>   bundle-uri.c                            |   2 +-\n>   t/t5558-clone-bundle-uri.sh             | 202 ++++++++++++++----------\n>   3 files changed, 124 insertions(+), 94 deletions(-)\n> \n> \n> base-commit: f65182a99e545d2f2bc22e6c1c2da192133b16a3\n> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1897%2Fschacon%2Fsc-more-bundle-refs-v7\n> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1897/schacon/sc-more-bundle-refs-v7\n> Pull-Request: https://github.com/git/git/pull/1897\n> \n> Range-diff vs v6:\n> \n>   1:  d6ec5c87b43 ! 1:  1cbf0787d49 bundle-uri: copy all bundle references ino the refs/bundle space\n>       @@ Documentation/technical/bundle-uri.adoc: will interact with bundle URIs accordin\n>        -   introduce a numbered namespace (such as `refs/bundles/<i>/*`) such that\n>        -   stale bundle refs can be deleted.\n>        +   client unbundles that data using a refspec. The refspec used is\n>       -+   `+refs/*:refs/bundles/*`. These refs are stored so that later\n>       ++   `+refs/*:refs/bundles/*`. These refs are stored so that later\n>        +   `git fetch` negotiations can communicate each bundled ref as a `have`,\n>        +   reducing the size of the fetch over the Git protocol. To allow pruning\n>        +   refs from this ref namespace, Git may introduce a numbered namespace\n>   2:  825d2b01eae = 2:  7f36484e267 bundle-uri: add test for bundle-uri clones with tags\n> \n\n"}]}