cmd/buildlet: clamp modtime to be no greater than current time

Updates golang/go#19062

Change-Id: I12faf2941083d44466e6ff8a053c832631276ffe
Reviewed-on: https://go-review.googlesource.com/37381
Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/cmd/buildlet/buildlet.go b/cmd/buildlet/buildlet.go
index d3a9cac..1cfd065 100644
--- a/cmd/buildlet/buildlet.go
+++ b/cmd/buildlet/buildlet.go
@@ -640,6 +640,7 @@
 		return badRequest("requires gzip-compressed body: " + err.Error())
 	}
 	tr := tar.NewReader(zr)
+	loggedChtimesError := false
 	for {
 		f, err := tr.Next()
 		if err == io.EOF {
@@ -684,14 +685,23 @@
 			if n != f.Size {
 				return fmt.Errorf("only wrote %d bytes to %s; expected %d", n, abs, f.Size)
 			}
-			if !f.ModTime.IsZero() {
-				if err := os.Chtimes(abs, f.ModTime, f.ModTime); err != nil {
+			modTime := f.ModTime
+			if modTime.After(t0) {
+				// Clamp modtimes at system time. See
+				// golang.org/issue/19062 when clock on
+				// buildlet was behind the gitmirror server
+				// doing the git-archive.
+				modTime = t0
+			}
+			if !modTime.IsZero() {
+				if err := os.Chtimes(abs, modTime, modTime); err != nil && !loggedChtimesError {
 					// benign error. Gerrit doesn't even set the
 					// modtime in these, and we don't end up relying
 					// on it anywhere (the gomote push command relies
 					// on digests only), so this is a little pointless
 					// for now.
-					log.Printf("error changing modtime: %v", err)
+					log.Printf("error changing modtime: %v (further Chtimes errors suppressed)", err)
+					loggedChtimesError = true // once is enough
 				}
 			}
 			nFiles++