Skip to content

Commit

Permalink
Merge pull request #20 from WillAbides/archivepath
Browse files Browse the repository at this point in the history
update download config
  • Loading branch information
WillAbides authored Nov 23, 2019
2 parents 1952248 + 66bb90a commit e2f22bb
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 58 deletions.
18 changes: 8 additions & 10 deletions buildtools.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
"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"
},
{
"os": "linux",
"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"
}
],
Expand All @@ -23,15 +23,17 @@
"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"
},
{
"os": "linux",
"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"
}
],
Expand All @@ -41,15 +43,15 @@
"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"
},
{
"os": "linux",
"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"
}
],
Expand All @@ -59,15 +61,13 @@
"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"
},
{
"os": "linux",
"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"
}
],
Expand All @@ -77,15 +77,13 @@
"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"
},
{
"os": "linux",
"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"
}
]
Expand Down
79 changes: 41 additions & 38 deletions downloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@ import (

// Downloader downloads a binary
type Downloader struct {
URL string `json:"url"`
Checksum string `json:"checksum"`
URL string `json:"url"`
Checksum string `json:"checksum"`
BinName string `json:"bin"`
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"`
BinName string `json:"bin"`
MoveFrom string `json:"move-from"`
OS string `json:"os"`
Arch string `json:"arch"`
}

func (d *Downloader) downloadableName() (string, error) {
Expand All @@ -49,45 +55,48 @@ 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 {
//noinspection GoDeprecation
if d.LinkSource != "" {
d.ArchivePath = d.LinkSource
d.Link = true
}
err := rm(d.binPath(targetDir))
if err != nil {
return err
//noinspection GoDeprecation
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 {
Expand Down Expand Up @@ -206,13 +215,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
Expand Down
109 changes: 100 additions & 9 deletions downloader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
Expand All @@ -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)
})
Expand All @@ -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")))
Expand All @@ -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")))
Expand All @@ -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",
Expand All @@ -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",
Expand All @@ -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))
})
}
Binary file added testdata/downloadables/fooinroot.tar.gz
Binary file not shown.
3 changes: 3 additions & 0 deletions testdata/downloadables/rawfile/foo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

echo bar
4 changes: 3 additions & 1 deletion testhelper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit e2f22bb

Please sign in to comment.