aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/go/internal/modcmd/edit.go
diff options
context:
space:
mode:
authorBryan C. Mills <bcmills@google.com>2018-10-23 15:51:42 -0400
committerBryan C. Mills <bcmills@google.com>2018-11-29 18:49:53 +0000
commit143c1c82371d52a4f2cf72c56eaaac4c8766e234 (patch)
tree412a8bc3a2d4dd9ff6cb4c59f4ed45f22659f4d3 /src/cmd/go/internal/modcmd/edit.go
parent04e12a5bfa51777c4ba46ed2e026f53578206754 (diff)
downloadgo-143c1c82371d52a4f2cf72c56eaaac4c8766e234.tar.gz
go-143c1c82371d52a4f2cf72c56eaaac4c8766e234.zip
cmd/go/internal/{modcmd,modload}: lock edits to go.mod
Use an arbitrary lockfile to serialize edits, and use atomic renames to actually write the go.mod file so that we never drop version requirements due to a command failing partway through a write. Multiple invocations of the 'go' command may read the go.mod file concurrently, and will see some consistent version even if some other invocation changes it concurrently. Multiple commands may attempt to write the go.mod file concurrently. One writer will succeed and write a consistent, complete go.mod file. The others will detect the changed contents and fail explicitly: it is not, in general, possible to resolve two conflicting changes to module requirements, so we surface the problem to the user rather than trying to solve the problem heuristically. Updates #26794 Change-Id: Ia1a06a01ef93fa9be664f560eb83bb86b0207443 Reviewed-on: https://go-review.googlesource.com/c/146380 Run-TryBot: Bryan C. Mills <bcmills@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/cmd/go/internal/modcmd/edit.go')
-rw-r--r--src/cmd/go/internal/modcmd/edit.go14
1 files changed, 11 insertions, 3 deletions
diff --git a/src/cmd/go/internal/modcmd/edit.go b/src/cmd/go/internal/modcmd/edit.go
index c589c6d4ed..875bad78dc 100644
--- a/src/cmd/go/internal/modcmd/edit.go
+++ b/src/cmd/go/internal/modcmd/edit.go
@@ -7,6 +7,7 @@
package modcmd
import (
+ "bytes"
"encoding/json"
"fmt"
"io/ioutil"
@@ -15,6 +16,7 @@ import (
"strings"
"cmd/go/internal/base"
+ "cmd/go/internal/modfetch"
"cmd/go/internal/modfile"
"cmd/go/internal/modload"
"cmd/go/internal/module"
@@ -204,17 +206,23 @@ func runEdit(cmd *base.Command, args []string) {
return
}
- data, err = modFile.Format()
+ out, err := modFile.Format()
if err != nil {
base.Fatalf("go: %v", err)
}
if *editPrint {
- os.Stdout.Write(data)
+ os.Stdout.Write(out)
return
}
- if err := ioutil.WriteFile(gomod, data, 0666); err != nil {
+ unlock := modfetch.SideLock()
+ defer unlock()
+ lockedData, err := ioutil.ReadFile(gomod)
+ if err == nil && !bytes.Equal(lockedData, data) {
+ base.Fatalf("go: go.mod changed during editing; not overwriting")
+ }
+ if err := ioutil.WriteFile(gomod, out, 0666); err != nil {
base.Fatalf("go: %v", err)
}
}