cli/pkg/cmd/auth/setupgit/setupgit.go
Des Preston 94a640bd2a
Add auth setup-git for setting up gh as a git credential helper (#4246)
Adds a new command `gh auth setup-git [<hostname>]` that sets up git to
use the GitHub CLI as a credential helper.

The gist is that it runs these two git commands for each hostname the
user is authenticated with.

```
git config --global --replace-all 'credential.https://github.com.helper' ''
git config --global --add 'credential.https://github.com.helper' '!gh auth git-credential'
```

If a hostname flag is given, it'll setup GH CLI as a credential helper
for only that hostname.

If the user is not authenticated with any git hostnames, or the user is
not authenticated with the hostname given as a flag, it'll print an
error.

Co-authored-by: Mislav Marohnić <mislav@github.com>
2021-12-02 16:38:34 +00:00

100 lines
2.1 KiB
Go

package setupgit
import (
"fmt"
"strings"
"github.com/cli/cli/v2/internal/config"
"github.com/cli/cli/v2/pkg/cmd/auth/shared"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/cli/cli/v2/pkg/iostreams"
"github.com/spf13/cobra"
)
type gitConfigurator interface {
Setup(hostname, username, authToken string) error
}
type SetupGitOptions struct {
IO *iostreams.IOStreams
Config func() (config.Config, error)
Hostname string
gitConfigure gitConfigurator
}
func NewCmdSetupGit(f *cmdutil.Factory, runF func(*SetupGitOptions) error) *cobra.Command {
opts := &SetupGitOptions{
IO: f.IOStreams,
Config: f.Config,
}
cmd := &cobra.Command{
Short: "Configure git to use GitHub CLI as a credential helper",
Use: "setup-git",
RunE: func(cmd *cobra.Command, args []string) error {
opts.gitConfigure = &shared.GitCredentialFlow{
Executable: f.Executable(),
}
if runF != nil {
return runF(opts)
}
return setupGitRun(opts)
},
}
cmd.Flags().StringVarP(&opts.Hostname, "hostname", "h", "", "The hostname to configure git for")
return cmd
}
func setupGitRun(opts *SetupGitOptions) error {
cfg, err := opts.Config()
if err != nil {
return err
}
hostnames, err := cfg.Hosts()
if err != nil {
return err
}
stderr := opts.IO.ErrOut
cs := opts.IO.ColorScheme()
if len(hostnames) == 0 {
fmt.Fprintf(
stderr,
"You are not logged into any GitHub hosts. Run %s to authenticate.\n",
cs.Bold("gh auth login"),
)
return cmdutil.SilentError
}
hostnamesToSetup := hostnames
if opts.Hostname != "" {
if !has(opts.Hostname, hostnames) {
return fmt.Errorf("You are not logged into the GitHub host %q\n", opts.Hostname)
}
hostnamesToSetup = []string{opts.Hostname}
}
for _, hostname := range hostnamesToSetup {
if err := opts.gitConfigure.Setup(hostname, "", ""); err != nil {
return fmt.Errorf("failed to set up git credential helper: %w", err)
}
}
return nil
}
func has(needle string, haystack []string) bool {
for _, s := range haystack {
if strings.EqualFold(s, needle) {
return true
}
}
return false
}