github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/gist/clone/clone.go (about)

     1  package clone
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/http"
     7  
     8  	"github.com/MakeNowJust/heredoc"
     9  	"github.com/ungtb10d/cli/v2/git"
    10  	"github.com/ungtb10d/cli/v2/internal/config"
    11  	"github.com/ungtb10d/cli/v2/internal/ghinstance"
    12  	"github.com/ungtb10d/cli/v2/pkg/cmdutil"
    13  	"github.com/ungtb10d/cli/v2/pkg/iostreams"
    14  	"github.com/spf13/cobra"
    15  	"github.com/spf13/pflag"
    16  )
    17  
    18  type CloneOptions struct {
    19  	HttpClient func() (*http.Client, error)
    20  	GitClient  *git.Client
    21  	Config     func() (config.Config, error)
    22  	IO         *iostreams.IOStreams
    23  
    24  	GitArgs   []string
    25  	Directory string
    26  	Gist      string
    27  }
    28  
    29  func NewCmdClone(f *cmdutil.Factory, runF func(*CloneOptions) error) *cobra.Command {
    30  	opts := &CloneOptions{
    31  		IO:         f.IOStreams,
    32  		HttpClient: f.HttpClient,
    33  		GitClient:  f.GitClient,
    34  		Config:     f.Config,
    35  	}
    36  
    37  	cmd := &cobra.Command{
    38  		DisableFlagsInUseLine: true,
    39  
    40  		Use:   "clone <gist> [<directory>] [-- <gitflags>...]",
    41  		Args:  cmdutil.MinimumArgs(1, "cannot clone: gist argument required"),
    42  		Short: "Clone a gist locally",
    43  		Long: heredoc.Doc(`
    44  			Clone a GitHub gist locally.
    45  
    46  			A gist can be supplied as argument in either of the following formats:
    47  			- by ID, e.g. 5b0e0062eb8e9654adad7bb1d81cc75f
    48  			- by URL, e.g. "https://gist.github.com/OWNER/5b0e0062eb8e9654adad7bb1d81cc75f"
    49  
    50  			Pass additional 'git clone' flags by listing them after '--'.
    51  		`),
    52  		RunE: func(cmd *cobra.Command, args []string) error {
    53  			opts.Gist = args[0]
    54  			opts.GitArgs = args[1:]
    55  
    56  			if runF != nil {
    57  				return runF(opts)
    58  			}
    59  
    60  			return cloneRun(opts)
    61  		},
    62  	}
    63  
    64  	cmd.SetFlagErrorFunc(func(cmd *cobra.Command, err error) error {
    65  		if err == pflag.ErrHelp {
    66  			return err
    67  		}
    68  		return cmdutil.FlagErrorf("%w\nSeparate git clone flags with '--'.", err)
    69  	})
    70  
    71  	return cmd
    72  }
    73  
    74  func cloneRun(opts *CloneOptions) error {
    75  	gistURL := opts.Gist
    76  
    77  	if !git.IsURL(gistURL) {
    78  		cfg, err := opts.Config()
    79  		if err != nil {
    80  			return err
    81  		}
    82  		hostname, _ := cfg.DefaultHost()
    83  		protocol, err := cfg.GetOrDefault(hostname, "git_protocol")
    84  		if err != nil {
    85  			return err
    86  		}
    87  		gistURL = formatRemoteURL(hostname, gistURL, protocol)
    88  	}
    89  
    90  	_, err := opts.GitClient.Clone(context.Background(), gistURL, opts.GitArgs)
    91  	if err != nil {
    92  		return err
    93  	}
    94  
    95  	return nil
    96  }
    97  
    98  func formatRemoteURL(hostname string, gistID string, protocol string) string {
    99  	if ghinstance.IsEnterprise(hostname) {
   100  		if protocol == "ssh" {
   101  			return fmt.Sprintf("git@%s:gist/%s.git", hostname, gistID)
   102  		}
   103  		return fmt.Sprintf("https://%s/gist/%s.git", hostname, gistID)
   104  	}
   105  
   106  	if protocol == "ssh" {
   107  		return fmt.Sprintf("git@gist.%s:%s.git", hostname, gistID)
   108  	}
   109  	return fmt.Sprintf("https://gist.%s/%s.git", hostname, gistID)
   110  }