Search code examples
gitlibgit2sharp

Can we get a specific file from a git server with libgit2sharp?


Let's say we have a git repo somewhere (in reality, this will be a git server that we run). In this repository, we have the file foo.txt, which has been revised a few times. Using LibGit2Sharp, how can we retrieve the latest version of foo.txt (or any specified file) from the server to view?

(Note that this process would be used in a very high-volume application, so efficiency is ideal, and we would like to avoid getting more data from the server than just the file itself).

I've looked at the documentation, and (partly because I'm still not very familiar with git) I can't figure out how this would be done. I know that there is a git unpack-file <blob> command, which looks like it might be what I want. Is there a way to replicate this behavior with LibGit2Sharp?

Furthermore, if we can do this, is there a way to get a specific revision of foo.txt instead of just the last revision?


Solution

  • The git protocol won't allow you to directly access a specific blob over the wire (However, as pointed at by Chris some git web front end can expose an api which would allow you to do this).

    In order to achieve this through LibGit2Sharp, you'll have to clone the repository locally (ie. retrieve the full history) or fetch the commits that have been pushed upstream and that aren't existing in your previously cloned repository (ie. retrieve the latest changes).

    Once this is done, pick the branch you're interested in, and leverage the file entry indexer to access the content you're interested in.

    string clonedRepoPath = Repository.Clone(remoteRepositoryUrl, localPath);
    
    using (var repo = new Repository(clonedRepoPath))
    {
        var masterBranch = repo.Branches["master"];
        var latestCommit = masterBranch.Tip;
    
        var blob = latestCommit["path/to/your/file.txt"].Target as Blob;
    
        Console.WriteLine(blob.GetContentText());
    }
    

    If you're willing a specific revision rather than the latest commit of a specific branch, the following should help you out.

    var specificCommit = repo.Lookup<Commit>("e90810b");
    

    This will retrieve the commit pointed out by the specified short sha. For what it's worth, the Lookup() method supports the git rev-parse extended SHA1 syntax.

    Considering the "efficiency" standpoint, provided you're interested in a specific remote repository, you may be willing to do the following:

    • Clone the repository once
    • Regularly check if the remote repository has gone ahead of yours by checking if the remote refs have changed (though the repo.Network.ListReferences() method. You can peek a test leveraging this method here
    • If the remote references differs from your local ones, update your local version with those changes through repo.Network.Fetch()
    • Check the new content of your file