From 00144a6ef1d206e669522c6e079c552d01446c82 Mon Sep 17 00:00:00 2001 From: Will Roden <willabides@github.com> Date: Sat, 23 Nov 2019 13:01:05 -0600 Subject: [PATCH 1/3] add ArchivePath and Link to download config --- downloader.go | 75 ++++++++-------- downloader_test.go | 109 ++++++++++++++++++++++-- testdata/downloadables/fooinroot.tar.gz | Bin 0 -> 179 bytes testdata/downloadables/rawfile/foo | 3 + testhelper_test.go | 4 +- 5 files changed, 142 insertions(+), 49 deletions(-) create mode 100644 testdata/downloadables/fooinroot.tar.gz create mode 100644 testdata/downloadables/rawfile/foo diff --git a/downloader.go b/downloader.go index 15e002dd..8edad8ba 100644 --- a/downloader.go +++ b/downloader.go @@ -16,13 +16,15 @@ import ( // Downloader downloads a binary type Downloader struct { - URL string `json:"url"` - Checksum string `json:"checksum"` - LinkSource string `json:"symlink,omitempty"` - BinName string `json:"bin"` - MoveFrom string `json:"move-from"` - OS string `json:"os"` - Arch string `json:"arch"` + URL string `json:"url"` + Checksum string `json:"checksum"` + LinkSource string `json:"symlink,omitempty"` + BinName string `json:"bin"` + MoveFrom string `json:"move-from"` + ArchivePath string `json:"archive_path"` + Link bool `json:"link"` + OS string `json:"os"` + Arch string `json:"arch"` } func (d *Downloader) downloadableName() (string, error) { @@ -49,45 +51,46 @@ func (d *Downloader) chmod(targetDir string) error { return os.Chmod(d.binPath(targetDir), 0755) //nolint:gosec } -func (d *Downloader) move(targetDir, extractDir string) error { - if d.MoveFrom == "" { - return nil +func (d *Downloader) moveOrLinkBin(targetDir, extractDir string) error { + if d.LinkSource != "" { + d.ArchivePath = d.LinkSource + d.Link = true } - err := rm(d.binPath(targetDir)) - if err != nil { - return err + if d.MoveFrom != "" { + d.ArchivePath = d.MoveFrom } - from := filepath.Join(extractDir, filepath.FromSlash(d.MoveFrom)) - to := d.binPath(targetDir) - return os.Rename(from, to) -} - -func (d *Downloader) link(targetDir, extractDir string) error { - if d.LinkSource == "" { - return nil + archivePath := filepath.FromSlash(d.ArchivePath) + if archivePath == "" { + archivePath = filepath.FromSlash(d.BinName) } var err error - if fileExists(d.binPath(targetDir)) { - err = rm(d.binPath(targetDir)) + target := d.binPath(targetDir) + if fileExists(target) { + err = rm(target) if err != nil { return err } } + extractDir, err = filepath.Abs(extractDir) if err != nil { return err } - target := d.binPath(targetDir) - targetDir, err = filepath.Abs(filepath.Dir(target)) - if err != nil { - return err - } + extractedBin := filepath.Join(extractDir, archivePath) - dst, err := filepath.Rel(targetDir, filepath.Join(extractDir, filepath.FromSlash(d.LinkSource))) - if err != nil { - return err + if d.Link { + targetDir, err = filepath.Abs(filepath.Dir(target)) + if err != nil { + return err + } + + dst, err := filepath.Rel(targetDir, extractedBin) + if err != nil { + return err + } + return os.Symlink(dst, target) } - return os.Symlink(dst, d.binPath(targetDir)) + return os.Rename(extractedBin, target) } func (d *Downloader) extract(downloadDir, extractDir string) error { @@ -206,13 +209,7 @@ func (d *Downloader) Install(opts InstallOpts) error { return err } - err = d.link(opts.TargetDir, extractDir) - if err != nil { - log.Printf("error linking: %v", err) - return err - } - - err = d.move(opts.TargetDir, extractDir) + err = d.moveOrLinkBin(opts.TargetDir, extractDir) if err != nil { log.Printf("error moving: %v", err) return err diff --git a/downloader_test.go b/downloader_test.go index 23c408b4..599623ce 100644 --- a/downloader_test.go +++ b/downloader_test.go @@ -19,16 +19,16 @@ func Test_downloadFile(t *testing.T) { t.Run("success", func(t *testing.T) { dir, teardown := tmpDir(t) defer teardown() - ts := serveFile(fooPath, "/foo/foo.tar.gz", "") + ts := serveFile(downloadablesPath("foo.tar.gz"), "/foo/foo.tar.gz", "") err := downloadFile(filepath.Join(dir, "bar.tar.gz"), ts.URL+"/foo/foo.tar.gz") assert.NoError(t, err) - assertEqualFiles(t, fooPath, filepath.Join(dir, "bar.tar.gz")) + assertEqualFiles(t, downloadablesPath("foo.tar.gz"), filepath.Join(dir, "bar.tar.gz")) }) t.Run("404", func(t *testing.T) { dir, teardown := tmpDir(t) defer teardown() - ts := serveFile(fooPath, "/foo/foo.tar.gz", "") + ts := serveFile(downloadablesPath("foo.tar.gz"), "/foo/foo.tar.gz", "") err := downloadFile(filepath.Join(dir, "bar.tar.gz"), ts.URL+"/wrongpath") assert.Error(t, err) }) @@ -43,7 +43,7 @@ func Test_downloadFile(t *testing.T) { t.Run("bad target", func(t *testing.T) { dir, teardown := tmpDir(t) defer teardown() - ts := serveFile(fooPath, "/foo/foo.tar.gz", "") + ts := serveFile(downloadablesPath("foo.tar.gz"), "/foo/foo.tar.gz", "") err := downloadFile(filepath.Join(dir, "notreal", "bar.tar.gz"), ts.URL+"/foo/foo.tar.gz") assert.Error(t, err) }) @@ -57,7 +57,7 @@ func Test_downloader_validateChecksum(t *testing.T) { URL: "foo/foo.tar.gz", Checksum: "f7fa712caea646575c920af17de3462fe9d08d7fe062b9a17010117d5fa4ed88", } - mustCopyFile(t, fooPath, filepath.Join(dir, "foo.tar.gz")) + mustCopyFile(t, downloadablesPath("foo.tar.gz"), filepath.Join(dir, "foo.tar.gz")) err := d.validateChecksum(dir) assert.NoError(t, err) assert.True(t, fileExists(filepath.Join(dir, "foo.tar.gz"))) @@ -82,7 +82,7 @@ func Test_downloader_validateChecksum(t *testing.T) { URL: "foo/foo.tar.gz", Checksum: "deadbeef", } - mustCopyFile(t, fooPath, filepath.Join(dir, "foo.tar.gz")) + mustCopyFile(t, downloadablesPath("foo.tar.gz"), filepath.Join(dir, "foo.tar.gz")) err := d.validateChecksum(dir) assert.Error(t, err) assert.False(t, fileExists(filepath.Join(dir, "foo.tar.gz"))) @@ -98,16 +98,83 @@ func TestDownloader_extract(t *testing.T) { } downloadDir := filepath.Join(dir, "download") extractDir := filepath.Join(dir, "extract") - mustCopyFile(t, fooPath, filepath.Join(downloadDir, "foo.tar.gz")) + mustCopyFile(t, downloadablesPath("foo.tar.gz"), filepath.Join(downloadDir, "foo.tar.gz")) err := d.extract(downloadDir, extractDir) assert.NoError(t, err) } func TestDownloader_Install(t *testing.T) { + t.Run("raw file", func(t *testing.T) { + dir, teardown := tmpDir(t) + defer teardown() + servePath := downloadablesPath("rawfile/foo") + ts := serveFile(servePath, "/foo/foo", "") + d := &Downloader{ + URL: ts.URL + "/foo/foo", + Checksum: "f044ff8b6007c74bcc1b5a5c92776e5d49d6014f5ff2d551fab115c17f48ac41", + BinName: "foo", + Arch: "amd64", + OS: "darwin", + } + err := d.Install(InstallOpts{ + TargetDir: dir, + Force: true, + }) + assert.NoError(t, err) + assert.True(t, fileExists(filepath.Join(dir, "foo"))) + stat, err := os.Stat(filepath.Join(dir, "foo")) + assert.NoError(t, err) + assert.False(t, stat.IsDir()) + assert.Equal(t, os.FileMode(0755), stat.Mode().Perm()) + }) + + t.Run("bin in root", func(t *testing.T) { + dir, teardown := tmpDir(t) + defer teardown() + servePath := downloadablesPath("fooinroot.tar.gz") + ts := serveFile(servePath, "/foo/fooinroot.tar.gz", "") + d := &Downloader{ + URL: ts.URL + "/foo/fooinroot.tar.gz", + Checksum: "27dcce60d1ed72920a84dd4bc01e0bbd013e5a841660e9ee2e964e53fb83c0b3", + BinName: "foo", + Arch: "amd64", + OS: "darwin", + } + err := d.Install(InstallOpts{ + TargetDir: dir, + Force: true, + }) + assert.NoError(t, err) + assert.True(t, fileExists(filepath.Join(dir, "foo"))) + stat, err := os.Stat(filepath.Join(dir, "foo")) + assert.NoError(t, err) + assert.False(t, stat.IsDir()) + assert.Equal(t, os.FileMode(0755), stat.Mode().Perm()) + }) + t.Run("move", func(t *testing.T) { dir, teardown := tmpDir(t) defer teardown() - ts := serveFile(fooPath, "/foo/foo.tar.gz", "foo=bar") + ts := serveFile(downloadablesPath("foo.tar.gz"), "/foo/foo.tar.gz", "foo=bar") + d := &Downloader{ + URL: ts.URL + "/foo/foo.tar.gz?foo=bar", + Checksum: "f7fa712caea646575c920af17de3462fe9d08d7fe062b9a17010117d5fa4ed88", + BinName: "foo.txt", + ArchivePath: "bin/foo.txt", + Arch: "amd64", + OS: "darwin", + } + err := d.Install(InstallOpts{ + TargetDir: dir, + Force: true, + }) + assert.NoError(t, err) + }) + + t.Run("legacy MoveFrom", func(t *testing.T) { + dir, teardown := tmpDir(t) + defer teardown() + ts := serveFile(downloadablesPath("foo.tar.gz"), "/foo/foo.tar.gz", "foo=bar") d := &Downloader{ URL: ts.URL + "/foo/foo.tar.gz?foo=bar", Checksum: "f7fa712caea646575c920af17de3462fe9d08d7fe062b9a17010117d5fa4ed88", @@ -126,7 +193,7 @@ func TestDownloader_Install(t *testing.T) { t.Run("link", func(t *testing.T) { dir, teardown := tmpDir(t) defer teardown() - ts := serveFile(fooPath, "/foo/foo.tar.gz", "foo=bar") + ts := serveFile(downloadablesPath("foo.tar.gz"), "/foo/foo.tar.gz", "foo=bar") d := &Downloader{ URL: ts.URL + "/foo/foo.tar.gz?foo=bar", Checksum: "f7fa712caea646575c920af17de3462fe9d08d7fe062b9a17010117d5fa4ed88", @@ -145,4 +212,28 @@ func TestDownloader_Install(t *testing.T) { absLinkTo := filepath.Join(dir, linksTo) assert.True(t, fileExists(absLinkTo)) }) + + t.Run("legacy LinkSource", func(t *testing.T) { + dir, teardown := tmpDir(t) + defer teardown() + ts := serveFile(downloadablesPath("foo.tar.gz"), "/foo/foo.tar.gz", "foo=bar") + d := &Downloader{ + URL: ts.URL + "/foo/foo.tar.gz?foo=bar", + Checksum: "f7fa712caea646575c920af17de3462fe9d08d7fe062b9a17010117d5fa4ed88", + BinName: "foo", + ArchivePath: "bin/foo.txt", + Link: true, + Arch: "amd64", + OS: "darwin", + } + err := d.Install(InstallOpts{ + TargetDir: dir, + Force: true, + }) + assert.NoError(t, err) + linksTo, err := os.Readlink(filepath.Join(dir, "foo")) + assert.NoError(t, err) + absLinkTo := filepath.Join(dir, linksTo) + assert.True(t, fileExists(absLinkTo)) + }) } diff --git a/testdata/downloadables/fooinroot.tar.gz b/testdata/downloadables/fooinroot.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..d0ed24cfac337336bd8843a7cfb12e5887743211 GIT binary patch literal 179 zcmb2|=3roLxEag9{Pv<Z*C7Lu)`va2yE=+LXUM(I+`80HDnoR8enz)(_hf}f|9$xy zC(L;=Z;FOrw(Q>N-fgB^OSAKqtgPiQJN9Dhm18XuEnl9l<}93_e|E}hn`I?0kA46B zY1_X0mg&{Uwd;>~e$^D+r~Kc&ATRx2<;Ju3U9&&^$(7AkEPWW)Z9o72#|5`uuXwg_ e)vnJIQf~WP-EPgufCPS=5e}%^pvIuVzyJUim{wx| literal 0 HcmV?d00001 diff --git a/testdata/downloadables/rawfile/foo b/testdata/downloadables/rawfile/foo new file mode 100644 index 00000000..f57cf482 --- /dev/null +++ b/testdata/downloadables/rawfile/foo @@ -0,0 +1,3 @@ +#!/bin/sh + +echo bar diff --git a/testhelper_test.go b/testhelper_test.go index d6d73bd8..da0c8e15 100644 --- a/testhelper_test.go +++ b/testhelper_test.go @@ -14,7 +14,9 @@ import ( "github.com/udhos/equalfile" ) -var fooPath = projectPath("testdata", "downloadables", "foo.tar.gz") +func downloadablesPath(path string) string { + return filepath.Join(projectPath("testdata", "downloadables"), filepath.FromSlash(path)) +} // projectPath exchanges a path relative to the project root for an absolute path func projectPath(path ...string) string { From 232f4294c8b3d5a8a9c9ab23be05cae99ca73f75 Mon Sep 17 00:00:00 2001 From: Will Roden <willabides@github.com> Date: Sat, 23 Nov 2019 13:11:16 -0600 Subject: [PATCH 2/3] mark MoveFrom and LinkSource deprecated --- downloader.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/downloader.go b/downloader.go index 8edad8ba..75774703 100644 --- a/downloader.go +++ b/downloader.go @@ -18,13 +18,17 @@ import ( type Downloader struct { URL string `json:"url"` Checksum string `json:"checksum"` - LinkSource string `json:"symlink,omitempty"` BinName string `json:"bin"` - MoveFrom string `json:"move-from"` ArchivePath string `json:"archive_path"` Link bool `json:"link"` OS string `json:"os"` Arch string `json:"arch"` + + // Deprecated: use ArchivePath + MoveFrom string `json:"move-from"` + + // Deprecated: use ArchivePath and Link + LinkSource string `json:"symlink,omitempty"` } func (d *Downloader) downloadableName() (string, error) { @@ -52,10 +56,12 @@ func (d *Downloader) chmod(targetDir string) error { } func (d *Downloader) moveOrLinkBin(targetDir, extractDir string) error { + //noinspection GoDeprecation if d.LinkSource != "" { d.ArchivePath = d.LinkSource d.Link = true } + //noinspection GoDeprecation if d.MoveFrom != "" { d.ArchivePath = d.MoveFrom } From 66bb90a998dd6aec71bead6e16fb909b86bcf796 Mon Sep 17 00:00:00 2001 From: Will Roden <willabides@github.com> Date: Sat, 23 Nov 2019 13:20:17 -0600 Subject: [PATCH 3/3] update buildtools.json to not use deprecated fields --- buildtools.json | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/buildtools.json b/buildtools.json index 36a26b0f..832d8bc1 100644 --- a/buildtools.json +++ b/buildtools.json @@ -5,7 +5,7 @@ "arch": "amd64", "url": "https://github.com/myitcv/gobin/releases/download/v0.0.10/darwin-amd64", "checksum": "84ed966949e06bebd7d006bc343caf9d736932fd8b37df5cb5b268a28d07bd30", - "move-from": "darwin-amd64", + "archive_path": "darwin-amd64", "bin": "gobin" }, { @@ -13,7 +13,7 @@ "arch": "amd64", "url": "https://github.com/myitcv/gobin/releases/download/v0.0.10/linux-amd64", "checksum": "415266d9af98578067051653f5057ea267c51ebf085408df48b118a8b978bac6", - "move-from": "linux-amd64", + "archive_path": "linux-amd64", "bin": "gobin" } ], @@ -23,7 +23,8 @@ "arch": "amd64", "url": "https://github.com/golangci/golangci-lint/releases/download/v1.21.0/golangci-lint-1.21.0-darwin-amd64.tar.gz", "checksum": "2b2713ec5007e67883aa501eebb81f22abfab0cf0909134ba90f60a066db3760", - "symlink": "golangci-lint-1.21.0-darwin-amd64/golangci-lint", + "archive_path": "golangci-lint-1.21.0-darwin-amd64/golangci-lint", + "link": true, "bin": "golangci-lint" }, { @@ -31,7 +32,8 @@ "arch": "amd64", "url": "https://github.com/golangci/golangci-lint/releases/download/v1.21.0/golangci-lint-1.21.0-linux-amd64.tar.gz", "checksum": "2c861f8dc56b560474aa27cab0c075991628cc01af3451e27ac82f5d10d5106b", - "symlink": "golangci-lint-1.21.0-linux-amd64/golangci-lint", + "archive_path": "golangci-lint-1.21.0-linux-amd64/golangci-lint", + "link": true, "bin": "golangci-lint" } ], @@ -41,7 +43,7 @@ "arch": "amd64", "url": "https://github.com/protocolbuffers/protobuf/releases/download/v3.9.1/protoc-3.9.1-osx-x86_64.zip", "checksum": "fd2e8a52b9b173bf90633f346901f4dcf3083769ea24f917809932d29ffa1410", - "move-from": "bin/protoc", + "archive_path": "bin/protoc", "bin": "protoc" }, { @@ -49,7 +51,7 @@ "arch": "amd64", "url": "https://github.com/protocolbuffers/protobuf/releases/download/v3.9.1/protoc-3.9.1-linux-x86_64.zip", "checksum": "77410d08e9a3c1ebb68afc13ee0c0fb4272c01c20bfd289adfb51b1c622bab07", - "move-from": "bin/protoc", + "archive_path": "bin/protoc", "bin": "protoc" } ], @@ -59,7 +61,6 @@ "arch": "amd64", "url": "https://github.com/goreleaser/goreleaser/releases/download/v0.120.7/goreleaser_Darwin_x86_64.tar.gz", "checksum": "2ec8bb354cca2936d0722e7da770c37e2ba6cc90de4a1cea186e20968c47b663", - "move-from": "goreleaser", "bin": "goreleaser" }, { @@ -67,7 +68,6 @@ "arch": "amd64", "url": "https://github.com/goreleaser/goreleaser/releases/download/v0.120.7/goreleaser_Linux_x86_64.tar.gz", "checksum": "771f2ad8219078b16a3e82097e9805309f6516640f0c6ab6b87f9b085a8ad743", - "move-from": "goreleaser", "bin": "goreleaser" } ], @@ -77,7 +77,6 @@ "arch": "amd64", "url": "https://github.com/WillAbides/semver-next/releases/download/v0.4.0/semver-next_0.4.0_darwin_amd64.tar.gz", "checksum": "a519f2c3bbe8972deb094d56c196fec89496f663431321c22be343ced23839fb", - "move-from": "semver-next", "bin": "semver-next" }, { @@ -85,7 +84,6 @@ "arch": "amd64", "url": "https://github.com/WillAbides/semver-next/releases/download/v0.4.0/semver-next_0.4.0_linux_amd64.tar.gz", "checksum": "6317c36bec63158038381e8878601151ae996310fef58306f70cb03f1b46ef7f", - "move-from": "semver-next", "bin": "semver-next" } ]