From 9d18cdd0ec73c8c4aae82be27b461e7a3f79e7b7 Mon Sep 17 00:00:00 2001 From: Gordon Bleux <33967640+UiP9AV6Y@users.noreply.github.com> Date: Fri, 28 Feb 2025 20:54:33 +0100 Subject: [PATCH] create binary symlinks with relative location since the installed binary as well as the symlink reside in the same directory, relative paths should be safe to use without having to worry about crossing filesystem boundaries. closes #158 --- get.go | 14 +++++++++++--- get_test.go | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/get.go b/get.go index 99333e5..792e04c 100644 --- a/get.go +++ b/get.go @@ -806,7 +806,8 @@ func install(ctx context.Context, logger *log.Logger, r *runner.Runner, modDir s } // go install does not define -modfile flag, so we mimic go install with go build -o instead. - binPath := filepath.Join(gobin, fmt.Sprintf("%s-%s", name, pkg.Module.Version)) + binName := fmt.Sprintf("%s-%s", name, pkg.Module.Version) + binPath := filepath.Join(gobin, binName) // New context with new environment files. modCtx = r.With(ctx, modFile.Filepath(), modDir, pkg.BuildEnvs) @@ -825,12 +826,19 @@ func install(ctx context.Context, logger *log.Logger, r *runner.Runner, modDir s return nil } - if err := os.RemoveAll(filepath.Join(gobin, name)); err != nil { + return installSymlink(gobin, binName, name) +} + +func installSymlink(dir, oldName, newName string) error { + newPath := filepath.Join(dir, newName) + if err := os.RemoveAll(newPath); err != nil { return errors.Wrap(err, "rm") } - if err := os.Symlink(binPath, filepath.Join(gobin, name)); err != nil { + + if err := os.Symlink(oldName, newPath); err != nil { return errors.Wrap(err, "symlink") } + return nil } diff --git a/get_test.go b/get_test.go index 3a8514a..fcb6c4c 100644 --- a/get_test.go +++ b/get_test.go @@ -4,6 +4,8 @@ package main import ( + "os" + "path/filepath" "testing" "github.com/efficientgo/core/errors" @@ -89,3 +91,38 @@ func TestParseTarget(t *testing.T) { } } + +func TestInstallSymlink(t *testing.T) { + dir := t.TempDir() + oldName := "some-binary-1.2.3" + newName := "some-binary" + oldPath := filepath.Join(dir, oldName) + newPath := filepath.Join(dir, newName) + testData := "#!/bin/true" + + // simulate an existing symlink to test the removal logic + f, err := os.Create(newPath) + testutil.Ok(t, err) + testutil.Ok(t, f.Close()) + + // create a dummy target ... + f, err = os.Create(oldPath) + testutil.Ok(t, err) + // ... and write some data for verification later + _, err = f.Write([]byte(testData)) + testutil.Ok(t, err) + testutil.Ok(t, f.Close()) + + err = installSymlink(dir, oldName, newName) + testutil.Ok(t, err) + + gotPath, err := os.Readlink(newPath) + testutil.Ok(t, err) + testutil.Equals(t, oldName, gotPath) + + gotData, err := os.ReadFile(newPath) + testutil.Ok(t, err) + + // ensure the symlink leads to the desired target + testutil.Equals(t, testData, string(gotData)) +}