github.com/jenkins-x/jx/v2@v2.1.155/pkg/gits/credentialhelper/git_credentialhelper.go (about) 1 package credentialhelper 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 8 "github.com/pkg/errors" 9 ) 10 11 // GitCredentialsHelper is used to implement the git credential helper algorithm. 12 // See also https://git-scm.com/docs/git-credential. 13 type GitCredentialsHelper struct { 14 in io.Reader 15 out io.Writer 16 knownCredentials []GitCredential 17 } 18 19 // CreateGitCredentialsHelper creates an instance of a git credential helper. It needs to get passed the handles to read 20 // the git credential data as well as write the response to. It also gets the list og known credentials. 21 func CreateGitCredentialsHelper(in io.Reader, out io.Writer, credentials []GitCredential) (*GitCredentialsHelper, error) { 22 if in == nil { 23 return nil, errors.New("in parameter cannot be nil") 24 } 25 26 if out == nil { 27 return nil, errors.New("out parameter cannot be nil") 28 } 29 30 if credentials == nil { 31 return nil, errors.New("credentials parameter cannot be nil") 32 } 33 34 return &GitCredentialsHelper{ 35 in: in, 36 out: out, 37 knownCredentials: credentials, 38 }, nil 39 } 40 41 // Run executes the specified git credential helper operation which must be one of get, store or erase. 42 // NOTE: Currently only get is implemented. 43 func (h *GitCredentialsHelper) Run(op string) error { 44 var err error 45 46 switch op { 47 case "get": 48 err = h.Get() 49 case "store": 50 // not yet implemented (HF) 51 fmt.Println("") 52 case "erase": 53 // not yet implemented (HF) 54 fmt.Println("") 55 default: 56 err = errors.Errorf("invalid git credential operation '%s'", op) 57 } 58 59 return err 60 } 61 62 // Get implements the get operation of the git credential helper protocol. It reads the authentication query from 63 // the reader of this instance and writes the response to the writer (usually this will be stdout and stdin). 64 func (h *GitCredentialsHelper) Get() error { 65 var data []string 66 scanner := bufio.NewScanner(h.in) 67 for scanner.Scan() { 68 data = append(data, scanner.Text()) 69 } 70 71 if scanner.Err() != nil { 72 return errors.Wrap(scanner.Err(), "unable to read input from stdin") 73 } 74 75 gitCredential, err := CreateGitCredential(data) 76 if err != nil { 77 return errors.Wrap(scanner.Err(), "unable to create GitCredential struct") 78 } 79 80 answer := h.Fill(gitCredential) 81 82 _, err = fmt.Fprintf(h.out, answer.String()) 83 if err != nil { 84 return errors.Wrap(err, "unable to write response to stdin") 85 } 86 87 return nil 88 } 89 90 // Fill creates a GitCredential instance based on a git credential helper request which represented by the passed queryCredential instance. 91 // If there is no auth information available an empty credential instance is returned 92 func (h *GitCredentialsHelper) Fill(queryCredential GitCredential) GitCredential { 93 for _, authCredential := range h.knownCredentials { 94 if queryCredential.Protocol != authCredential.Protocol { 95 continue 96 } 97 98 if queryCredential.Host != authCredential.Host { 99 continue 100 } 101 102 if queryCredential.Path != authCredential.Path { 103 continue 104 } 105 106 answer := authCredential.Clone() 107 return answer 108 } 109 110 return GitCredential{} 111 }