cmd/buildlet: recreate accidentally deleted dirs lazily
The buildlet's /removeall handler previously restored any deletes of
important directories (the $WORKDIR, $GOCACHE, and $TMP) immediately
after the deletes, before the /removeall handler returned to the
client.
Unfortunately, some clients actually do want to delete $GOCACHE and
$TMP: in CL 159257 (submitted too early), cmd/release wants to delete
those before tarring/zipping up the rest of $WORKDIR to ship a
release.
This CL changes the remove handler to just remove stuff without fixing
mistakes. Instead, missing directories are created lazily later if
needed.
Also, minor debug logging change to cmd/release that I hadn't yet
uploaded to CL 159257 before it was submitted.
Fixes golang/go#29906
Change-Id: Ifb5d3c16e2d83e7ac9e7f8e353d1b7b866f7d338
Reviewed-on: https://go-review.googlesource.com/c/159320
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
diff --git a/cmd/buildlet/buildlet.go b/cmd/buildlet/buildlet.go
index f11437b..f57737a 100644
--- a/cmd/buildlet/buildlet.go
+++ b/cmd/buildlet/buildlet.go
@@ -524,6 +524,9 @@
http.Error(w, "requires GET method", http.StatusBadRequest)
return
}
+ if !mkdirAllWorkdir(w) {
+ return
+ }
dir := r.FormValue("dir")
if !validRelativeDir(dir) {
http.Error(w, "bogus dir", http.StatusBadRequest)
@@ -584,6 +587,9 @@
}
func handleWriteTGZ(w http.ResponseWriter, r *http.Request) {
+ if !mkdirAllWorkdir(w) {
+ return
+ }
urlParam, _ := url.ParseQuery(r.URL.RawQuery)
baseDir := *workDir
if dir := urlParam.Get("dir"); dir != "" {
@@ -841,6 +847,19 @@
http.Error(w, "HTTP/1.1 or higher required", http.StatusBadRequest)
return
}
+ // Create *workDir and (if needed) tmp and gocache.
+ if !mkdirAllWorkdir(w) {
+ return
+ }
+ for _, dir := range []string{processTmpDirEnv, processGoCacheEnv} {
+ if dir == "" {
+ continue
+ }
+ if err := os.MkdirAll(dir, 0755); err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ }
w.Header().Set("Trailer", hdrProcessState) // declare it so we can set it
@@ -1229,16 +1248,18 @@
return
}
}
- // If we nuked the work directory (or tmp or gocache), recreate them.
- for _, dir := range []string{*workDir, processTmpDirEnv, processGoCacheEnv} {
- if dir == "" {
- continue
- }
- if err := os.MkdirAll(dir, 0755); err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
+}
+
+// mkdirAllWorkdir reports whether *workDir either exists or was created.
+// If it returns false, it also writes an HTTP 500 error to w.
+// This is used by callers to verify *workDir exists, even if it might've been
+// deleted previously.
+func mkdirAllWorkdir(w http.ResponseWriter) bool {
+ if err := os.MkdirAll(*workDir, 0755); err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return false
}
+ return true
}
func handleWorkDir(w http.ResponseWriter, r *http.Request) {
@@ -1280,6 +1301,9 @@
http.Error(w, "bogus dir", http.StatusBadRequest)
return
}
+ if !mkdirAllWorkdir(w) {
+ return
+ }
base := filepath.Join(*workDir, filepath.FromSlash(dir))
anyOutput := false
err := filepath.Walk(base, func(path string, fi os.FileInfo, err error) error {
diff --git a/cmd/release/release.go b/cmd/release/release.go
index 9d69adc..8a30f2e 100644
--- a/cmd/release/release.go
+++ b/cmd/release/release.go
@@ -532,7 +532,7 @@
}
// And verify there's no other top-level stuff besides the "go" directory:
- if err := checkTopLevelDirs(client); err != nil {
+ if err := b.checkTopLevelDirs(client); err != nil {
return fmt.Errorf("verifying no unwanted top-level directories: %v", err)
}
@@ -544,15 +544,15 @@
// checkTopLevelDirs checks that all files under client's "."
// ($WORKDIR) are are under "go/".
-func checkTopLevelDirs(client *buildlet.Client) error {
+func (b *Build) checkTopLevelDirs(client *buildlet.Client) error {
var badFileErr error // non-nil once an unexpected file/dir is found
if err := client.ListDir(".", buildlet.ListDirOpts{Recursive: true}, func(ent buildlet.DirEntry) {
- if badFileErr != nil {
- return
- }
name := ent.Name()
if !(strings.HasPrefix(name, "go/") || strings.HasPrefix(name, `go\`)) {
- badFileErr = fmt.Errorf("unexpected filename %q found after cleaning", name)
+ b.logf("unexpected file: %q", name)
+ if badFileErr == nil {
+ badFileErr = fmt.Errorf("unexpected filename %q found after cleaning", name)
+ }
}
}); err != nil {
return err