diff --git a/cli/meta/symlink_win.go b/cli/meta/symlink_win.go index 62eb074..22287fe 100644 --- a/cli/meta/symlink_win.go +++ b/cli/meta/symlink_win.go @@ -19,7 +19,6 @@ import ( "golang.org/x/sys/windows" ) - func becomeAdmin() error { verb := "runas" exe, _ := os.Executable() @@ -51,23 +50,23 @@ func isAdmin() bool { // but with automatic privilege escalation on windows // for systems that do not support non-admin symlinks. func Symlink(oldname, newname string) error { - - // Check if already admin first - if isAdmin() { - if err := os.Symlink(oldname, newname); err != nil { - return errors.Join(ErrEscalatedSymlink, err) - } - return nil - } else { - // If not already admin, try to become admin - if err := becomeAdmin(); err != nil { + // Attempt to do a regular symlink if allowed by user's permissions + if err := os.Symlink(oldname, newname); err != nil { + // Check if already admin first + if isAdmin() { if err := os.Symlink(oldname, newname); err != nil { return errors.Join(ErrEscalatedSymlink, err) } + return nil + } else { + // If not already admin, try to become admin + if err := becomeAdmin(); err != nil { + if err := os.Symlink(oldname, newname); err != nil { + return errors.Join(ErrEscalatedSymlink, err) + } + } } } - - return nil } diff --git a/cli/meta/version.go b/cli/meta/version.go index e157f41..43eb1c1 100644 --- a/cli/meta/version.go +++ b/cli/meta/version.go @@ -9,7 +9,7 @@ import ( ) const ( - VERSION = "v0.6.2" + VERSION = "v0.6.3" ) diff --git a/cli/use.go b/cli/use.go index a2d3c68..6ee996f 100644 --- a/cli/use.go +++ b/cli/use.go @@ -8,7 +8,6 @@ import ( "bufio" "errors" "fmt" - "io/fs" "os" "path/filepath" "strings" @@ -40,13 +39,17 @@ func (z *ZVM) setBin(ver string) error { version_path := filepath.Join(z.baseDir, ver) bin_dir := filepath.Join(z.baseDir, "bin") - // Remove "bin" dir only if it already exists - - if _, err := os.Stat(bin_dir); errors.Is(err, fs.ErrExist) { + // Came across https://pkg.go.dev/os#Lstat + // which is specifically to check symbolic links. + // Seemed like the more appropriate solution here + stat, err := os.Lstat(bin_dir); + if err == nil { fmt.Printf("Removing old %s", bin_dir) if err := os.Remove(bin_dir); err != nil { return err } + } else { + return fmt.Errorf("%w: %s", err, stat.Name()) } if err := meta.Symlink(version_path, bin_dir); err != nil { diff --git a/cli/use_test.go b/cli/use_test.go new file mode 100644 index 0000000..beddb58 --- /dev/null +++ b/cli/use_test.go @@ -0,0 +1,19 @@ +package cli + +import ( + "os" + "testing" +) + +func TestSymlinkExists(t *testing.T) { + if err := os.Symlink("use_test.go", "symlink.test"); err != nil { + t.Error(err) + } + + stat, err := os.Lstat("symlink.test"); + if err != nil { + t.Errorf("%q: %s", err, stat.Name()) + } + + defer os.Remove("symlink.test") +} \ No newline at end of file