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  }