aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--worktree.go16
-rw-r--r--worktree_darwin.go4
-rw-r--r--worktree_linux.go4
-rw-r--r--worktree_windows.go15
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
+}