89 lines
3.1 KiB
Go
89 lines
3.1 KiB
Go
package shared
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/cli/cli/v2/git"
|
|
"github.com/cli/cli/v2/pkg/cmd/auth/shared/gitcredentials"
|
|
)
|
|
|
|
type HelperConfig interface {
|
|
ConfigureOurs(hostname string) error
|
|
ConfiguredHelper(hostname string) (gitcredentials.Helper, error)
|
|
}
|
|
|
|
type GitCredentialFlow struct {
|
|
Prompter Prompt
|
|
|
|
HelperConfig HelperConfig
|
|
Updater *gitcredentials.Updater
|
|
|
|
shouldSetup bool
|
|
helper gitcredentials.Helper
|
|
scopes []string
|
|
}
|
|
|
|
func (flow *GitCredentialFlow) Prompt(hostname string) error {
|
|
// First we'll fetch the credential helper that would be used for this host
|
|
var configuredHelperErr error
|
|
flow.helper, configuredHelperErr = flow.HelperConfig.ConfiguredHelper(hostname)
|
|
// If the helper is gh itself, then we don't need to ask the user if they want to update their git credentials
|
|
// because it will happen automatically by virtue of the fact that gh will return the active token.
|
|
//
|
|
// Since gh is the helper, this token may be used for git operations, so we'll additionally request the workflow
|
|
// scope to ensure that git push operations that include workflow changes succeed.
|
|
if flow.helper.IsOurs() {
|
|
flow.scopes = append(flow.scopes, "workflow")
|
|
return nil
|
|
}
|
|
|
|
// Prompt the user for whether they want to configure git with the newly obtained token
|
|
result, err := flow.Prompter.Confirm("Authenticate Git with your GitHub credentials?", true)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
flow.shouldSetup = result
|
|
|
|
if flow.shouldSetup {
|
|
// If the user does want to configure git, we'll check the error returned from fetching the configured helper
|
|
// above. If the error indicates that git isn't installed, we'll return an error now to ensure that the auth
|
|
// flow is aborted before the user goes any further.
|
|
//
|
|
// Note that this is _slightly_ naive because there may be other reasons that fetching the configured helper
|
|
// fails that might cause later failures but this code has existed for a long time and I don't want to change
|
|
// it as part of a refactoring.
|
|
//
|
|
// Refs:
|
|
// * https://git-scm.com/docs/git-config#_description
|
|
// * https://github.com/cli/cli/pull/4109
|
|
var errNotInstalled *git.NotInstalled
|
|
if errors.As(configuredHelperErr, &errNotInstalled) {
|
|
return configuredHelperErr
|
|
}
|
|
|
|
// On the other hand, if the user has requested setup we'll additionally request the workflow
|
|
// scope to ensure that git push operations that include workflow changes succeed.
|
|
flow.scopes = append(flow.scopes, "workflow")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (flow *GitCredentialFlow) Scopes() []string {
|
|
return flow.scopes
|
|
}
|
|
|
|
func (flow *GitCredentialFlow) ShouldSetup() bool {
|
|
return flow.shouldSetup
|
|
}
|
|
|
|
func (flow *GitCredentialFlow) Setup(hostname, username, authToken string) error {
|
|
// If there is no credential helper configured then we will set ourselves up as
|
|
// the credential helper for this host.
|
|
if !flow.helper.IsConfigured() {
|
|
return flow.HelperConfig.ConfigureOurs(hostname)
|
|
}
|
|
|
|
// Otherwise, we'll tell git to inform the existing credential helper of the new credentials.
|
|
return flow.Updater.Update(hostname, username, authToken)
|
|
}
|