From 389f7c25dd3ddd8a530eaa61ef7c333fb4e5d6cf Mon Sep 17 00:00:00 2001 From: Gavin Chappell <2798739+g-a-c@users.noreply.github.com> Date: Sat, 20 Nov 2021 19:30:46 +0000 Subject: [PATCH] refactor downloading of binaries * If `/tmp` is a `tmpfs` or somehow not the same filesystem, `os.Rename()` will fail so use `io.Copy()` instead * don't defer cleanup of `to` as this removes the newly-created file if the operation is successful, making `install` and `upgrade` _functionally_ `uninstall` * defer cleanup of the temporary file since it will still be in place if `os.Rename()` fails Fixes: #130 --- internal/bins/bins.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/internal/bins/bins.go b/internal/bins/bins.go index 27c640c..2d90667 100644 --- a/internal/bins/bins.go +++ b/internal/bins/bins.go @@ -87,9 +87,23 @@ func downloadAndInstallAsset(body GithubRelease, name string) error { } to := path.Join(INSTALL_PATH, name) - defer os.Remove(to) // Delete if current, ignore error if file does not exits. + defer os.Remove(tmp.Name()) // Cleanup temporary file after thread exits if err := os.Rename(tmp.Name(), to); err != nil { - return nil + colors.Error.Printf("os.Rename() failed (%v), retrying with io.Copy()\n", err.Error()) + var src *os.File + var dst *os.File + if src, err = os.Open(tmp.Name()); err != nil { + return err + } + if dst, err = os.Create(to); err != nil { + return err + } + if _, err := io.Copy(dst, src); err != nil { + return err + } + if err := os.Chmod(to, 0755); err != nil { + return err + } } colors.Success.Printf("Successfully installed '%s' under %s\n", name, INSTALL_PATH)