github.com/adevinta/maiao@v0.0.0-20240318133227-b6f9656b5e07/pkg/credentials/git.go (about) 1 package credentials 2 3 import ( 4 "bytes" 5 "errors" 6 "os/exec" 7 "strings" 8 ) 9 10 var run = realRun 11 12 type runOpts struct { 13 path string 14 args []string 15 stdin string 16 } 17 18 func realRun(opts runOpts) (string, error) { 19 cmd := exec.Command(opts.path, opts.args...) 20 b := bytes.Buffer{} 21 cmd.Stdout = &b 22 if opts.stdin != "" { 23 cmd.Stdin = strings.NewReader(opts.stdin) 24 } 25 return b.String(), nil 26 } 27 28 type GitCredentials struct { 29 GitPath string 30 } 31 32 func (c *GitCredentials) CredentialForHost(host string) (*Credentials, error) { 33 // this should be better included with the actual git remotes. 34 out, err := run(runOpts{path: c.GitPath, args: []string{"credential", "fill"}, stdin: "protocol=https\nhost=" + host}) 35 if err != nil { 36 return nil, err 37 } 38 if out != "" { 39 kv := map[string]string{} 40 for _, line := range strings.Split(out, "\n") { 41 keyAndValue := strings.SplitN(line, "=", 2) 42 if len(keyAndValue) == 2 { 43 kv[strings.TrimSpace(keyAndValue[0])] = strings.TrimSuffix(keyAndValue[1], "\n") 44 } 45 } 46 if _, ok := kv["password"]; ok { 47 return &Credentials{Username: kv["username"], Password: kv["password"]}, nil 48 } 49 return nil, errors.New("unable to find username and password from git credential") 50 } 51 return nil, errors.New("not found") 52 }