eclipse-jgit/jgit

Expose HEAD branch in RemoteConfig

Opened this issue · 2 comments

Description

The value I'm looking for, given this command would be main

❯ git remote show origin
* remote origin
  Fetch URL: https://github.com/xenoterracide/gradle-semver
  Push  URL: https://github.com/xenoterracide/gradle-semver
  HEAD branch: main
  Remote branches:

which from source diving I think being retrieved using Constant.HEAD but doesn't appear to be publicly exposed in any way.

RemoteConfig::getHeadBranch feels appropriate, I'm not certain whether it should return a String or a Ref

Motivation

I need this so I can find the default branch and do describe like behavior to count its distance from the last tag. More complexly, I want to find the distance of the most common ancestor of a branch from the "HEAD branch" from its most recent tag.

I am not trying to clone.

Alternatives considered

I guess I could copy/paste this implementation to get it, accessing FetchResult myself. In the mean time I'm probably going to do an educated guess heuristic, or have a user explicitly set it. Both of which are fragile, and would not change if the remote actually changed. I might actually just invoke git but I'm trying to avoid that due to the lack of happyness of gradle regarding invoking external processes when using the configuration cache.

Additional context

org.eclipse.jgit:org.eclipse.jgit:7.0.0.202409031743-r=compileClasspath,testCompileClasspath,testRuntimeClasspath
------------------------------------------------------------
Gradle 8.10.2
------------------------------------------------------------

Build time:    2024-09-23 21:28:39 UTC
Revision:      415adb9e06a516c44b391edff552fd42139443f7

Kotlin:        1.9.24
Groovy:        3.0.22
Ant:           Apache Ant(TM) version 1.10.14 compiled on August 16 2023
Launcher JVM:  21.0.5 (Eclipse Adoptium 21.0.5+11-LTS)
Daemon JVM:    /home/xeno/.asdf/installs/java/temurin-21.0.5+11.0.LTS (no JDK specified, using current Java home)
OS:            Linux 6.6.54-2-MANJARO amd64
msohn commented

The default branch of a remote repository is not stored in the static remote configuration of the git client.
Instead you can use git ls-remote to get all refs, this includes HEAD and, if it's referring to a branch, the peeled ref (a commitId).

Run the ls-remote command which returns all refs. The list starts with the value of the symbolic ref HEAD and, if it's set to a ref (for the jgit repo refs/heads/master), the peeled symbolic ref HEAD (here c67393562be7e3db0e39cb2d3ff5f8192e2f2cd5).

jgit ls-remote --symref https://eclipse.gerrithub.io/eclipse-jgit/jgit.git
ref: refs/heads/master  HEAD
c67393562be7e3db0e39cb2d3ff5f8192e2f2cd5        HEAD
5140bb0aafe9c32c89526c5fb1afdbdc5cc9454d        refs/changes/00/100/1
bf3d0ae6b1907a51fc6ff2309cd27d369743c2fa        refs/changes/00/100/meta
...
fad60bddbbee7fd9f6fe5df8f00b5a348b6f387d        refs/changes/99/99/1
5b7dba35ed9cd5364467e2dbddfb7763fc049771        refs/changes/99/99/meta
c67393562be7e3db0e39cb2d3ff5f8192e2f2cd5        refs/heads/master
026d46de13eb2321c18045469f27b065ba107ff5        refs/heads/next
51d1af9489924ff03fa10ec963110c608c2882a3        refs/heads/stable-0.10
...
42977e7b1fc075fc6f2fc520ccc5ea328c9b136d        refs/tags/v0.10.1
1fdc17bfe4a1deb61756abeb8470bd813827d44a        refs/tags/v0.10.1^{}
f5847db3c229348f7e519900bc88ea4f142f8fe3        refs/tags/v0.11.1
857d1511987599c66b834eb43f25b45394244af3        refs/tags/v0.11.1^{}
fe25d5693bb45634d72b05771c5c9a9691d16c60        refs/tags/v0.11.3
...

Refer to the class org.eclipse.jgit.pgm.LsRemote to see how this can be implemented using JGit APIs.

If you are running CloneCommand to clone a repository it retrieves the same information from the advertised refs via git protocol. It is returned by the FetchResult of the FetchCommand used to fetch the git repo, use FetchResult.getAdvertisedRef(Constants.HEAD) to get the default branch, see CloneCommand.findBranchToCheckout().

but why can't it be exposed in RemoteConfig?

note: talking on the git list about fixing places where this HEAD ref is not automatically present. There is ongoing work even before this conversation. I'm not as frustrated with jgit as a command line in these tickets as its api is a little unintuitive internally. Another thing I could open (and will if you want) is the seeming lack of git remote set-head, I don't really need this. I'm just going to tell consumers to call that themselves instead of invoking git/jgit in my gradle plugin. Since I have no idea what that does to the configuration cache...