forked from cli/cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgit_credential.go
More file actions
126 lines (104 loc) · 2.72 KB
/
git_credential.go
File metadata and controls
126 lines (104 loc) · 2.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package shared
import (
"bytes"
"fmt"
"path/filepath"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/MakeNowJust/heredoc"
"github.com/cli/cli/git"
"github.com/cli/cli/internal/run"
"github.com/cli/cli/pkg/prompt"
"github.com/google/shlex"
)
type GitCredentialFlow struct {
shouldSetup bool
helper string
scopes []string
}
func (flow *GitCredentialFlow) Prompt(hostname string) error {
flow.helper, _ = gitCredentialHelper(hostname)
if isOurCredentialHelper(flow.helper) {
flow.scopes = append(flow.scopes, "workflow")
return nil
}
err := prompt.SurveyAskOne(&survey.Confirm{
Message: "Authenticate Git with your GitHub credentials?",
Default: true,
}, &flow.shouldSetup)
if err != nil {
return fmt.Errorf("could not prompt: %w", err)
}
if flow.shouldSetup {
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 {
return GitCredentialSetup(hostname, username, authToken, flow.helper)
}
func GitCredentialSetup(hostname, username, password, helper string) error {
if helper == "" {
// use GitHub CLI as a credential helper (for this host only)
configureCmd, err := git.GitCommand("config", "--global", gitCredentialHelperKey(hostname), "!gh auth git-credential")
if err != nil {
return err
}
return run.PrepareCmd(configureCmd).Run()
}
// clear previous cached credentials
rejectCmd, err := git.GitCommand("credential", "reject")
if err != nil {
return err
}
rejectCmd.Stdin = bytes.NewBufferString(heredoc.Docf(`
protocol=https
host=%s
`, hostname))
err = run.PrepareCmd(rejectCmd).Run()
if err != nil {
return err
}
approveCmd, err := git.GitCommand("credential", "approve")
if err != nil {
return err
}
approveCmd.Stdin = bytes.NewBufferString(heredoc.Docf(`
protocol=https
host=%s
username=%s
password=%s
`, hostname, username, password))
err = run.PrepareCmd(approveCmd).Run()
if err != nil {
return err
}
return nil
}
func gitCredentialHelperKey(hostname string) string {
return fmt.Sprintf("credential.https://%s.helper", hostname)
}
func gitCredentialHelper(hostname string) (helper string, err error) {
helper, err = git.Config(gitCredentialHelperKey(hostname))
if helper != "" {
return
}
helper, err = git.Config("credential.helper")
return
}
func isOurCredentialHelper(cmd string) bool {
if !strings.HasPrefix(cmd, "!") {
return false
}
args, err := shlex.Split(cmd[1:])
if err != nil || len(args) == 0 {
return false
}
return strings.TrimSuffix(filepath.Base(args[0]), ".exe") == "gh"
}