From: Russ Cox Date: Mon, 20 Apr 2015 15:41:31 +0000 (-0400) Subject: cmd/dist: do not rewrite files that already have the correct content X-Git-Tag: go1.5beta1~382 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=e346adf5685b5c310ecdd6b121591ecb0ea91ea0;p=gostls13.git cmd/dist: do not rewrite files that already have the correct content In particular, this avoids moving the mtime on runtime/zversion.go forward unless the file is out of date. In turn, this makes cross compiles that run dist multiple times coexist nicely. (It's no longer necessary to run dist multiple times to set up cross compiles, but people still might, and it's easy to fix regardless.) Fixes #4749. Change-Id: Id430525f168f106bc4b821ca74b2ca498a748f14 Reviewed-on: https://go-review.googlesource.com/9152 Reviewed-by: Brad Fitzpatrick --- diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go index 2262a736de..2fcb12c826 100644 --- a/src/cmd/dist/build.go +++ b/src/cmd/dist/build.go @@ -809,11 +809,11 @@ func shouldbuild(file, dir string) bool { } // copy copies the file src to dst, via memory (so only good for small files). -func copyfile(dst, src string, exec int) { +func copyfile(dst, src string, flag int) { if vflag > 1 { errprintf("cp %s %s\n", src, dst) } - writefile(readfile(src), dst, exec) + writefile(readfile(src), dst, flag) } // dopack copies the package src to dst, diff --git a/src/cmd/dist/buildruntime.go b/src/cmd/dist/buildruntime.go index 70aafe9183..9b8d8f0cf6 100644 --- a/src/cmd/dist/buildruntime.go +++ b/src/cmd/dist/buildruntime.go @@ -35,7 +35,7 @@ func mkzversion(dir, file string) { "const stackGuardMultiplier = %d\n"+ "var buildVersion = theVersion\n", goroot_final, findgoversion(), os.Getenv("GOEXPERIMENT"), stackGuardMultiplier()) - writefile(out, file, 0) + writefile(out, file, writeSkipSame) } // mkzbootstrap writes cmd/internal/obj/zbootstrap.go: @@ -80,7 +80,7 @@ func mkzbootstrap(file string) { "const goexperiment = `%s`\n", goroot_final, go386, goarm, goextlinkenabled, findgoversion(), stackGuardMultiplier(), os.Getenv("GOEXPERIMENT")) - writefile(out, file, 0) + writefile(out, file, writeSkipSame) } // stackGuardMultiplier returns a multiplier to apply to the default diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index 2840f71749..be54ac46de 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -118,7 +118,7 @@ func bootstrapBuildTools() { // Copy binaries into tool binary directory. for _, name := range bootstrapDirs { if !strings.Contains(name, "/") { - copyfile(pathf("%s/%s%s", tooldir, name, exe), pathf("%s/bin/%s%s", workspace, name, exe), 1) + copyfile(pathf("%s/%s%s", tooldir, name, exe), pathf("%s/bin/%s%s", workspace, name, exe), writeExec) } } diff --git a/src/cmd/dist/util.go b/src/cmd/dist/util.go index cae5d699d4..f13210f4de 100644 --- a/src/cmd/dist/util.go +++ b/src/cmd/dist/util.go @@ -5,6 +5,7 @@ package main import ( + "bytes" "fmt" "io/ioutil" "os" @@ -245,14 +246,28 @@ func readfile(file string) string { return string(data) } -// writefile writes b to the named file, creating it if needed. if -// exec is non-zero, marks the file as executable. -func writefile(b, file string, exec int) { +const ( + writeExec = 1 << iota + writeSkipSame +) + +// writefile writes b to the named file, creating it if needed. +// if exec is non-zero, marks the file as executable. +// If the file already exists and has the expected content, +// it is not rewritten, to avoid changing the time stamp. +func writefile(b, file string, flag int) { + new := []byte(b) + if flag&writeSkipSame != 0 { + old, err := ioutil.ReadFile(file) + if err == nil && bytes.Equal(old, new) { + return + } + } mode := os.FileMode(0666) - if exec != 0 { + if flag&writeExec != 0 { mode = 0777 } - err := ioutil.WriteFile(file, []byte(b), mode) + err := ioutil.WriteFile(file, new, mode) if err != nil { fatal("%v", err) }