aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmd/go/internal/work/shell.go33
-rw-r--r--src/cmd/go/testdata/script/build_output_overwrite.txt20
2 files changed, 43 insertions, 10 deletions
diff --git a/src/cmd/go/internal/work/shell.go b/src/cmd/go/internal/work/shell.go
index 284ed26f22..ceff84d81f 100644
--- a/src/cmd/go/internal/work/shell.go
+++ b/src/cmd/go/internal/work/shell.go
@@ -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 {
diff --git a/src/cmd/go/testdata/script/build_output_overwrite.txt b/src/cmd/go/testdata/script/build_output_overwrite.txt
new file mode 100644
index 0000000000..c7b967ccec
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_output_overwrite.txt
@@ -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() {}