"io/ioutil"
"os"
"path/filepath"
+ "strconv"
"strings"
"time"
"cmd/go/internal/cache"
"cmd/go/internal/cfg"
"cmd/go/internal/load"
+ "cmd/go/internal/lockedfile"
"cmd/go/internal/modfetch"
"cmd/go/internal/modload"
"cmd/go/internal/work"
// right now are to be ignored.
dir := cache.DefaultDir()
if dir != "off" {
- err := ioutil.WriteFile(filepath.Join(dir, "testexpire.txt"), []byte(fmt.Sprintf("%d\n", time.Now().UnixNano())), 0666)
+ f, err := lockedfile.Edit(filepath.Join(dir, "testexpire.txt"))
+ if err == nil {
+ now := time.Now().UnixNano()
+ buf, _ := ioutil.ReadAll(f)
+ prev, _ := strconv.ParseInt(strings.TrimSpace(string(buf)), 10, 64)
+ if now > prev {
+ if err = f.Truncate(0); err == nil {
+ _, err = fmt.Fprintf(f, "%d\n", now)
+ }
+ }
+ if closeErr := f.Close(); err == nil {
+ err = closeErr
+ }
+ }
if err != nil {
base.Errorf("go clean -testcache: %v", err)
}
"cmd/go/internal/cache"
"cmd/go/internal/cfg"
"cmd/go/internal/load"
+ "cmd/go/internal/lockedfile"
"cmd/go/internal/modload"
"cmd/go/internal/str"
"cmd/go/internal/work"
// (We implement go clean -testcache by writing an expiration date
// instead of searching out and deleting test result cache entries.)
if dir := cache.DefaultDir(); dir != "off" {
- if data, _ := ioutil.ReadFile(filepath.Join(dir, "testexpire.txt")); len(data) > 0 && data[len(data)-1] == '\n' {
+ if data, _ := lockedfile.Read(filepath.Join(dir, "testexpire.txt")); len(data) > 0 && data[len(data)-1] == '\n' {
if t, err := strconv.ParseInt(string(data[:len(data)-1]), 10, 64); err == nil {
testCacheExpire = time.Unix(0, t)
}