2017-09-27 107 views
2

我試圖在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

請發表您的解決方案作爲答案,而不是編輯問題請參閱[遊覽] –

回答

1

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甚至不需要。所以我們需要一種方法來區分這種情況。 –

0

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認證)。

1

如何使用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) 

}