@@ -128,19 +128,17 @@ func (sh *Shell) Wait() {
128
128
sh .HandleError (sh .wait ())
129
129
}
130
130
131
- // Rename renames (moves) a file. It's just like os.Rename, but retries once on
132
- // error.
133
- func (sh * Shell ) Rename (oldpath , newpath string ) {
131
+ // Move moves a file.
132
+ func (sh * Shell ) Move (oldpath , newpath string ) {
134
133
sh .Ok ()
135
- sh .HandleError (sh .rename (oldpath , newpath ))
134
+ sh .HandleError (sh .move (oldpath , newpath ))
136
135
}
137
136
138
137
// BuildGoPkg compiles a Go package using the "go build" command and writes the
139
- // resulting binary to sh.Opts.BinDir unless the -o flag was specified.
138
+ // resulting binary to sh.Opts.BinDir, or to the -o flag location if specified.
140
139
// Returns the absolute path to the binary.
141
- // Included in Shell for convenience, but could have just as easily been
142
- // provided as a utility function.
143
140
func (sh * Shell ) BuildGoPkg (pkg string , flags ... string ) string {
141
+ // TODO(sadovsky): Convert BuildGoPkg into a utility function.
144
142
sh .Ok ()
145
143
res , err := sh .buildGoPkg (pkg , flags ... )
146
144
sh .HandleError (err )
@@ -347,34 +345,20 @@ func (sh *Shell) wait() error {
347
345
return res
348
346
}
349
347
350
- func (sh * Shell ) rename (oldpath , newpath string ) error {
351
- if err := os .Rename (oldpath , newpath ); err != nil {
352
- // Concurrent, same-directory rename operations sometimes fail on certain
353
- // filesystems, so we retry once after a random backoff.
354
- time .Sleep (time .Duration (rand .Int63n (1000 )) * time .Millisecond )
355
- if err := os .Rename (oldpath , newpath ); err != nil {
356
- return err
357
- }
358
- }
359
- return nil
360
- }
361
-
362
- func copyfile (from , to string ) error {
348
+ func copyFile (from , to string ) error {
363
349
fi , err := os .Stat (from )
364
350
if err != nil {
365
351
return err
366
352
}
367
- mode := fi .Mode ()
368
353
in , err := os .Open (from )
369
354
if err != nil {
370
355
return err
371
356
}
372
357
defer in .Close ()
373
- out , err := os .OpenFile (to , os .O_CREATE | os .O_RDWR | os .O_TRUNC , mode )
358
+ out , err := os .OpenFile (to , os .O_CREATE | os .O_TRUNC | os .O_WRONLY , fi . Mode (). Perm () )
374
359
if err != nil {
375
360
return err
376
361
}
377
- defer out .Close ()
378
362
_ , err = io .Copy (out , in )
379
363
cerr := out .Close ()
380
364
if err != nil {
@@ -383,6 +367,24 @@ func copyfile(from, to string) error {
383
367
return cerr
384
368
}
385
369
370
+ func (sh * Shell ) move (oldpath , newpath string ) error {
371
+ var err error
372
+ if err = os .Rename (oldpath , newpath ); err != nil {
373
+ // Concurrent, same-directory rename operations sometimes fail on certain
374
+ // filesystems, so we retry once after a random backoff.
375
+ time .Sleep (time .Duration (rand .Int63n (1000 )) * time .Millisecond )
376
+ err = os .Rename (oldpath , newpath )
377
+ }
378
+ // If the error was a LinkError, try copying the file over.
379
+ if _ , ok := err .(* os.LinkError ); ! ok {
380
+ return err
381
+ }
382
+ if err := copyFile (oldpath , newpath ); err != nil {
383
+ return err
384
+ }
385
+ return os .Remove (oldpath )
386
+ }
387
+
386
388
func extractOutputFlag (flags ... string ) (string , []string ) {
387
389
for i , f := range flags {
388
390
if f == "-o" && len (flags ) > i {
@@ -408,16 +410,14 @@ func (sh *Shell) buildGoPkg(pkg string, flags ...string) (string, error) {
408
410
} else if ! os .IsNotExist (err ) {
409
411
return "" , err
410
412
}
411
- // Build binary to tempBinPath, then move it to binPath.
413
+ // Build binary to tempBinPath (in a fresh temporary directory), then move it
414
+ // to binPath.
412
415
tempDir , err := ioutil .TempDir (sh .Opts .BinDir , "" )
413
416
if err != nil {
414
417
return "" , err
415
418
}
416
419
defer os .RemoveAll (tempDir )
417
420
tempBinPath := filepath .Join (tempDir , path .Base (pkg ))
418
- if outputFlag != "" {
419
- tempBinPath = filepath .Join (tempDir , filepath .Base (binPath ))
420
- }
421
421
args := []string {"build" , "-o" , tempBinPath }
422
422
args = append (args , flags ... )
423
423
args = append (args , pkg )
@@ -428,10 +428,7 @@ func (sh *Shell) buildGoPkg(pkg string, flags ...string) (string, error) {
428
428
if err := c .run (); err != nil {
429
429
return "" , err
430
430
}
431
- if err := sh .rename (tempBinPath , binPath ); err != nil {
432
- if _ , ok := err .(* os.LinkError ); ok {
433
- return "" , copyfile (tempBinPath , binPath )
434
- }
431
+ if err := sh .move (tempBinPath , binPath ); err != nil {
435
432
return "" , err
436
433
}
437
434
return binPath , nil
0 commit comments