1

I am trying to create a git bundle of a repository using JGit's BundleWriter. I am attempting to include all Refs in my bundle like so:

Repository repo; // valid repo from elsewhere
BundleWriter bundleWriter = new BundleWriter(repo);

Map<String, Ref> refMap = repo.getAllRefs();
for (Ref ref:refMap.values()) {
    bundleWriter.include(ref);
}

JGit throws an exception for the symbolic HEAD ref, which refers to the default branch (refs/head/master)

java.lang.IllegalArgumentException: Invalid ref name: HEAD
at org.eclipse.jgit.transport.BundleWriter.include(BundleWriter.java:132)

If I exclude the HEAD symbolic ref the bundle is created fine but, when the bundle is cloned from, the missing HEAD reference causes the following git error:

warning: remote HEAD refers to nonexistent ref, unable to checkout.

I can manually checkout master to get things back to normal but it's not ideal behaviour as the bundle is being sent to other people who will expect it to work like any other git repository and include the HEAD reference pointing to the default branch.

Can anyone offer any advice or workarounds so that the default branch is set when the bundle is cloned?

Thanks

Beaver
  • 13
  • 3
  • To me this looks like a bug in JGit, I'd open a [bugzilla](https://bugs.eclipse.org/bugs/enter_bug.cgi?product=JGit) or ask on the [mailing list](https://dev.eclipse.org/mailman/listinfo/jgit-dev). In the meanwhile, to work around the issue, I see no other way than to adopt the code and remove the ref-validity-check. `BundleWriter` seems to be relatively small and self-contained. – Rüdiger Herrmann Oct 10 '14 at 12:04
  • @RüdigerHerrmann thank you for the advice. I think I will patch BundleWriter locally to work around the issue and report it to the project. – Beaver Oct 13 '14 at 08:17

2 Answers2

1

The bug has been reported to JGit in bug 446813 (by the OP I assume). It has already been fixed and will be released in the next JGit version (3.6).

robinst
  • 30,027
  • 10
  • 102
  • 108
0

Note: the origin of the error is now explained in Git 2.11 fix:

See commit eb39879, commit 63b747c (09 Sep 2016) by Jonathan Tan (jhowtan).
Helped-by: Jonathan Nieder (artagnon).
See commit 55e4f93 (09 Sep 2016) by Jonathan Nieder (artagnon).
Helped-by: Jonathan Nieder (artagnon).
(Merged by Junio C Hamano -- gitster -- in commit 07d8724, 21 Sep 2016)

connect: advertized capability is not a ref

since [JGit] v3.1.0.201309270735-rc1~22 (Advertise capabilities with no refs in upload service., 2013-08-08, commit ae1f469), JGit's ref advertisement includes a ref named capabilities^{} to advertise its capabilities on, while git's ref advertisement is empty in this case.
This allows the client to learn about the server's capabilities and is needed, for example, for fetch-by-sha1 to work when no refs are advertised.

Here, this affects also git bundle.
As mentioned above, it is fixed on JGit side.

when the bundle is cloned from, the missing HEAD reference causes the following git error:

warning: remote HEAD refers to nonexistent ref, unable to checkout.

That is what is now (Git 2.11, Q4 2016) different:

Git advertises the same capabilities^{} ref in its ref advertisement for push but since it never did so for fetch, the client didn't need to handle this case.
Handle it.


The code to parse capability list for v0 on-wire protocol fell into an infinite loop when a capability appears multiple times, which has been corrected with Git 2.41 (Q2 2023).

See commit 7ce4c8f, commit c471623, commit d6747ad, commit 20272ee, commit 13e67aa, commit e6c4309, commit aa962fe (14 Apr 2023) by Jeff King (peff).
(Merged by Junio C Hamano -- gitster -- in commit 80d268f, 25 Apr 2023)

v0 protocol: fix sha1/sha256 confusion for capabilities^{}

Signed-off-by: Jeff King

Commit eb39879 ("connect: advertized capability is not a ref", 2016-09-09, Git v2.11.0-rc0 -- merge listed in batch #4) added support for an upload-pack server responding with:

0000000000000000000000000000000000000000        capabilities^{}

followed by a NUL and the actual capabilities.
We correctly parse the oid using the packet_reader's hash_algo field, but then we compare it to null_oid(), which will instead use our current repo's default algorithm.
If we're defaulting to sha256 locally but the other side is sha1, they won't match and we'll fail to parse the line (and thus die()).

This can cause a test failure when the suite is run with GIT_TEST_DEFAULT_HASH=sha256, and we even do so regularly via the linux-sha256 CI job.
But since the test requires JGit to run, it's usually just skipped, and nobody noticed the problem.

The reason the original patch used JGit is that Git itself does not ever produce such a line via upload-pack; the feature was added to fix a real-world problem when interacting with JGit.
That was good for verifying that the incompatibility was fixed, but it's not a good regression test:

  • hardly anybody runs it, because you have to have jgit installed; hence this bug going unnoticed
  • we're depending on jgit's behavior for the test to do anything useful.
    In particular, this behavior is only relevant to the v0 protocol, but these days we ask for the v2 protocol by default.
    So for modern jgit, this is probably testing nothing.
  • it's complicated and slow.
    We had to do some fifo trickery to handle races, and this one test makes up 40% of the runtime of the total script.

Instead, let's just hard-code the response that's of interest to us.
That will test exactly what we want for every run, and reveals the bug when run in sha256 mode.
And of course we'll fix the actual bug by using the correct hash_algo struct.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250