github.com/kubeshop/testkube@v1.17.23/cmd/tcl/testworkflow-toolkit/commands/clone.go (about) 1 // Copyright 2024 Testkube. 2 // 3 // Licensed as a Testkube Pro file under the Testkube Community 4 // License (the "License"); you may not use this file except in compliance with 5 // the License. You may obtain a copy of the License at 6 // 7 // https://github.com/kubeshop/testkube/blob/main/licenses/TCL.txt 8 9 package commands 10 11 import ( 12 "fmt" 13 "net/url" 14 "os" 15 "path/filepath" 16 17 "github.com/spf13/cobra" 18 19 "github.com/kubeshop/testkube/pkg/ui" 20 ) 21 22 func NewCloneCmd() *cobra.Command { 23 var ( 24 paths []string 25 username string 26 token string 27 authType string 28 revision string 29 ) 30 31 cmd := &cobra.Command{ 32 Use: "clone <uri> <outputPath>", 33 Short: "Clone the Git repository", 34 Args: cobra.ExactArgs(2), 35 36 Run: func(cmd *cobra.Command, args []string) { 37 uri, err := url.Parse(args[0]) 38 ui.ExitOnError("repository uri", err) 39 outputPath, err := filepath.Abs(args[1]) 40 ui.ExitOnError("output path", err) 41 42 // Disable interactivity 43 os.Setenv("GIT_TERMINAL_PROMPT", "0") 44 45 authArgs := make([]string, 0) 46 47 if authType == "header" { 48 ui.Debug("auth type: header") 49 if token != "" { 50 authArgs = append(authArgs, "-c", fmt.Sprintf("http.extraHeader='%s'", "Authorization: Bearer "+token)) 51 } 52 if username != "" { 53 uri.User = url.User(username) 54 } 55 } else { 56 ui.Debug("auth type: token") 57 if username != "" && token != "" { 58 uri.User = url.UserPassword(username, token) 59 } else if username != "" { 60 uri.User = url.User(username) 61 } else if token != "" { 62 uri.User = url.User(token) 63 } 64 } 65 66 // Mark directory as safe 67 configArgs := []string{"-c", fmt.Sprintf("safe.directory=%s", outputPath), "-c", "advice.detachedHead=false"} 68 69 // Clone repository 70 if len(paths) == 0 { 71 ui.Debug("full checkout") 72 err = Run("git", "clone", configArgs, authArgs, "--depth", 1, "--verbose", uri.String(), outputPath) 73 ui.ExitOnError("cloning repository", err) 74 } else { 75 ui.Debug("sparse checkout") 76 err = Run("git", "clone", configArgs, authArgs, "--filter=blob:none", "--no-checkout", "--sparse", "--depth", 1, "--verbose", uri.String(), outputPath) 77 ui.ExitOnError("cloning repository", err) 78 err = Run("git", "-C", outputPath, configArgs, "sparse-checkout", "set", "--no-cone", paths) 79 ui.ExitOnError("sparse checkout repository", err) 80 if revision != "" { 81 err = Run("git", "-C", outputPath, configArgs, "fetch", authArgs, "--depth", 1, "origin", revision) 82 ui.ExitOnError("fetching revision", err) 83 err = Run("git", "-C", outputPath, configArgs, "checkout", "FETCH_HEAD") 84 ui.ExitOnError("checking out head", err) 85 // TODO: Don't do it for commits 86 err = Run("git", "-C", outputPath, configArgs, "checkout", "-B", revision) 87 ui.ExitOnError("checking out the branch", err) 88 } else { 89 err = Run("git", "-C", outputPath, configArgs, "checkout") 90 ui.ExitOnError("fetching head", err) 91 } 92 } 93 }, 94 } 95 96 cmd.Flags().StringSliceVarP(&paths, "paths", "p", nil, "paths for sparse checkout") 97 cmd.Flags().StringVarP(&username, "username", "u", "", "") 98 cmd.Flags().StringVarP(&token, "token", "t", "", "") 99 cmd.Flags().StringVarP(&authType, "authType", "a", "basic", "allowed: basic, header") 100 cmd.Flags().StringVarP(&revision, "revision", "r", "", "commit hash, branch name or tag") 101 102 return cmd 103 }