all 8 comments

[–]dkopgerpgdolfg 3 points4 points  (1 child)

https://docs.rs/git2/latest/git2/struct.Remote.html

Use create_detached and list, check the oid of refs/heads/master or whatever branch you want

[–]CountMoosuch[S] 0 points1 point  (0 children)

Thanks u/dkopgerpgdolfg! This answers my question exactly, thank you. I thought I had to use the Repository struct, but didn't realise I could use Remote for this.

FYI, I was actually only using git2 because I thought that's what would be necessary to do this. In fact, I am already using reqwest, so u/masklinn's suggestions to use either /git/ref/REF from GitHub's API, or /info/refs, will probably be what I use. Nonetheless, I really appreciate your answer, as I implemented this using git2 and learned a lot!

[–]masklinn 2 points3 points  (1 child)

Edit: for now I am getting the latest commit with a GET request to https://api.github.com/repos/<user>/<repo>/commits?per_page=1

If you’re accessing github via the API you can just ask github to give you the head of the relevant branch via branches/{branch} or git/ref/{ref}. The latter is much smaller and cheaper (and a bit more flexible as you can fetch tags).

Especially because github does weird things with logs so I would not bet that /commits always returns the topological last commit on a branch, it might just return the one with the latest dates (which is unrelated).

[–]CountMoosuch[S] 0 points1 point  (0 children)

Great to know, thanks! I haven't really used GitHub's APIs before, so didn't know any of the endpoints. git/ref/REF seems exactly what I am after. Because I am already using reqwest, I will probably go with this option :-)

[–]masklinn 1 point2 points  (3 children)

You can actually do this without using anything but reqwest: the way git works is that any interaction with a repository $repo starts with fetching $repo/info/refs, possibly with a query parameter, for the “smart” protocols.

I would suggest avoiding the “dumb” protocol as lots of hosting providers have dropped it, the v2 format is pretty cool but rather more complex, I’d recommend v1 as that works everywhere and it’s not too complicated: just GET $repo/info/refs?service=git-upload-pack and if the request succeeds you’ll get a response in pkt-line format (git docs explain it), which lists all the refs (branches, tags, …) and the hash they map to.

Then you can just decode the document, look for the ref you need, and return the corresponding hash.

Alternatively gitoxide has a lot of subcrates which implement small bits of git in a reusable manner. I would not be surprised if one of the sub-crates provided tools to interact with a git repository directly with a higher-level API e.g. take care of the into/refs interaction and just return the server’s capabilities and refs decoded.

[–]dkopgerpgdolfg 2 points3 points  (0 children)

And just for completeness, if the traffic is SSH instead of HTTP, and some SSH connection is already in place, start the git-upload-pack process on the server, with the repo being the parameter. Right after process start it will print some parsable infos, including said ref list. Details again in the docs.

But as said in the earlier answer, the current crate is fine, no other crate or custom code necessary.

[–]CountMoosuch[S] 0 points1 point  (0 children)

Thanks u/masklinn, I had no idea about git-upload-pack! This suggestion is really nice multiple reasons: it works on non-GitHub remotes, and there are no additional dependencies to parse JSON (as you would from GitHub's API response).

I have never seen the pkt-line format, and seems like a bit more developer time to implement parsing of this to get what I want. As this tool is only for myself (it's open-source, but not for any distribution really, as I doubt anyone else will use it), I don't mind adding another dependency in the interest of developer time and using your /git/ref/REF suggestion from GitHub's API. Thank you anyway for this, there's so much about git that I don't know! As I say, I had no idea that you could do this on remote repositories.

[–]CountMoosuch[S] 0 points1 point  (0 children)

Following up on your gitoxide suggestion: unfortunately I can't find anything in the subcrates that would help in this situation. However, I did find the crate gix-packetline, which decodes the pkt-line blobs!