OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package cipd | 5 package local |
6 | 6 |
7 import ( | 7 import ( |
8 "archive/zip" | 8 "archive/zip" |
9 "bytes" | 9 "bytes" |
10 "fmt" | 10 "fmt" |
11 "io" | 11 "io" |
12 "io/ioutil" | 12 "io/ioutil" |
13 "os" | 13 "os" |
14 "strings" | 14 "strings" |
15 "time" | 15 "time" |
| 16 |
| 17 "infra/libs/logging" |
| 18 "infra/tools/cipd/common" |
16 ) | 19 ) |
17 | 20 |
18 // BuildInstanceOptions defines options for BuildInstance function. | 21 // BuildInstanceOptions defines options for BuildInstance function. |
19 type BuildInstanceOptions struct { | 22 type BuildInstanceOptions struct { |
20 // List of files to add to the package. | 23 // List of files to add to the package. |
21 Input []File | 24 Input []File |
22 // Where to write the package file to. | 25 // Where to write the package file to. |
23 Output io.Writer | 26 Output io.Writer |
24 // Package name, e.g. 'infra/tools/cipd'. | 27 // Package name, e.g. 'infra/tools/cipd'. |
25 PackageName string | 28 PackageName string |
| 29 // Log defines logger to use. |
| 30 Log logging.Logger |
26 } | 31 } |
27 | 32 |
28 // BuildInstance builds a new package instance for package named opts.PackageNam
e | 33 // BuildInstance builds a new package instance for package named opts.PackageNam
e |
29 // by archiving input files (passed via opts.Input). The final binary is written | 34 // by archiving input files (passed via opts.Input). The final binary is written |
30 // to opts.Output. Some output may be written even if BuildInstance eventually | 35 // to opts.Output. Some output may be written even if BuildInstance eventually |
31 // returns an error. | 36 // returns an error. |
32 func BuildInstance(opts BuildInstanceOptions) error { | 37 func BuildInstance(opts BuildInstanceOptions) error { |
33 » err := ValidatePackageName(opts.PackageName) | 38 » if opts.Log == nil { |
| 39 » » opts.Log = logging.DefaultLogger |
| 40 » } |
| 41 » err := common.ValidatePackageName(opts.PackageName) |
34 if err != nil { | 42 if err != nil { |
35 return err | 43 return err |
36 } | 44 } |
37 | 45 |
38 // Make sure no files are written to package service directory. | 46 // Make sure no files are written to package service directory. |
39 for _, f := range opts.Input { | 47 for _, f := range opts.Input { |
40 if strings.HasPrefix(f.Name(), packageServiceDir+"/") { | 48 if strings.HasPrefix(f.Name(), packageServiceDir+"/") { |
41 return fmt.Errorf("Can't write to %s: %s", packageServic
eDir, f.Name()) | 49 return fmt.Errorf("Can't write to %s: %s", packageServic
eDir, f.Name()) |
42 } | 50 } |
43 } | 51 } |
44 | 52 |
45 // Generate the manifest file, add to the list of input files. | 53 // Generate the manifest file, add to the list of input files. |
46 manifestFile, err := makeManifestFile(opts) | 54 manifestFile, err := makeManifestFile(opts) |
47 if err != nil { | 55 if err != nil { |
48 return err | 56 return err |
49 } | 57 } |
50 files := append(opts.Input, manifestFile) | 58 files := append(opts.Input, manifestFile) |
51 | 59 |
52 // Make sure filenames are unique. | 60 // Make sure filenames are unique. |
53 seenNames := make(map[string]struct{}, len(files)) | 61 seenNames := make(map[string]struct{}, len(files)) |
54 for _, f := range files { | 62 for _, f := range files { |
55 _, seen := seenNames[f.Name()] | 63 _, seen := seenNames[f.Name()] |
56 if seen { | 64 if seen { |
57 return fmt.Errorf("File %s is provided twice", f.Name()) | 65 return fmt.Errorf("File %s is provided twice", f.Name()) |
58 } | 66 } |
59 seenNames[f.Name()] = struct{}{} | 67 seenNames[f.Name()] = struct{}{} |
60 } | 68 } |
61 | 69 |
62 // Write the final zip file. | 70 // Write the final zip file. |
63 » return zipInputFiles(files, opts.Output) | 71 » return zipInputFiles(files, opts.Output, opts.Log) |
64 } | 72 } |
65 | 73 |
66 // zipInputFiles deterministically builds a zip archive out of input files and | 74 // zipInputFiles deterministically builds a zip archive out of input files and |
67 // writes it to the writer. Files are written in the order given. | 75 // writes it to the writer. Files are written in the order given. |
68 func zipInputFiles(files []File, w io.Writer) error { | 76 func zipInputFiles(files []File, w io.Writer, log logging.Logger) error { |
69 writer := zip.NewWriter(w) | 77 writer := zip.NewWriter(w) |
70 defer writer.Close() | 78 defer writer.Close() |
71 | 79 |
72 // Reports zipping progress to the log each second. | 80 // Reports zipping progress to the log each second. |
73 lastReport := time.Time{} | 81 lastReport := time.Time{} |
74 progress := func(count int) { | 82 progress := func(count int) { |
75 if time.Since(lastReport) > time.Second { | 83 if time.Since(lastReport) > time.Second { |
76 lastReport = time.Now() | 84 lastReport = time.Now() |
77 log.Infof("Zipping files: %d files left", len(files)-cou
nt) | 85 log.Infof("Zipping files: %d files left", len(files)-cou
nt) |
78 } | 86 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 err := writeManifest(&Manifest{ | 173 err := writeManifest(&Manifest{ |
166 FormatVersion: manifestFormatVersion, | 174 FormatVersion: manifestFormatVersion, |
167 PackageName: opts.PackageName, | 175 PackageName: opts.PackageName, |
168 }, buf) | 176 }, buf) |
169 if err != nil { | 177 if err != nil { |
170 return nil, err | 178 return nil, err |
171 } | 179 } |
172 out := manifestFile(buf.Bytes()) | 180 out := manifestFile(buf.Bytes()) |
173 return &out, nil | 181 return &out, nil |
174 } | 182 } |
OLD | NEW |