3

Is there any way to see the current target SHA of a GitHub repository submodule via Octokit[.net] (without cloning it locally)?

I've been able to track down all the submodules by retrieving the .gitmodules file from the "parent" repo, but that file doesn't maintain where the submodule is pointing with in that submodule repo.

Prior attempts

After finding someone getting this information by indexing into a commit by the submodule path using LibGit2Sharp, I gave that a similar try in Octokit.

var submodulePathContents = await repositoriesClient.Content.GetAllContents(parentRepoId, "path/to/submodule");

While stepping through this code in the debugger, I see this in Locals/Autos, so it definitely knew I was pointing it to a submodule path.

System.Collections.Generic.IReadOnlyList.this[int].get Name: mono-tools Path: path/to/submodule Type:Submodule Octokit.RepositoryContent

Unfortunately, when I get the actual content from that list, submodulePathContents[0].Content is just null.

The GitHub web interface definitely surfaces this information when you navigate to a submodule's parent directory, so it makes me think I've just tried the wrong approach.

GitHub showing a submodule's target hash in the web interface.

Is there some other magic way in the Octokit APIs that I've missed to get this submodule target hash?

patridge
  • 26,385
  • 18
  • 89
  • 135

1 Answers1

3

TL;DR

As described in the question, if you get the contents at the submodule path found in .gitmodules, you will get a piece of content of type "Submodule". This has null content.

If, however, you get the contents of the parent directory for that same submodule path, you will get a piece of content of type "File", with the path of your submodule (e.g., path/to/submodule above). This files hash is the target SHA on the submodule's own repository.

Details

To get the SHA of a submodule, you need to get the contents of its parent directory and then index to the file representing the submodule. While going directly to the path gets you something of type "Submodule", getting the parent contents will get you bunch of "File" type things (and "Dir", if you have sibling subdirectories there). Oddly, this parent content list excludes the "Submodule" type you get when you point directly at the submodule path.

In the example above, just go one level up in the path.

var submodulePathContents = await repositoriesClient.Content.GetAllContents(parentRepoId, "path/to"); // no longer "path/to/submodule"

From there, grab the content item with the path you wanted in the first place (e.g., "path/to/submodule"), which will have a Sha field containing the submodule's target SHA on the submodule repository.

using System.Linq;
…
var submoduleTargetSha = submodulePathContents.First(content => content.Path == submodulePath).Sha;

Here's an example entry from the monodevelop repo's primary submodule directory.

Name: mono-tools Path: main/external/mono-tools Type:File   Octokit.RepositoryContent
Content null    string
DownloadUrl null    System.Uri
EncodedContent  null    string
Encoding    null    string
GitUrl  {https://api.github.com/repos/mono/mono-tools/git/trees/d858f5f27fa8b10d734ccce7ffba631b995093e5}   System.Uri
HtmlUrl {https://github.com/mono/mono-tools/tree/d858f5f27fa8b10d734ccce7ffba631b995093e5}  System.Uri
Name    "mono-tools"    string
Path    "main/external/mono-tools"  string
Sha "d858f5f27fa8b10d734ccce7ffba631b995093e5"  string
Size    0   int
SubmoduleGitUrl null    System.Uri
Target  null    string
Type    File    Octokit.ContentType
Url {https://api.github.com/repos/mono/monodevelop/contents/main/external/mono-tools?ref=master}    System.Uri

And that hash lines up with the web UI.

enter image description here

patridge
  • 26,385
  • 18
  • 89
  • 135