| 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, |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 } | 140 } |
| 141 return nil | 141 return nil |
| 142 } | 142 } |
| 143 | 143 |
| 144 // Finalize creates and uploads the isolate JSON at the isolatePath, and closes
the checker and uploader. | 144 // Finalize creates and uploads the isolate JSON at the isolatePath, and closes
the checker and uploader. |
| 145 // It returns the isolate digest. | 145 // It returns the isolate digest. |
| 146 // If dumpJSONPath is non-empty, the digest is also written to that path as | 146 // If dumpJSONPath is non-empty, the digest is also written to that path as |
| 147 // JSON (in the same format as batch_archive). | 147 // JSON (in the same format as batch_archive). |
| 148 // Finalize should only be called after UploadDeps. | 148 // Finalize should only be called after UploadDeps. |
| 149 func (ut *UploadTracker) Finalize(isolatedPath string, dumpJSONWriter io.Writer)
(isolated.HexDigest, error) { | 149 func (ut *UploadTracker) Finalize(isolatedPath string, dumpJSONWriter io.Writer)
(isolated.HexDigest, error) { |
| 150 » // Marshal the isolated file into JSON, and create an Item to describe i
t. | 150 » isolFile, err := newIsolatedFile(ut.isol, isolatedPath) |
| 151 » isolJSON, err := json.Marshal(ut.isol) | |
| 152 if err != nil { | 151 if err != nil { |
| 153 return "", err | 152 return "", err |
| 154 } | 153 } |
| 155 isolItem := &Item{ | |
| 156 Path: isolatedPath, | |
| 157 RelPath: filepath.Base(isolatedPath), | |
| 158 Digest: isolated.HashBytes(isolJSON), | |
| 159 Size: int64(len(isolJSON)), | |
| 160 } | |
| 161 | 154 |
| 162 // Check and upload isolate JSON. | 155 // Check and upload isolate JSON. |
| 163 » ut.checker.AddItem(isolItem, true, func(item *Item, ps *isolatedclient.P
ushState) { | 156 » ut.checker.AddItem(isolFile.item(), true, func(item *Item, ps *isolatedc
lient.PushState) { |
| 164 if ps == nil { | 157 if ps == nil { |
| 165 return | 158 return |
| 166 } | 159 } |
| 167 log.Printf("QUEUED %q for upload", item.RelPath) | 160 log.Printf("QUEUED %q for upload", item.RelPath) |
| 168 » » ut.uploader.UploadBytes(item.RelPath, isolJSON, ps, func() { | 161 » » ut.uploader.UploadBytes(item.RelPath, isolFile.contents(), ps, f
unc() { |
| 169 log.Printf("UPLOADED %q", item.RelPath) | 162 log.Printf("UPLOADED %q", item.RelPath) |
| 170 }) | 163 }) |
| 171 }) | 164 }) |
| 172 | 165 |
| 173 // Make sure that all pending items have been checked. | 166 // Make sure that all pending items have been checked. |
| 174 if err := ut.checker.Close(); err != nil { | 167 if err := ut.checker.Close(); err != nil { |
| 175 return "", err | 168 return "", err |
| 176 } | 169 } |
| 177 | 170 |
| 178 // Make sure that all the uploads have completed successfully. | 171 // Make sure that all the uploads have completed successfully. |
| 179 if err := ut.uploader.Close(); err != nil { | 172 if err := ut.uploader.Close(); err != nil { |
| 180 return "", err | 173 return "", err |
| 181 } | 174 } |
| 182 | 175 |
| 183 // Write the isolated file, and emit its digest to stdout. | 176 // Write the isolated file, and emit its digest to stdout. |
| 184 » if err := ioutil.WriteFile(isolatedPath, isolJSON, 0644); err != nil { | 177 » if err := isolFile.writeJSONFile(); err != nil { |
| 185 return "", err | 178 return "", err |
| 186 } | 179 } |
| 187 | 180 |
| 188 » fmt.Printf("%s\t%s\n", isolItem.Digest, filepath.Base(isolatedPath)) | 181 » fmt.Printf("%s\t%s\n", isolFile.item().Digest, filepath.Base(isolatedPat
h)) |
| 189 | 182 |
| 190 » if err := dumpJSON(isolatedPath, dumpJSONWriter, isolItem); err != nil { | 183 » if err := dumpJSON(isolFile.name(), dumpJSONWriter, isolFile.item()); er
r != nil { |
| 191 return "", err | 184 return "", err |
| 192 } | 185 } |
| 193 | 186 |
| 194 » return isolItem.Digest, nil | 187 » return isolFile.item().Digest, nil |
| 195 } | 188 } |
| 196 | 189 |
| 197 func dumpJSON(isolatedPath string, dumpJSONWriter io.Writer, isolItem *Item) err
or { | 190 func dumpJSON(isolName string, dumpJSONWriter io.Writer, isolItem *Item) error { |
| 198 » // The name is the base name of the isolated file, extension stripped. | 191 » enc := json.NewEncoder(dumpJSONWriter) |
| 199 » name := filepath.Base(isolatedPath) | 192 » return enc.Encode(map[string]isolated.HexDigest{ |
| 193 » » isolName: isolItem.Digest, |
| 194 » }) |
| 195 } |
| 196 |
| 197 // isolatedFile is an isolated file which is stored in memory. |
| 198 // It can produce a corresponding Item, for upload to the server, |
| 199 // and also write its contents to the filesystem. |
| 200 type isolatedFile struct { |
| 201 » json []byte |
| 202 » path string |
| 203 } |
| 204 |
| 205 func newIsolatedFile(isol *isolated.Isolated, path string) (*isolatedFile, error
) { |
| 206 » j, err := json.Marshal(isol) |
| 207 » if err != nil { |
| 208 » » return &isolatedFile{}, err |
| 209 » } |
| 210 » return &isolatedFile{json: j, path: path}, nil |
| 211 } |
| 212 |
| 213 // item creates an *Item to represent the isolated JSON file. |
| 214 func (ij *isolatedFile) item() *Item { |
| 215 » return &Item{ |
| 216 » » Path: ij.path, |
| 217 » » RelPath: filepath.Base(ij.path), |
| 218 » » Digest: isolated.HashBytes(ij.json), |
| 219 » » Size: int64(len(ij.json)), |
| 220 » } |
| 221 } |
| 222 |
| 223 func (ij *isolatedFile) contents() []byte { |
| 224 » return ij.json |
| 225 } |
| 226 |
| 227 // writeJSONFile writes the file contents to the filesystem. |
| 228 func (ij *isolatedFile) writeJSONFile() error { |
| 229 » return ioutil.WriteFile(ij.path, ij.json, 0644) |
| 230 } |
| 231 |
| 232 // name returns the base name of the isolated file, extension stripped. |
| 233 func (ij *isolatedFile) name() string { |
| 234 » name := filepath.Base(ij.path) |
| 200 if i := strings.LastIndex(name, "."); i != -1 { | 235 if i := strings.LastIndex(name, "."); i != -1 { |
| 201 name = name[:i] | 236 name = name[:i] |
| 202 } | 237 } |
| 203 | 238 » return name |
| 204 » enc := json.NewEncoder(dumpJSONWriter) | |
| 205 » return enc.Encode(map[string]isolated.HexDigest{ | |
| 206 » » name: isolItem.Digest, | |
| 207 » }) | |
| 208 } | 239 } |
| OLD | NEW |