3

我正在使用 LibGit2Sharp 向应用程序添加许多 Git 操作。我添加了Microsoft.Alm.Authentication以帮助身份验证和凭据管理器访问。它非常适合检索已经从命令行输入的凭据。

但是,有什么方法可以连接到 Credential Manager 的登录 UI,提示输入 Github、BitBucket 和 VSTS 的用户名和密码。此 UI 从命令行自动弹出,但在使用 LibGit2Sharp 时不会触发。

我查看了 Github 上的 GitCredentialManager 项目,我可以看到提供 UI 的组件,但是在尝试弄清楚如何明确挂钩之前,我是否缺少某种方式,这是作为Microsoft.Alm.Authentication(或相关包)?或者任何人都可以指出如何最好地连接它的示例或指导?

4

2 回答 2

3

不幸的是,libgit2(或 LibGit2Sharp)中没有直接与功能对话的git-credential-helper功能,这是 git 本身用来执行此操作的功能。

相反,您可以CredentialsHandler在您的PushOptions(或FetchOptions)上设置 a,例如:

options.CredentialsProvider = (url, usernameFromUrl, types) => {
    string username, password;

    Uri uri = new Uri(url);   
    string hostname = uri.Host;

    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.UseShellExecute = false;

    startInfo.RedirectStandardInput = true;
    startInfo.RedirectStandardOutput = true;
    startInfo.RedirectStandardError = true;

    startInfo.FileName = "git.exe";
    startInfo.Arguments = "credential fill";

    Process process = new Process();
    process.StartInfo = startInfo;
    process.Start();

    process.StandardInput.WriteLine("hostname={0}", hostname);
    process.StandardInput.WriteLine("username={0}", usernameFromUrl);

    while ((line = process.StandardOutput.ReadLine()) != null)
    {
        string[] details = line.Split('=', 2);
        if (details[0] == "username")
        {
            username = details[1];
        }
        else if (details[0] == "password")
        {
            password = details[1];
        }
    }

    return new UsernamePasswordCredentials(username, password);
};
于 2018-04-25T08:46:42.393 回答
3

我设法让您的解决方案进行了一些小的修改。我在此处粘贴示例代码以使用 git 凭据进行推送。它使用已存储在计算机中的凭据工作,并在第一次使用 UI 时提示输入凭据。

到目前为止,我遇到的唯一问题是当用户提示输入凭据并且他们输入了无效的用户/密码时。Git 写入控制台询问用户/通行证,直到您输入该过程才完成。试图监控 StandardError/Output 没有成功。我在 stderror 中得到错误文本,但只有在手动填写之后。

public void PushLibGit2Sharp(string repositoryFolder, string branch)
{
    using (var repo = new Repository(repositoryFolder))
    {
        var options = new PushOptions
        {
            CredentialsProvider = (url, usernameFromUrl, types) =>
            {
                ProcessStartInfo startInfo = new ProcessStartInfo
                {
                    FileName = "git.exe",
                    Arguments = "credential fill",
                    UseShellExecute = false,
                    WindowStyle = ProcessWindowStyle.Hidden,
                    CreateNoWindow = true,
                    RedirectStandardInput = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true
                };

                Process process = new Process
                {
                    StartInfo = startInfo
                };

                process.Start();

                // Write query to stdin. 
                // For stdin to work we need to send \n instead of WriteLine
                // We need to send empty line at the end
                var uri = new Uri(url);
                process.StandardInput.NewLine = "\n";       
                process.StandardInput.WriteLine($"protocol={uri.Scheme}");
                process.StandardInput.WriteLine($"host={uri.Host}");
                process.StandardInput.WriteLine($"path={uri.AbsolutePath}");
                process.StandardInput.WriteLine();

                // Get user/pass from stdout
                string username = null;
                string password = null;
                string line;
                while ((line = process.StandardOutput.ReadLine()) != null)
                {
                    string[] details = line.Split('=');
                    if (details[0] == "username")
                    {
                        username = details[1];
                    }
                    else if (details[0] == "password")
                    {
                        password = details[1];
                    }
                }

                return new UsernamePasswordCredentials()
                {
                    Username = username,
                    Password = password
                };
            }
        };

        repo.Network.Push(repo.Branches[branch], options);
    }
}
于 2019-03-27T07:37:15.630 回答