【问题标题】:How to determine whether a branch contains a commit with TFS WebApi client library?如何确定分支是否包含带有 TFS WebApi 客户端库的提交?
【发布时间】:2018-11-07 07:09:04
【问题描述】:

基本上我想用 TFS WebApi client libraries 找到 git branch --contains 的 API 替代品:

var commitId = "123456789abcdef";
var branchName = "branch";
var tpc = new TfsTeamProjectCollection(new Uri(""));
var git = tpc.GetClient<GitHttpClient>();
var isInBranch = git.?????(branchName, commitId);

有没有办法实现它?

或者我应该使用 git.exe/libgit 在本地克隆上进行操作(有问题的存储库有点太大,如果可能的话,我更愿意避免克隆它)?

【问题讨论】:

    标签: c# git tfs git-commit tfs-sdk


    【解决方案1】:

    git分支对应的WebApi客户端库不存在--包含命令。

    但是,作为一种解决方法,您可以直接在 C# 代码中运行 git 命令。

    string gitCommand = "git";
    string gitAddArgument = @"add -A" ;
    string gitCommitArgument = @"commit ""explanations_of_changes"" "
    string gitPushArgument = @"push our_remote"
    
    Process.Start(gitCommand, gitAddArgument );
    Process.Start(gitCommand, gitCommitArgument );
    Process.Start(gitCommand, gitPushArgument );
    

    您可以包含您的认证,更多详细信息请参考Run git commands from a C# function

    另一种方法是使用powershell脚本运行git命令并调用TFS API。

    【讨论】:

    【解决方案2】:

    现在最好的方法是使用GetBranchStatsBatchAsync

    GetCommits 解决方案并不真正可靠 - 我们在某些情况下 API 未能找到范围内的特定提交,错误地声明提交不在分支中(然后我们用 GetBranchStatsBatchAsync 替换了逻辑,因为它变得可用从那以后就没有问题了)。


    旧的/不可靠的解决方案

    有一种方法可以在没有GetBranchStatsBatchAsync 的情况下实现它 - 获取提交时间,然后检查该时间间隔是否在分支中,尽管它需要两个单独的调用并且可能有一些问题 与:

    1. Committer date vs Author date - 我使用提交者日期,但没有花足够的时间尝试真正检查它。

    用法是:

    GitHttpClient git = ...;
    var isInBranch = git.BranchContains(
        project: "project",
        repositoryId: "repository",
        branch: "master",
        commitId: "12345678910...")
    

    代码是:

    public static class GitHttpClientExt
    {
        /// <summary>
        /// Gets a value indicating whether a branch with name <paramref name="branch"/> (like 'master', 'dev') contains the commit with specified <paramref name="commitId"/>.
        /// Just like the <code>git branch --contains</code> it doesn't take possible reversions into account.
        /// </summary>
        public static Boolean BranchContains(this GitHttpClient git, String project, String repositoryId, String branch, String commitId)
        {
            var commitToFind = git.TryGetCommit(project: project, repositoryId: repositoryId, commitId: commitId);
            if (commitToFind == null)
            {
                return false;
            }
            var committedDate = commitToFind.Committer.Date; // TODO: It will usually be the same as the author's, but I have failed to check what date TFS actually uses in date queries.
            var criteria = new GitQueryCommitsCriteria
            {
                ItemVersion = new GitVersionDescriptor
                {
                    Version = branch,
                    VersionType = GitVersionType.Branch
                },
                FromDate = DateToString(committedDate.AddSeconds(-1)), // Zero length interval seems to work, but just in case
                ToDate = DateToString(committedDate.AddSeconds(1)),
            };
            var commitIds = git
                .GetAllCommits(
                    project: project, 
                    repositoryId: repositoryId,
                    searchCriteria: criteria)
                .Select(c => c.CommitId);
            return commitIds.Contains(commitId);
        }
    
        /// <summary>
        /// Gets the string representation of <paramref name="dateTime"/> usable in query objects for <see cref="GitHttpClient"/>.
        /// </summary>
        public static String DateToString(DateTimeOffset dateTime)
        {
            return dateTime.ToString(CultureInfo.InvariantCulture);
        }
    
        /// <summary>Tries to retrieve git commit with specified <paramref name="commitId"/> for a project.</summary>
        public static GitCommitRef TryGetCommit(this GitHttpClient git, String project, String repositoryId, String commitId)
        {
            return git
                .GetAllCommits(
                    project: project,
                    repositoryId: repositoryId,
                    searchCriteria: new GitQueryCommitsCriteria
                    {
                        Ids = new List<String>
                        {
                            commitId
                        }
                    })
                .SingleOrDefault();
        }
    
        /// <summary>Retrieve all(up to <see cref="Int32.MaxValue"/>) git (unless <paramref name="top"/> is set) commits for a project</summary>
        public static List<GitCommitRef> GetAllCommits(
            this GitHttpClient git, 
            String project,
            String repositoryId, 
            GitQueryCommitsCriteria searchCriteria, 
            Int32? skip = null, 
            Int32? top = (Int32.MaxValue - 1)) // Current API somehow fails (silently!) on Int32.MaxValue;
        {
            return git
                .GetCommitsAsync(
                    project: project,
                    repositoryId: repositoryId,
                    searchCriteria: searchCriteria,
                    skip: skip,
                    top: top)
                .GetAwaiter()
                .GetResult();
        }
    }
    

    P.S.:目前的代码是异步方法的同步包装器,不幸的是当前项目需要它。如果适合您,请将其重新制作成合适的异步版本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-03
      • 2010-11-28
      • 2016-05-02
      • 2016-02-22
      • 2017-12-02
      • 2013-06-02
      • 1970-01-01
      相关资源
      最近更新 更多