diff options
-rw-r--r-- | worktree.go | 16 | ||||
-rw-r--r-- | worktree_darwin.go | 4 | ||||
-rw-r--r-- | worktree_linux.go | 4 | ||||
-rw-r--r-- | worktree_windows.go | 15 |
4 files changed, 39 insertions, 0 deletions
diff --git a/worktree.go b/worktree.go index 394dce4..d2cb29a 100644 --- a/worktree.go +++ b/worktree.go @@ -554,6 +554,22 @@ func (w *Worktree) checkoutFileSymlink(f *object.File) (err error) { } err = w.Filesystem.Symlink(string(bytes), f.Name) + + // On windows, this might fail. + // Follow Git on Windows behavior by writing the link as it is. + if err != nil && isSymlinkWindowsNonAdmin(err) { + mode, _ := f.Mode.ToOSFileMode() + + to, err := w.Filesystem.OpenFile(f.Name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode.Perm()) + if err != nil { + return err + } + + defer ioutil.CheckClose(to, &err) + + _, err = to.Write(bytes) + return err + } return } diff --git a/worktree_darwin.go b/worktree_darwin.go index 8eaffde..3b374c7 100644 --- a/worktree_darwin.go +++ b/worktree_darwin.go @@ -20,3 +20,7 @@ func init() { } } } + +func isSymlinkWindowsNonAdmin(err error) bool { + return false +} diff --git a/worktree_linux.go b/worktree_linux.go index a33cd2f..891cb1c 100644 --- a/worktree_linux.go +++ b/worktree_linux.go @@ -20,3 +20,7 @@ func init() { } } } + +func isSymlinkWindowsNonAdmin(err error) bool { + return false +} diff --git a/worktree_windows.go b/worktree_windows.go index d59448e..1bef6f7 100644 --- a/worktree_windows.go +++ b/worktree_windows.go @@ -3,6 +3,7 @@ package git import ( + "os" "syscall" "time" @@ -18,3 +19,17 @@ func init() { } } } + +func isSymlinkWindowsNonAdmin(err error) bool { + const ERROR_PRIVILEGE_NOT_HELD syscall.Errno = 1314 + + if err != nil { + if errLink, ok := err.(*os.LinkError); ok { + if errNo, ok := errLink.Err.(syscall.Errno); ok { + return errNo == ERROR_PRIVILEGE_NOT_HELD + } + } + } + + return false +} |