github.com/zaquestion/lab@v0.25.1/cmd/clone.go (about)

     1  package cmd
     2  
     3  import (
     4  	"strings"
     5  	"time"
     6  
     7  	"github.com/MakeNowJust/heredoc/v2"
     8  	retry "github.com/avast/retry-go"
     9  	"github.com/spf13/cobra"
    10  	"github.com/zaquestion/lab/internal/git"
    11  	"github.com/zaquestion/lab/internal/gitlab"
    12  )
    13  
    14  // cloneCmd represents the clone command
    15  var cloneCmd = &cobra.Command{
    16  	Use:   "clone",
    17  	Short: "GitLab aware clone repo command",
    18  	Long: heredoc.Doc(`
    19  		Clone a repository, similarly to 'git clone', but aware of GitLab
    20  		specific settings.`),
    21  	Example: heredoc.Doc(`
    22  		lab clone awesome-repo
    23  		lab clone company/awesome-repo --http
    24  		lab clone company/backend-team/awesome-repo`),
    25  	PersistentPreRun: labPersistentPreRun,
    26  	Run: func(cmd *cobra.Command, args []string) {
    27  		if len(args) == 0 {
    28  			log.Fatal("You must specify a repository to clone.")
    29  		}
    30  
    31  		useHTTP, err := cmd.Flags().GetBool("http")
    32  		if err != nil {
    33  			log.Fatal(err)
    34  		}
    35  
    36  		if useHTTP {
    37  			args = append(args, []string{"--http"}...)
    38  		}
    39  
    40  		project, err := gitlab.FindProject(args[0])
    41  		if err == gitlab.ErrProjectNotFound {
    42  			err = git.New(append([]string{"clone"}, args...)...).Run()
    43  			if err != nil {
    44  				log.Fatal(err)
    45  			}
    46  			return
    47  		} else if err != nil {
    48  			log.Fatal(err)
    49  		}
    50  		path := labURLToRepo(project)
    51  		// #116 retry on the cases where we found a project but clone
    52  		// failed over ssh
    53  		err = retry.Do(func() error {
    54  			return git.New(append([]string{"clone", path}, args[1:]...)...).Run()
    55  		}, retry.Attempts(3), retry.Delay(time.Second))
    56  		if err != nil {
    57  			log.Fatal(err)
    58  		}
    59  
    60  		// Clone project was a fork belonging to the user; user is
    61  		// treating forks as origin. Add upstream as remoted pointing
    62  		// to forked from repo
    63  		if project.ForkedFromProject != nil &&
    64  			strings.Contains(project.PathWithNamespace, gitlab.User()) {
    65  			var dir string
    66  			if len(args) > 1 {
    67  				dir = args[1]
    68  			} else {
    69  				dir = project.Path
    70  			}
    71  			ffProject, err := gitlab.FindProject(project.ForkedFromProject.PathWithNamespace)
    72  			if err != nil {
    73  				log.Fatal(err)
    74  			}
    75  			urlToRepo := labURLToRepo(ffProject)
    76  			err = git.RemoteAdd("upstream", urlToRepo, "./"+dir)
    77  			if err != nil {
    78  				log.Fatal(err)
    79  			}
    80  		}
    81  	},
    82  }
    83  
    84  func init() {
    85  	// useHTTP is defined in "project_create.go"
    86  	cloneCmd.Flags().BoolVar(&useHTTP, "http", false, "clone using HTTP protocol instead of SSH")
    87  	RootCmd.AddCommand(cloneCmd)
    88  }