github.com/replicatedcom/ship@v0.50.0/pkg/specs/gogetter/go_getter.go (about) 1 package gogetter 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "path" 8 "path/filepath" 9 10 "github.com/go-kit/kit/log" 11 "github.com/go-kit/kit/log/level" 12 getter "github.com/hashicorp/go-getter" 13 "github.com/pkg/errors" 14 "github.com/replicatedhq/ship/pkg/constants" 15 "github.com/replicatedhq/ship/pkg/util" 16 errors2 "github.com/replicatedhq/ship/pkg/util/errors" 17 "github.com/spf13/afero" 18 ) 19 20 type GoGetter struct { 21 Logger log.Logger 22 FS afero.Afero 23 Subdir string 24 IsSingleFile bool 25 } 26 27 // TODO figure out how to copy files from host into afero filesystem for testing, or how to force go-getter to fetch into afero 28 func (g *GoGetter) GetFiles(ctx context.Context, upstream, savePath string) (string, error) { 29 debug := level.Debug(g.Logger) 30 debug.Log("event", "gogetter.GetFiles", "upstream", upstream, "savePath", savePath) 31 32 // Remove the directory because go-getter wants to create it 33 err := g.FS.RemoveAll(savePath) 34 if err != nil { 35 return "", errors.Wrap(err, "remove dir") 36 } 37 38 if g.IsSingleFile { 39 debug.Log("event", "gogetter.getSingleFile", "upstream", upstream, "savePath", savePath) 40 return g.getSingleFile(ctx, upstream, savePath) 41 } 42 43 err = getter.GetAny(savePath, upstream) 44 if err != nil { 45 return "", errors2.FetchFilesError{Message: err.Error()} 46 } 47 48 // check if the upstream is a local file - if it is, we shouldn't remove the .git directory 49 fileDetector := getter.FileDetector{} 50 if _, foundFile, err := fileDetector.Detect(upstream, savePath); !foundFile || err != nil { 51 // if there is a `.git` directory, remove it - it's dynamic and will break the content hash used by `ship update` 52 gitPresent, err := g.FS.Exists(path.Join(savePath, ".git")) 53 if err != nil { 54 return "", errors.Wrap(err, "check for .git directory") 55 } 56 if gitPresent { 57 err := g.FS.RemoveAll(path.Join(savePath, ".git")) 58 if err != nil { 59 return "", errors.Wrap(err, "remove .git directory") 60 } 61 } 62 debug.Log("event", "gitPresent.check", "gitPresent", gitPresent) 63 } 64 65 return filepath.Join(savePath, g.Subdir), nil 66 } 67 68 func (g *GoGetter) getSingleFile(ctx context.Context, upstream, savePath string) (string, error) { 69 tmpDir := filepath.Join(constants.ShipPathInternalTmp, "gogetter-file") 70 71 err := getter.GetAny(tmpDir, upstream) 72 if err != nil { 73 return "", errors2.FetchFilesError{Message: err.Error()} 74 } 75 defer g.FS.RemoveAll(tmpDir) 76 77 err = g.FS.MkdirAll(filepath.Dir(filepath.Join(savePath, g.Subdir)), os.FileMode(0777)) 78 if err != nil { 79 return "", errors.Wrap(err, "make path to move file to") 80 } 81 82 err = g.FS.Rename(filepath.Join(tmpDir, g.Subdir), filepath.Join(savePath, g.Subdir)) 83 if err != nil { 84 return "", errors.Wrap(err, "move downloaded file to destination") 85 } 86 87 return savePath, nil 88 } 89 90 func IsGoGettable(path string) bool { 91 _, err := getter.Detect(path, "", getter.Detectors) 92 if err != nil { 93 return false 94 } 95 return true 96 } 97 98 // if this path is a github path of the form `github.com/OWNER/REPO/tree/REF/SUBDIR` or `github.com/OWNER/REPO/SUBDIR`, 99 // change it to the go-getter form of `github.com/OWNER/REPO?ref=REF//` with a default ref of master and return a subdir of SUBDIR 100 // otherwise return the unmodified path 101 // the final param is whether the github URL is a blob (and thus a single file) 102 func UntreeGithub(path string) (string, string, bool) { 103 githubURL, err := util.ParseGithubURL(path, "master") 104 if err != nil { 105 return path, "", false 106 } 107 return fmt.Sprintf("github.com/%s/%s?ref=%s//", githubURL.Owner, githubURL.Repo, githubURL.Ref), githubURL.Subdir, githubURL.IsBlob 108 } 109 110 func IsShipYaml(path string) bool { 111 base := filepath.Base(path) 112 return base == "ship.yaml" || base == "ship.yml" 113 }