Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Getting last commit with changes in specified subfolder in git repository
internal class GitInfo : VcsInfoRetriever
{
public override VcsInfoData Execute(string localPath)
{
string relativePath;
var repoPath = FindRepoRoot(localPath, ".git\\index", out relativePath);
if (repoPath == null) return null;
using (var repo = new Repository(repoPath))
{
Commit lastCommit = repo.Head.Tip;
if (!string.IsNullOrEmpty(relativePath))
{
var splitPath = relativePath.Replace('\\', '/').Trim('/').Split(Path.DirectorySeparatorChar);
var changeTreeId = GetTreeId(repo.Head.Tip, splitPath);
var previousCommit = repo.Head.Commits
.TakeWhile(commit => GetTreeId(commit, splitPath) == changeTreeId)
.LastOrDefault();
if (previousCommit != null)
lastCommit = previousCommit;
}
if (lastCommit == null) return null;
return new VcsInfoData
{
LastChangedDate = new DateTime(lastCommit.Author.When.Ticks),
LastChangedRevision = lastCommit.Sha,
RevisionIsSequentialNumber = false,
VcsName = "git",
};
}
}
private static string FindRepoRoot(string startPath, string metaFile, out string relativePath)
{
var completeStartPath = Path.GetFullPath(startPath);
relativePath = null;
string testPath;
do
{
testPath = startPath;
string metaPath = Path.Combine(testPath, metaFile);
if (File.Exists(metaPath))
{
relativePath = completeStartPath.Substring(testPath.Length);
return testPath;
}
startPath = Path.GetFullPath(Path.Combine(startPath, ".."));
} while (testPath != startPath);
return null;
}
private static ObjectId GetTreeId(Commit commit, IEnumerable<string> relativePath)
{
var root = commit.Tree;
foreach (var folder in relativePath)
{
if (string.IsNullOrEmpty(folder)) continue;
var treeEntry = root[folder];
if (treeEntry == null) return null;
root = (Tree)treeEntry.Target;
}
return root.Id;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment