如何在Go中禁用git clone的凭证提示?

如何在Go中禁用git clone的凭证提示?

问题描述:

我试图在Go中运行git clone的等价物,但是如果提示输入来自stdin(例如,如果ssh密钥未在远程存储库中设置),则我想退出该命令。有没有办法做到这一点?现在它只会阻止输入。如何在Go中禁用git clone的凭证提示?

+0

您是否尝试过将'nil'传递给Stdin? https://golang.org/pkg/os/exec/#Cmd另外请用CommandContext和StdinPipe检查下面的例子。 –

+0

@EugeneLisitsky是通过零没有做任何事情。 golang.org/pkg/os/exec/#Cmd.StdinPipe好像关闭stdinPipe应该保持命令不被阻塞我仍然会被提示输入密码。 – sreya

+0

请发表您的解决方案作为答案,而不是编辑问题请参阅[游览] –

UPDATE:特殊的git解决方案。

由于v 2.3 git支持环境设置GIT_TERMINAL_PROMPT=0,它表示不要求凭据但失败。

func main() { 
    cmd := exec.Command("git", "clone", "https://github.com/some/non-existing-repo") 
    os.Setenv("GIT_SSH_COMMAND", "ssh -oBatchMode=yes") // 
    cmd.Env = append(os.Environ(), "GIT_TERMINAL_PROMPT=1", "GIT_SSH_COMMAND='ssh -oBatchMode=yes'") 

    cmd.Stdout = os.Stdout 
    err := cmd.Run() 
    if err != nil { 
     log.Println("Error: ", err) 
    } 
} 
+0

这很好,唯一的问题是,即使没有提示输入,仍然会调用Read(),所以它在技术上会中止git clone op,即使没有提示输入密码 – sreya

+0

我几乎写了这个答案,但我首先双重检查了文档。这确实不行。我无法想出一个可行的解决方案,但我也没有很努力......(为什么这个标记被接受,如果它不起作用?) –

+0

我检查了 - 是'git'试图读取stdin甚至不需要。所以我们需要一种方法来区分这种情况。 –

SSH解决方法:

接受的答案只会以http克隆工作。如果你想使用ssh的方式来做到这一点下面的工作:

//disables stdin prompts for username/password. If passwordless-ssh isn't configured we want to fail 
os.Setenv("GIT_SSH_COMMAND", "ssh -oBatchMode=yes") 
cmd := exec.Command(name, args...) 
return cmd.CombinedOutput() 

man git条目GIT_SSH_COMMAND

如果这些环境变量的设置,那么git的提取和混帐推将使用 当他们需要连接到远程系统时,使用指定的命令而不是ssh。命令将会给 两个或四个参数:URL中的用户名@主机(或主机)和要在该远程系统上执行的shell命令(可选地,前面加上-p(字面上))和 端口当它指定了默认的SSH端口以外的URL。

$ GIT_SSH_COMMAND优先于$ GIT_SSH,并由shell解释,允许包含 附加参数。另一方面,$ GIT_SSH必须是 程序的路径(如果需要其他参数,它可以是包装程序的外壳脚本)。

通常通过您的个人.ssh/config文件配置任何所需的选项会更容易。 有关更多详细信息,请参阅您的ssh文档。

man git条目GIT_TERMINAL_PROMPT

如果该环境变量被设置为0,git会不在终端上提示(例如,当 要求HTTP认证)。

如何使用git代替原生golang解决方案。这将意味着你的程序不会需要git,你不会有stdin和git二进制文件的问题。从https://godoc.org/gopkg.in/src-d/go-git.v4检出此示例。另外一个好处是文档非常好,这是来自该项目的examples页面。它也支持ssh协议。这是一个git的full comparison vs这个项目。

import (
    "fmt" 
    "os" 

    "gopkg.in/src-d/go-git.v4" 
    . "gopkg.in/src-d/go-git.v4/_examples" 
) 

// Basic example of how to clone a repository using clone options. 
func main() { 
    url := "https://github.com/some/non-existing-repo" 
    directory := "/foo/bar" 

    // Clone the given repository to the given directory 
    Info("git clone %s %s --recursive", url, directory) 

    r, err := git.PlainClone(directory, false, &git.CloneOptions{ 
     URL:    url, 
     RecurseSubmodules: git.DefaultSubmoduleRecursionDepth, 
    }) 

    CheckIfError(err) 

}