github.com/kubeshop/testkube@v1.17.23/pkg/git/checkout.go (about) 1 // TODO consider checkout by some go-git library to limit external deps in docker container 2 // in time writing code "github.com/src-d/go-git" didn't have any filter options 3 // "github.com/go-git/go-git/v5" also 4 package git 5 6 import ( 7 "fmt" 8 "os" 9 "strings" 10 11 "github.com/kubeshop/testkube/pkg/executor/output" 12 "github.com/kubeshop/testkube/pkg/process" 13 ) 14 15 // CheckoutCommit checks out specific commit 16 func CheckoutCommit(uri, authHeader, path, commit, dir string) (err error) { 17 repoDir := dir + "/repo" 18 if err = os.Mkdir(repoDir, 0750); err != nil { 19 return err 20 } 21 22 if _, err = process.ExecuteInDir( 23 repoDir, 24 "git", 25 "init", 26 ); err != nil { 27 return err 28 } 29 30 if _, err = process.ExecuteInDir( 31 repoDir, 32 "git", 33 "remote", 34 "add", 35 "origin", 36 uri, 37 ); err != nil { 38 return err 39 } 40 41 args := []string{} 42 // Appends the HTTP Authorization header to the git clone args to 43 // authenticate using a bearer token. More info: 44 // https://confluence.atlassian.com/bitbucketserver/http-access-tokens-939515499.html 45 if authHeader != "" { 46 args = append(args, "-c", fmt.Sprintf("http.extraHeader='%s'", authHeader)) 47 } 48 49 args = append(args, "fetch", "--depth", "1", "origin", commit) 50 _, err = process.ExecuteInDir( 51 repoDir, 52 "git", 53 args..., 54 ) 55 output.PrintLogf("Git parameters: %s", strings.Join(obfuscateArgs(args, uri, authHeader), " ")) 56 if err != nil { 57 return err 58 } 59 60 if path != "" { 61 if _, err = process.ExecuteInDir( 62 repoDir, 63 "git", 64 "sparse-checkout", 65 "set", 66 path, 67 ); err != nil { 68 return err 69 } 70 } 71 72 if _, err = process.ExecuteInDir( 73 repoDir, 74 "git", 75 "checkout", 76 "FETCH_HEAD", 77 ); err != nil { 78 return err 79 } 80 81 return nil 82 } 83 84 // Checkout will checkout directory from Git repository 85 func Checkout(uri, authHeader, branch, commit, dir string) (outputDir string, err error) { 86 tmpDir := dir 87 if tmpDir == "" { 88 tmpDir, err = os.MkdirTemp("", "git-checkout") 89 if err != nil { 90 return "", err 91 } 92 } 93 94 if commit == "" { 95 args := []string{"clone"} 96 if branch != "" { 97 args = append(args, "-b", branch) 98 } 99 100 // Appends the HTTP Authorization header to the git clone args to 101 // authenticate using a bearer token. More info: 102 // https://confluence.atlassian.com/bitbucketserver/http-access-tokens-939515499.html 103 if authHeader != "" { 104 args = append(args, "-c", fmt.Sprintf("http.extraHeader='%s'", authHeader)) 105 } 106 107 args = append(args, "--depth", "1", uri, "repo") 108 _, err = process.ExecuteInDir( 109 tmpDir, 110 "git", 111 args..., 112 ) 113 output.PrintLogf("Git parameters: %s", strings.Join(obfuscateArgs(args, uri, authHeader), " ")) 114 if err != nil { 115 return "", err 116 } 117 } else { 118 if err = CheckoutCommit(uri, authHeader, "", commit, tmpDir); err != nil { 119 return "", err 120 } 121 } 122 123 return tmpDir + "/repo/", nil 124 } 125 126 // PartialCheckout will checkout only given directory from Git repository 127 func PartialCheckout(uri, authHeader, path, branch, commit, dir string) (outputDir string, err error) { 128 tmpDir := dir 129 if tmpDir == "" { 130 tmpDir, err = os.MkdirTemp("", "git-sparse-checkout") 131 if err != nil { 132 return "", err 133 } 134 } 135 136 if commit == "" { 137 args := []string{"clone"} 138 if branch != "" { 139 args = append(args, "-b", branch) 140 } 141 142 // Appends the HTTP Authorization header to the git clone args to 143 // authenticate using a bearer token. More info: 144 // https://confluence.atlassian.com/bitbucketserver/http-access-tokens-939515499.html 145 if authHeader != "" { 146 args = append(args, "-c", fmt.Sprintf("http.extraHeader='%s'", authHeader)) 147 } 148 149 args = append(args, "--depth", "1", "--filter", "blob:none", "--sparse", uri, "repo") 150 _, err = process.ExecuteInDir( 151 tmpDir, 152 "git", 153 args..., 154 ) 155 output.PrintLogf("Git parameters: %s", strings.Join(obfuscateArgs(args, uri, authHeader), " ")) 156 if err != nil { 157 return "", err 158 } 159 160 _, err = process.ExecuteInDir( 161 tmpDir+"/repo", 162 "git", 163 "sparse-checkout", 164 "set", 165 "--no-cone", 166 path, 167 ) 168 if err != nil { 169 return "", err 170 } 171 } else { 172 if err = CheckoutCommit(uri, authHeader, path, commit, tmpDir); err != nil { 173 return "", err 174 } 175 } 176 177 return tmpDir + "/repo/" + path, nil 178 } 179 180 func obfuscateArgs(args []string, uri, authHeader string) []string { 181 for i := range args { 182 for _, value := range []string{uri, authHeader} { 183 if value != "" { 184 args[i] = strings.ReplaceAll(args[i], value, strings.Repeat("*", len(value))) 185 } 186 } 187 } 188 189 return args 190 }