-
Notifications
You must be signed in to change notification settings - Fork 787
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Handling git credentials via credential helper
fixes #5772
- Loading branch information
1 parent
9345f7f
commit ec9a6bf
Showing
13 changed files
with
677 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package credentialhelper | ||
|
||
import ( | ||
"fmt" | ||
"net/url" | ||
"reflect" | ||
"strings" | ||
|
||
"github.com/jenkins-x/jx/pkg/util" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
// GitCredential represents the different parts of a git credential URL | ||
// See also https://git-scm.com/docs/git-credential | ||
type GitCredential struct { | ||
Protocol string | ||
Host string | ||
Path string | ||
Username string | ||
Password string | ||
} | ||
|
||
// CreateGitCredential creates a CreateGitCredential instance from a slice of strings where each element is a key/value pair | ||
// separated by '='. | ||
func CreateGitCredential(lines []string) (GitCredential, error) { | ||
var credential GitCredential | ||
|
||
if lines == nil { | ||
return credential, errors.New("no data lines provided") | ||
} | ||
|
||
fieldMap, err := util.ExtractKeyValuePairs(lines, "=") | ||
if err != nil { | ||
return credential, errors.Wrap(err, "unable to extract git credential parameters") | ||
} | ||
for key, value := range fieldMap { | ||
v := reflect.ValueOf(&credential).Elem().FieldByName(strings.Title(key)) | ||
if v.IsValid() { | ||
v.SetString(value) | ||
} else { | ||
return GitCredential{}, errors.Errorf("invalid key/value %s/%s", key, value) | ||
} | ||
} | ||
|
||
return credential, nil | ||
} | ||
|
||
// CreateGitCredentialFromURL creates a CreateGitCredential instance from a URL and optional username and password. | ||
func CreateGitCredentialFromURL(gitURL string, username string, password string) (GitCredential, error) { | ||
var credential GitCredential | ||
|
||
if gitURL == "" { | ||
return credential, errors.New("url cannot be empty") | ||
} | ||
|
||
u, err := url.Parse(gitURL) | ||
if err != nil { | ||
return credential, errors.Wrapf(err, "unable to parse URL %s", gitURL) | ||
} | ||
|
||
credential.Protocol = u.Scheme | ||
credential.Host = u.Host | ||
credential.Path = u.Path | ||
if username != "" { | ||
credential.Username = username | ||
} | ||
|
||
if password != "" { | ||
credential.Password = password | ||
} | ||
|
||
return credential, nil | ||
} | ||
|
||
// String returns a string representation of this instance according to the expected format of git credential helpers. | ||
// See also https://git-scm.com/docs/git-credential | ||
func (g *GitCredential) String() string { | ||
answer := "" | ||
|
||
value := reflect.ValueOf(g).Elem() | ||
typeOfT := value.Type() | ||
|
||
for i := 0; i < value.NumField(); i++ { | ||
field := value.Field(i) | ||
answer = answer + fmt.Sprintf("%s=%v\n", strings.ToLower(typeOfT.Field(i).Name), field.Interface()) | ||
} | ||
|
||
answer = answer + "\n" | ||
|
||
return answer | ||
} | ||
|
||
// Clones this GitCredential instance | ||
func (g *GitCredential) Clone() GitCredential { | ||
clone := GitCredential{} | ||
|
||
value := reflect.ValueOf(g).Elem() | ||
typeOfT := value.Type() | ||
for i := 0; i < value.NumField(); i++ { | ||
field := value.Field(i) | ||
value := field.String() | ||
v := reflect.ValueOf(&clone).Elem().FieldByName(typeOfT.Field(i).Name) | ||
v.SetString(value) | ||
} | ||
|
||
return clone | ||
} | ||
|
||
// URL returns a URL from the data of this instance. If not enough information exist an error is returned | ||
func (g *GitCredential) URL() (url.URL, error) { | ||
urlAsString := g.Protocol + "://" + g.Host | ||
if g.Path != "" { | ||
urlAsString = urlAsString + "/" + g.Path | ||
} | ||
u, err := url.Parse(urlAsString) | ||
if err != nil { | ||
return url.URL{}, errors.Wrap(err, "unable to construct URL") | ||
} | ||
|
||
u.User = url.UserPassword(g.Username, g.Password) | ||
return *u, nil | ||
} |
Oops, something went wrong.