github.com/gfleury/gobbs@v0.0.0-20200831213239-44ca2b94c1a1/repos/clone.go (about) 1 package repos 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "net" 8 "net/http" 9 "os" 10 11 "github.com/gfleury/gobbs/common" 12 "github.com/gfleury/gobbs/common/log" 13 14 bitbucketv1 "github.com/gfleury/go-bitbucket-v1" 15 "github.com/spf13/cobra" 16 "gopkg.in/src-d/go-git.v4" 17 "gopkg.in/src-d/go-git.v4/plumbing/transport/ssh" 18 ) 19 20 // Clone is the cmd implementation for Cloning repositories locally 21 var Clone = &cobra.Command{ 22 Use: "clone repoName", 23 Aliases: []string{"cl"}, 24 Short: "Clone repository", 25 Args: cobra.MinimumNArgs(1), 26 RunE: func(cmd *cobra.Command, args []string) error { 27 apiClient, cancel, err := common.APIClient(cmd) 28 defer cancel() 29 30 if err != nil { 31 cmd.SilenceUsage = true 32 return err 33 } 34 35 stashInfo := cmd.Context().Value(common.StashInfoKey).(*common.StashInfo) 36 err = mustHaveProject(stashInfo) 37 if err != nil { 38 return err 39 } 40 41 response, err := apiClient.DefaultApi.GetRepository(*stashInfo.Project(), args[0]) 42 43 if netError, ok := err.(net.Error); (!ok || (ok && !netError.Timeout())) && 44 !errors.Is(err, context.Canceled) && 45 !errors.Is(err, context.DeadlineExceeded) && 46 response != nil && response.Response != nil && 47 response.Response.StatusCode >= http.StatusMultipleChoices { 48 common.PrintApiError(response.Values) 49 cmd.SilenceUsage = true 50 log.Debugf(err.Error()) 51 return fmt.Errorf("Unable to process request, API Error") 52 } else if err != nil { 53 cmd.SilenceUsage = true 54 return err 55 } 56 57 repo, err := bitbucketv1.GetRepositoryResponse(response) 58 if err != nil { 59 cmd.SilenceUsage = true 60 return err 61 } 62 63 if len(repo.Links.Clone) < 1 { 64 cmd.SilenceUsage = true 65 return fmt.Errorf("Can't find a clonable link for the repository.") 66 } 67 68 homeDir, err := os.UserHomeDir() 69 if err != nil { 70 return err 71 } 72 73 authSSH, err := ssh.NewPublicKeysFromFile("git", fmt.Sprintf("%s/.ssh/id_rsa", homeDir), "") 74 if err != nil { 75 return err 76 } 77 78 for _, link := range repo.Links.Clone { 79 if link.Name == "ssh" { 80 _, err = git.PlainClone(args[0], false, &git.CloneOptions{ 81 URL: link.Href, 82 RecurseSubmodules: git.DefaultSubmoduleRecursionDepth, 83 Auth: authSSH, 84 }) 85 break 86 } 87 } 88 89 if err != nil { 90 return err 91 } 92 93 log.Noticef("Repository successfully cloned into %s", args[0]) 94 return err 95 }, 96 }