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 |