From 0ed70efc6b7ec096603c58f27c2668af3862bb3c Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 2 Feb 2016 09:19:47 -0500 Subject: [PATCH] cmd/go: fix rebuild after installation of new Go release The loading of zversion.go was expecting it to be in package runtime, but it moved to runtime/internal/sys. Worse, the load was not checking the error. Update the path, check the error, add a test. Fixes #14176. Change-Id: I203c40afe1448875581415d5e42c29f09b14545d Reviewed-on: https://go-review.googlesource.com/19180 Run-TryBot: Russ Cox Reviewed-by: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- src/cmd/go/go_test.go | 86 +++++++++++++++++++++++++++++++++++++++---- src/cmd/go/pkg.go | 9 +++-- 2 files changed, 85 insertions(+), 10 deletions(-) diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 0136ba4b1b..6d12f75073 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -657,6 +657,9 @@ func TestGoBuildDashAInDevBranch(t *testing.T) { tg.setenv("TESTGO_IS_GO_RELEASE", "0") tg.run("build", "-v", "-a", "math") tg.grepStderr("runtime", "testgo build -a math in dev branch DID NOT build runtime, but should have") + + // Everything is out of date. Rebuild to leave things in a better state. + tg.run("install", "std") } func TestGoBuildDashAInReleaseBranch(t *testing.T) { @@ -672,11 +675,80 @@ func TestGoBuildDashAInReleaseBranch(t *testing.T) { tg.grepStderr("runtime", "testgo build -a math in release branch DID NOT build runtime, but should have") // Now runtime.a is updated (newer mtime), so everything would look stale if not for being a release. - // tg.run("build", "-v", "net/http") tg.grepStderrNot("strconv", "testgo build -v net/http in release branch with newer runtime.a DID build strconv but should not have") tg.grepStderrNot("golang.org/x/net/http2/hpack", "testgo build -v net/http in release branch with newer runtime.a DID build .../golang.org/x/net/http2/hpack but should not have") tg.grepStderrNot("net/http", "testgo build -v net/http in release branch with newer runtime.a DID build net/http but should not have") + + // Everything is out of date. Rebuild to leave things in a better state. + tg.run("install", "std") +} + +func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) { + if testing.Short() { + t.Skip("don't rebuild the standard library in short mode") + } + + tg := testgo(t) + defer tg.cleanup() + + addNL := func(name string) (restore func()) { + data, err := ioutil.ReadFile(name) + if err != nil { + t.Fatal(err) + } + old := data + data = append(data, '\n') + if err := ioutil.WriteFile(name, append(data, '\n'), 0666); err != nil { + t.Fatal(err) + } + tg.sleep() + return func() { + if err := ioutil.WriteFile(name, old, 0666); err != nil { + t.Fatal(err) + } + } + } + + tg.setenv("TESTGO_IS_GO_RELEASE", "1") + + tg.tempFile("d1/src/p1/p1.go", `package p1`) + tg.setenv("GOPATH", tg.path("d1")) + tg.run("install", "-a", "p1") + tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly") + tg.sleep() + + // Changing mtime and content of runtime/internal/sys/sys.go + // should have no effect: we're in a release, which doesn't rebuild + // for general mtime or content changes. + sys := runtime.GOROOT() + "/src/runtime/internal/sys/sys.go" + restore := addNL(sys) + defer restore() + tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly, after updating runtime/internal/sys/sys.go") + restore() + tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly, after restoring runtime/internal/sys/sys.go") + + // But changing runtime/internal/sys/zversion.go should have an effect: + // that's how we tell when we flip from one release to another. + zversion := runtime.GOROOT() + "/src/runtime/internal/sys/zversion.go" + restore = addNL(zversion) + defer restore() + tg.wantStale("p1", "./testgo list claims p1 is NOT stale, incorrectly, after changing to new release") + restore() + tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly, after changing back to old release") + addNL(zversion) + tg.wantStale("p1", "./testgo list claims p1 is NOT stale, incorrectly, after changing again to new release") + tg.run("install", "p1") + tg.wantNotStale("p1", "./testgo list claims p1 is stale after building with new release") + + // Restore to "old" release. + restore() + tg.wantStale("p1", "./testgo list claims p1 is NOT stale, incorrectly, after changing to old release after new build") + tg.run("install", "p1") + tg.wantNotStale("p1", "./testgo list claims p1 is stale after building with old release") + + // Everything is out of date. Rebuild to leave things in a better state. + tg.run("install", "std") } func TestGoListStandard(t *testing.T) { @@ -756,8 +828,8 @@ func TestGoInstallRebuildsStalePackagesInOtherGOPATH(t *testing.T) { sep := string(filepath.ListSeparator) tg.setenv("GOPATH", tg.path("d1")+sep+tg.path("d2")) tg.run("install", "p1") - tg.wantNotStale("p1", "./testgo list mypkg claims p1 is stale, incorrectly") - tg.wantNotStale("p2", "./testgo list mypkg claims p2 is stale, incorrectly") + tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly") + tg.wantNotStale("p2", "./testgo list claims p2 is stale, incorrectly") tg.sleep() if f, err := os.OpenFile(tg.path("d2/src/p2/p2.go"), os.O_WRONLY|os.O_APPEND, 0); err != nil { t.Fatal(err) @@ -766,12 +838,12 @@ func TestGoInstallRebuildsStalePackagesInOtherGOPATH(t *testing.T) { } else { tg.must(f.Close()) } - tg.wantStale("p2", "./testgo list mypkg claims p2 is NOT stale, incorrectly") - tg.wantStale("p1", "./testgo list mypkg claims p1 is NOT stale, incorrectly") + tg.wantStale("p2", "./testgo list claims p2 is NOT stale, incorrectly") + tg.wantStale("p1", "./testgo list claims p1 is NOT stale, incorrectly") tg.run("install", "p1") - tg.wantNotStale("p2", "./testgo list mypkg claims p2 is stale after reinstall, incorrectly") - tg.wantNotStale("p1", "./testgo list mypkg claims p1 is stale after reinstall, incorrectly") + tg.wantNotStale("p2", "./testgo list claims p2 is stale after reinstall, incorrectly") + tg.wantNotStale("p1", "./testgo list claims p1 is stale after reinstall, incorrectly") } func TestGoInstallDetectsRemovedFiles(t *testing.T) { diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go index 95a06ffedc..a804ccd277 100644 --- a/src/cmd/go/pkg.go +++ b/src/cmd/go/pkg.go @@ -1542,11 +1542,14 @@ func computeBuildID(p *Package) { fmt.Fprintf(h, "file %s\n", file) } - // Include the content of runtime/zversion.go in the hash + // Include the content of runtime/internal/sys/zversion.go in the hash // for package runtime. This will give package runtime a // different build ID in each Go release. - if p.Standard && p.ImportPath == "runtime" { - data, _ := ioutil.ReadFile(filepath.Join(p.Dir, "zversion.go")) + if p.Standard && p.ImportPath == "runtime/internal/sys" { + data, err := ioutil.ReadFile(filepath.Join(p.Dir, "zversion.go")) + if err != nil { + fatalf("go: %s", err) + } fmt.Fprintf(h, "zversion %q\n", string(data)) }