Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 71e3741

Browse files
authored
Merge pull request #778 from konsorten/fix-windows-symlink3
Worktree.Checkout: handling of symlink on Windows
2 parents 1d28459 + 4915f58 commit 71e3741

File tree

4 files changed

+39
-0
lines changed

4 files changed

+39
-0
lines changed

worktree.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,22 @@ func (w *Worktree) checkoutFileSymlink(f *object.File) (err error) {
554554
}
555555

556556
err = w.Filesystem.Symlink(string(bytes), f.Name)
557+
558+
// On windows, this might fail.
559+
// Follow Git on Windows behavior by writing the link as it is.
560+
if err != nil && isSymlinkWindowsNonAdmin(err) {
561+
mode, _ := f.Mode.ToOSFileMode()
562+
563+
to, err := w.Filesystem.OpenFile(f.Name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode.Perm())
564+
if err != nil {
565+
return err
566+
}
567+
568+
defer ioutil.CheckClose(to, &err)
569+
570+
_, err = to.Write(bytes)
571+
return err
572+
}
557573
return
558574
}
559575

worktree_darwin.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,7 @@ func init() {
2020
}
2121
}
2222
}
23+
24+
func isSymlinkWindowsNonAdmin(err error) bool {
25+
return false
26+
}

worktree_linux.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,7 @@ func init() {
2020
}
2121
}
2222
}
23+
24+
func isSymlinkWindowsNonAdmin(err error) bool {
25+
return false
26+
}

worktree_windows.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package git
44

55
import (
6+
"os"
67
"syscall"
78
"time"
89

@@ -18,3 +19,17 @@ func init() {
1819
}
1920
}
2021
}
22+
23+
func isSymlinkWindowsNonAdmin(err error) bool {
24+
const ERROR_PRIVILEGE_NOT_HELD syscall.Errno = 1314
25+
26+
if err != nil {
27+
if errLink, ok := err.(*os.LinkError); ok {
28+
if errNo, ok := errLink.Err.(syscall.Errno); ok {
29+
return errNo == ERROR_PRIVILEGE_NOT_HELD
30+
}
31+
}
32+
}
33+
34+
return false
35+
}

0 commit comments

Comments
 (0)