From c98b5b2a0b935be5662e5475d331bdc12bd18b44 Mon Sep 17 00:00:00 2001 From: Carolyn Van Slyck Date: Fri, 8 Apr 2022 15:01:08 -0500 Subject: [PATCH] Support downloading to an arbitrary location This adds downloads.Download, which you can use in place of downloads.DownloadToGopathBin to install a tool into a local tools or bin directory. Signed-off-by: Carolyn Van Slyck --- pkg/downloads/download.go | 22 +++++++------ pkg/downloads/download_test.go | 58 +++++++++++++++++++++++++++++----- 2 files changed, 63 insertions(+), 17 deletions(-) diff --git a/pkg/downloads/download.go b/pkg/downloads/download.go index fa91c73..0707792 100644 --- a/pkg/downloads/download.go +++ b/pkg/downloads/download.go @@ -20,7 +20,7 @@ import ( // PostDownloadHook is the handler called after downloading a file, which returns the absolute path to the binary. type PostDownloadHook func(archivePath string) (string, error) -// DownloadOptions +// DownloadOptions is the configuration settings used to download a file. type DownloadOptions struct { // UrlTemplate is the Go template for the URL to download. Required. // Available Template Variables: @@ -60,16 +60,20 @@ type DownloadOptions struct { // - {{.EXT}} // - {{.VERSION}} func DownloadToGopathBin(opts DownloadOptions) error { - src, err := RenderTemplate(opts.UrlTemplate, opts) - if err != nil { + + if err := gopath.EnsureGopathBin(); err != nil { return err } - log.Printf("Downloading %s...", src) + bin := gopath.GetGopathBin() + return Download(bin, opts) +} - err = gopath.EnsureGopathBin() +func Download(destDir string, opts DownloadOptions) error { + src, err := RenderTemplate(opts.UrlTemplate, opts) if err != nil { return err } + log.Printf("Downloading %s...", src) // Download to a temp file tmpDir, err := ioutil.TempDir("", "magex") @@ -116,10 +120,10 @@ func DownloadToGopathBin(opts DownloadOptions) error { return fmt.Errorf("could not make %s executable: %w", tmpBin, err) } - // Move it to GOPATH/bin - dest := filepath.Join(gopath.GetGopathBin(), opts.Name+xplat.FileExt()) - if err := shx.Copy(tmpBin, dest); err != nil { - return fmt.Errorf("error copying %s to %s: %w", tmpBin, dest, err) + // Move it to the destination + destPath := filepath.Join(destDir, opts.Name+xplat.FileExt()) + if err := shx.Copy(tmpBin, destPath); err != nil { + return fmt.Errorf("error copying %s to %s: %w", tmpBin, destPath, err) } return nil } diff --git a/pkg/downloads/download_test.go b/pkg/downloads/download_test.go index f73729c..5933fea 100644 --- a/pkg/downloads/download_test.go +++ b/pkg/downloads/download_test.go @@ -1,27 +1,69 @@ package downloads import ( + "github.com/carolynvs/magex/pkg/gopath" + "github.com/carolynvs/magex/xplat" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "io/ioutil" "net/http" "net/http/httptest" + "os" + "path/filepath" "testing" ) func TestDownloadToGopathBin(t *testing.T) { + err, cleanup := gopath.UseTempGopath() + require.NoError(t, err, "Failed to set up a temporary GOPATH") + defer cleanup() + + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("echo ok")) + })) + defer svr.Close() + + opts := DownloadOptions{ + UrlTemplate: svr.URL, + Name: "mybin", + } + err = DownloadToGopathBin(opts) + require.NoError(t, err) + assert.FileExists(t, filepath.Join(gopath.GetGopathBin(), "mybin"+xplat.FileExt())) +} + +func TestDownload(t *testing.T) { t.Run("not found", func(t *testing.T) { svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(404) })) defer svr.Close() - t.Run("not found", func(t *testing.T) { - opts := DownloadOptions{ - UrlTemplate: svr.URL, - } - err := DownloadToGopathBin(opts) - require.Error(t, err) - assert.Contains(t, err.Error(), "404 Not Found") - }) + opts := DownloadOptions{ + UrlTemplate: svr.URL, + Name: "mybin", + } + err := Download("bin", opts) + require.Error(t, err) + assert.Contains(t, err.Error(), "404 Not Found") + }) + + t.Run("found", func(t *testing.T) { + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("echo ok")) + })) + defer svr.Close() + + dest, err := ioutil.TempDir("", "magex") + require.NoError(t, err) + defer os.RemoveAll(dest) + + opts := DownloadOptions{ + UrlTemplate: svr.URL, + Name: "mybin", + } + err = Download(dest, opts) + require.NoError(t, err) + assert.FileExists(t, filepath.Join(dest, "mybin"+xplat.FileExt())) }) }