LibGit2Sharp中与git log path等效的是什么?

11

如何获取包含特定文件的提交列表,即相当于 LibGit2Sharpgit log path 命令。

这个功能是否已经实现或者我是否遗漏了某些方法?


2
LibGit2Sharp问题跟踪器中有一个特定于此主题的功能请求。 - nulltoken
4个回答

6
我正在使用LibGit2Sharp为我的应用程序获取相同的功能。我编写了下面的代码,它将列出包含该文件的所有提交。GitCommit类没有包含在内,但它只是一组属性。
我的意图是让代码仅列出更改了文件的提交,类似于SVN日志,但我还没有编写该部分。
请注意,代码尚未优化,这只是我的初始尝试,但我希望它有用。
/// <summary>
/// Loads the history for a file
/// </summary>
/// <param name="filePath">Path to file</param>
/// <returns>List of version history</returns>
public List<IVersionHistory> LoadHistory(string filePath)
{
    LibGit2Sharp.Repository repo = new Repository(this.pathToRepo);

    string path = filePath.Replace(this.pathToRepo.Replace(System.IO.Path.DirectorySeparatorChar + ".git", string.Empty), string.Empty).Substring(1);
    List<IVersionHistory> list = new List<IVersionHistory>();

    foreach (Commit commit in repo.Head.Commits)
    {
        if (this.TreeContainsFile(commit.Tree, path) && list.Count(x => x.Date == commit.Author.When) == 0)
        {
            list.Add(new GitCommit() { Author = commit.Author.Name, Date = commit.Author.When, Message = commit.MessageShort} as IVersionHistory);
        }
    }

    return list;
}

/// <summary>
/// Checks a GIT tree to see if a file exists
/// </summary>
/// <param name="tree">The GIT tree</param>
/// <param name="filename">The file name</param>
/// <returns>true if file exists</returns>
private bool TreeContainsFile(Tree tree, string filename)
{
    if (tree.Any(x => x.Path == filename))
    {
        return true;
    }
    else
    {
        foreach (Tree branch in tree.Where(x => x.Type == GitObjectType.Tree).Select(x => x.Target as Tree))
        {
            if (this.TreeContainsFile(branch, filename))
            {
                return true;
            }
        }
    }

    return false;
}

只是出于好奇,IVersionHistory是什么? - toofarsideways
@toofarsideways 我的应用程序可以使用 SVN 和 Git 存储库,因此我有一个文件版本历史记录的界面。 - dmck
我建议您使用基于差异的方法,这应该会更快。您可以查看一个利用此方法的提案 **here**。 - nulltoken
@nulltoken 这很奇怪,他已经编写了一个测试用例,我怀疑它完全正常运行,我会尝试追踪这个问题,看看能否将其隔离出来... - toofarsideways
1
这个dll必须与托管代码匹配。我建议从vNext分支开始。另外,也许我们应该把这个讨论移到SO之外? :-) - nulltoken
显示剩余4条评论

5

1
C 库,我想你是指它。 - Edward Thomson
有没有办法手动遍历结构?还是我必须获取提交列表,然后排除不涉及我感兴趣的文件的提交? - toofarsideways
正如dmck的回答所示,您需要获取提交并自行进行过滤。 - VonC

5
每当树/ blob 被更改后,它都会获得新的 ID 哈希值。你只需要与父提交的树/ blob 项哈希进行比较即可。
var commits = repository.Commits
   .Where(c => c.Parents.Count() == 1 && c.Tree["file"] != null &&
      (c.Parents.FirstOrDefault().Tree["file"] == null ||
         c.Tree["file"].Target.Id !=
         c.Parents.FirstOrDefault().Tree["file"].Target.Id));

哇!谢谢。这是我遇到的最好的机制。 - grenade

1
非常类似于dmck的回答,但更加更新。
private bool TreeContainsFile(Tree tree, string filePath)
{
    //filePath is the relative path of your file to the root directory
    if (tree.Any(x => x.Path == filePath))
    {
        return true;
    }

    return tree.Where(x => x.GetType() == typeof (TreeEntry))
        .Select(x => x.Target)
        .OfType<Tree>()
        .Any(branch => TreeContainsFile(branch, filePath));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接