@@ -12,6 +12,7 @@ import (
12
12
"path/filepath"
13
13
"runtime"
14
14
"strings"
15
+ "syscall"
15
16
"text/template"
16
17
"time"
17
18
@@ -732,13 +733,61 @@ func (i *Installer) extractTarGz(tarPath, binaryPath string, tool *Tool) error {
732
733
}
733
734
734
735
// Move the binary into place
735
- if err := os . Rename (found , binaryPath ); err != nil {
736
+ if err := MoveFile (found , binaryPath ); err != nil {
736
737
return fmt .Errorf ("failed to move extracted binary: %w" , err )
737
738
}
738
739
739
740
return nil
740
741
}
741
742
743
+ func isCrossDeviceError (errno syscall.Errno ) bool {
744
+ if runtime .GOOS == "windows" {
745
+ return errno == 0x11 // ERROR_NOT_SAME_DEVICE
746
+ }
747
+ return errno == syscall .EXDEV
748
+ }
749
+
750
+ // MoveFile tries os.Rename, but if that fails due to cross-device link,
751
+ // it falls back to a copy+remove.
752
+ func MoveFile (src , dst string ) error {
753
+ // Ensure target dir exists
754
+ if err := os .MkdirAll (filepath .Dir (dst ), 0o755 ); err != nil {
755
+ return fmt .Errorf ("failed to create target dir: %w" , err )
756
+ }
757
+
758
+ if err := os .Rename (src , dst ); err != nil {
759
+ if err := copyFile (src , dst ); err != nil {
760
+ return fmt .Errorf ("failed to copy during move fallback: %w" , err )
761
+ }
762
+ if err := os .Remove (src ); err != nil {
763
+ return fmt .Errorf ("failed to remove source after copy: %w" , err )
764
+ }
765
+ return nil
766
+ }
767
+ return nil
768
+ }
769
+
770
+ func copyFile (src , dst string ) error {
771
+ in , err := os .Open (src )
772
+ if err != nil {
773
+ return err
774
+ }
775
+ defer in .Close ()
776
+
777
+ out , err := os .Create (dst )
778
+ if err != nil {
779
+ return err
780
+ }
781
+ defer func () {
782
+ _ = out .Close ()
783
+ }()
784
+
785
+ if _ , err = io .Copy (out , in ); err != nil {
786
+ return err
787
+ }
788
+ return out .Sync ()
789
+ }
790
+
742
791
// extractGzip decompresses a single gzip-compressed binary.
743
792
func (i * Installer ) extractGzip (gzPath , binaryPath string ) error {
744
793
log .Debug ("Decompressing gzip binary" , "filename" , filepath .Base (gzPath ))
0 commit comments