| OLD | NEW |
| 1 // Copyright 2017 The LUCI Authors. | 1 // Copyright 2017 The LUCI Authors. |
| 2 // | 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
| 6 // | 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // | 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. | 13 // limitations under the License. |
| 14 | 14 |
| 15 package main | 15 package main |
| 16 | 16 |
| 17 import ( | 17 import ( |
| 18 "encoding/json" | 18 "encoding/json" |
| 19 "fmt" | 19 "fmt" |
| 20 "io/ioutil" |
| 20 "log" | 21 "log" |
| 21 "os" | 22 "os" |
| 22 "path/filepath" | 23 "path/filepath" |
| 24 "strings" |
| 23 | 25 |
| 24 humanize "github.com/dustin/go-humanize" | 26 humanize "github.com/dustin/go-humanize" |
| 25 "github.com/luci/luci-go/common/isolated" | 27 "github.com/luci/luci-go/common/isolated" |
| 26 "github.com/luci/luci-go/common/isolatedclient" | 28 "github.com/luci/luci-go/common/isolatedclient" |
| 27 ) | 29 ) |
| 28 | 30 |
| 29 // UploadTracker uploads and keeps track of files. | 31 // UploadTracker uploads and keeps track of files. |
| 30 type UploadTracker struct { | 32 type UploadTracker struct { |
| 31 checker *Checker | 33 checker *Checker |
| 32 uploader *Uploader | 34 uploader *Uploader |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 } | 133 } |
| 132 log.Printf("QUEUED %q for upload", item.RelPath) | 134 log.Printf("QUEUED %q for upload", item.RelPath) |
| 133 ut.uploader.UploadFile(item, ps, func() { | 135 ut.uploader.UploadFile(item, ps, func() { |
| 134 log.Printf("UPLOADED %q", item.RelPath) | 136 log.Printf("UPLOADED %q", item.RelPath) |
| 135 }) | 137 }) |
| 136 }) | 138 }) |
| 137 } | 139 } |
| 138 return nil | 140 return nil |
| 139 } | 141 } |
| 140 | 142 |
| 141 // Finalize creates and uploads the isolate JSON at the isolatePath. | 143 // Finalize creates and uploads the isolate JSON at the isolatePath, and closes
the checker and uploader. |
| 142 // It returns the corresponding Item and its contents. | 144 // It returns the isolate digest. |
| 145 // If dumpJSONPath is non-empty, the digest is also written to that path as |
| 146 // JSON (in the same format as batch_archive). |
| 143 // Finalize should only be called after UploadDeps. | 147 // Finalize should only be called after UploadDeps. |
| 144 func (ut *UploadTracker) Finalize(isolatedPath string) (*Item, []byte, error) { | 148 func (ut *UploadTracker) Finalize(isolatedPath, dumpJSONPath string) (isolated.H
exDigest, error) { |
| 145 // Marshal the isolated file into JSON, and create an Item to describe i
t. | 149 // Marshal the isolated file into JSON, and create an Item to describe i
t. |
| 146 isolJSON, err := json.Marshal(ut.isol) | 150 isolJSON, err := json.Marshal(ut.isol) |
| 147 if err != nil { | 151 if err != nil { |
| 148 » » return nil, []byte{}, err | 152 » » return "", err |
| 149 } | 153 } |
| 150 isolItem := &Item{ | 154 isolItem := &Item{ |
| 151 Path: isolatedPath, | 155 Path: isolatedPath, |
| 152 RelPath: filepath.Base(isolatedPath), | 156 RelPath: filepath.Base(isolatedPath), |
| 153 Digest: isolated.HashBytes(isolJSON), | 157 Digest: isolated.HashBytes(isolJSON), |
| 154 Size: int64(len(isolJSON)), | 158 Size: int64(len(isolJSON)), |
| 155 } | 159 } |
| 156 | 160 |
| 157 // Check and upload isolate JSON. | 161 // Check and upload isolate JSON. |
| 158 ut.checker.AddItem(isolItem, true, func(item *Item, ps *isolatedclient.P
ushState) { | 162 ut.checker.AddItem(isolItem, true, func(item *Item, ps *isolatedclient.P
ushState) { |
| 159 if ps == nil { | 163 if ps == nil { |
| 160 return | 164 return |
| 161 } | 165 } |
| 162 log.Printf("QUEUED %q for upload", item.RelPath) | 166 log.Printf("QUEUED %q for upload", item.RelPath) |
| 163 ut.uploader.UploadBytes(item.RelPath, isolJSON, ps, func() { | 167 ut.uploader.UploadBytes(item.RelPath, isolJSON, ps, func() { |
| 164 log.Printf("UPLOADED %q", item.RelPath) | 168 log.Printf("UPLOADED %q", item.RelPath) |
| 165 }) | 169 }) |
| 166 }) | 170 }) |
| 167 | 171 |
| 168 » return isolItem, isolJSON, nil | 172 » // Make sure that all pending items have been checked. |
| 173 » if err := ut.checker.Close(); err != nil { |
| 174 » » return "", err |
| 175 » } |
| 176 |
| 177 » // Make sure that all the uploads have completed successfully. |
| 178 » if err := ut.uploader.Close(); err != nil { |
| 179 » » return "", err |
| 180 » } |
| 181 |
| 182 » // Write the isolated file, and emit its digest to stdout. |
| 183 » if err := ioutil.WriteFile(isolatedPath, isolJSON, 0644); err != nil { |
| 184 » » return "", err |
| 185 » } |
| 186 |
| 187 » fmt.Printf("%s\t%s\n", isolItem.Digest, filepath.Base(isolatedPath)) |
| 188 |
| 189 » if err := dumpJSON(isolatedPath, dumpJSONPath, isolItem); err != nil { |
| 190 » » return "", err |
| 191 » } |
| 192 |
| 193 » return isolItem.Digest, nil |
| 169 } | 194 } |
| 195 |
| 196 func dumpJSON(isolatedPath, dumpJSONPath string, isolItem *Item) error { |
| 197 if dumpJSONPath == "" { |
| 198 return nil |
| 199 } |
| 200 // The name is the base name of the isolated file, extension stripped. |
| 201 name := filepath.Base(isolatedPath) |
| 202 if i := strings.LastIndex(name, "."); i != -1 { |
| 203 name = name[:i] |
| 204 } |
| 205 j, err := json.Marshal(map[string]isolated.HexDigest{ |
| 206 name: isolItem.Digest, |
| 207 }) |
| 208 if err != nil { |
| 209 return err |
| 210 } |
| 211 if err := ioutil.WriteFile(dumpJSONPath, j, 0644); err != nil { |
| 212 return err |
| 213 } |
| 214 return nil |
| 215 } |
| OLD | NEW |