mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/go: check if build output should overwrite files with renames
CopyFile has a check to ensure that only object files are overwritten. Extend this to moveOrCopyFile, so the check also happens when the source and destination file are on the same filesystem (when renames are a valid way of moving files). Fixes #75970 Change-Id: Ie667301f1c9c00b114cfd91cdf8053ac20fd817b Reviewed-on: https://go-review.googlesource.com/c/go/+/712960 Reviewed-by: Laurent Demailly <ldemailly@gmail.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Michael Matloob <matloob@google.com> Reviewed-by: Ian Alexander <jitsu@google.com> Reviewed-by: Michael Matloob <matloob@golang.org>
This commit is contained in:
parent
557b4d6e0f
commit
7c9fa4d5e9
2 changed files with 43 additions and 10 deletions
|
|
@ -123,6 +123,11 @@ func (sh *Shell) moveOrCopyFile(dst, src string, perm fs.FileMode, force bool) e
|
|||
return nil
|
||||
}
|
||||
|
||||
err := checkDstOverwrite(dst, force)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If we can update the mode and rename to the dst, do it.
|
||||
// Otherwise fall back to standard copy.
|
||||
|
||||
|
|
@ -193,16 +198,9 @@ func (sh *Shell) CopyFile(dst, src string, perm fs.FileMode, force bool) error {
|
|||
}
|
||||
defer sf.Close()
|
||||
|
||||
// Be careful about removing/overwriting dst.
|
||||
// Do not remove/overwrite if dst exists and is a directory
|
||||
// or a non-empty non-object file.
|
||||
if fi, err := os.Stat(dst); err == nil {
|
||||
if fi.IsDir() {
|
||||
return fmt.Errorf("build output %q already exists and is a directory", dst)
|
||||
}
|
||||
if !force && fi.Mode().IsRegular() && fi.Size() != 0 && !isObject(dst) {
|
||||
return fmt.Errorf("build output %q already exists and is not an object file", dst)
|
||||
}
|
||||
err = checkDstOverwrite(dst, force)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// On Windows, remove lingering ~ file from last attempt.
|
||||
|
|
@ -247,6 +245,21 @@ func mayberemovefile(s string) {
|
|||
os.Remove(s)
|
||||
}
|
||||
|
||||
// Be careful about removing/overwriting dst.
|
||||
// Do not remove/overwrite if dst exists and is a directory
|
||||
// or a non-empty non-object file.
|
||||
func checkDstOverwrite(dst string, force bool) error {
|
||||
if fi, err := os.Stat(dst); err == nil {
|
||||
if fi.IsDir() {
|
||||
return fmt.Errorf("build output %q already exists and is a directory", dst)
|
||||
}
|
||||
if !force && fi.Mode().IsRegular() && fi.Size() != 0 && !isObject(dst) {
|
||||
return fmt.Errorf("build output %q already exists and is not an object file", dst)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// writeFile writes the text to file.
|
||||
func (sh *Shell) writeFile(file string, text []byte) error {
|
||||
if cfg.BuildN || cfg.BuildX {
|
||||
|
|
|
|||
20
src/cmd/go/testdata/script/build_output_overwrite.txt
vendored
Normal file
20
src/cmd/go/testdata/script/build_output_overwrite.txt
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# windows executables have the .exe extension and won't overwrite source files
|
||||
[GOOS:windows] skip
|
||||
|
||||
mkdir out
|
||||
env GOTMPDIR=$PWD/out
|
||||
|
||||
grep 'this should still exist' foo.go
|
||||
|
||||
! go build
|
||||
stderr 'already exists and is not an object file'
|
||||
|
||||
grep 'this should still exist' foo.go
|
||||
|
||||
-- go.mod --
|
||||
module foo.go
|
||||
|
||||
-- foo.go --
|
||||
package main // this should still exist
|
||||
|
||||
func main() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue