feat(gerrit): Create detzip, a small helper utility for packing zips determinstically.
detzip will be used in a patch for the Gerrit bower repository helper, which allows us to get consistent hashes for the output of fetching the dependencies for the Bazel build. Change-Id: I6c87b19815b9d747064108aecbb57ed875d2623b Reviewed-on: https://cl.tvl.fyi/c/depot/+/251 Reviewed-by: lukegb <lukegb@tvl.fyi>
This commit is contained in:
parent
f3d9d5ef49
commit
af167ff8d4
1 changed files with 97 additions and 0 deletions
97
third_party/gerrit/detzip.go
vendored
Normal file
97
third_party/gerrit/detzip.go
vendored
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/zip"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
exclude = flag.String("exclude", "", "comma-separated list of filenames to exclude (in any directory)")
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
flag.Usage = func() {
|
||||||
|
fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s [zip file] [directory]:\n", os.Args[0])
|
||||||
|
flag.PrintDefaults()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func listToMap(ss []string) map[string]bool {
|
||||||
|
m := make(map[string]bool)
|
||||||
|
for _, s := range ss {
|
||||||
|
m[s] = true
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
if flag.NArg() != 2 {
|
||||||
|
flag.Usage()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
outPath := flag.Arg(0)
|
||||||
|
dirPath := flag.Arg(1)
|
||||||
|
|
||||||
|
excludeFiles := listToMap(strings.Split(*exclude, ","))
|
||||||
|
|
||||||
|
// Aggregate all files first.
|
||||||
|
var files []string
|
||||||
|
filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if info.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if excludeFiles[info.Name()] {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
files = append(files, path)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create zip
|
||||||
|
outW, err := os.Create(outPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Create(%q): %v", outPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
zipW := zip.NewWriter(outW)
|
||||||
|
|
||||||
|
// Output files in alphabetical order
|
||||||
|
sort.Strings(files)
|
||||||
|
for _, f := range files {
|
||||||
|
fw, err := zipW.CreateHeader(&zip.FileHeader{
|
||||||
|
Name: f,
|
||||||
|
Method: zip.Store,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("creating %q in zip: %v", f, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ff, err := os.Open(f)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("opening %q: %v", f, err)
|
||||||
|
}
|
||||||
|
if _, err := io.Copy(fw, ff); err != nil {
|
||||||
|
log.Fatalf("copying %q to zip: %v", f, err)
|
||||||
|
}
|
||||||
|
ff.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := zipW.Close(); err != nil {
|
||||||
|
log.Fatalf("writing ZIP central directory: %v", err)
|
||||||
|
}
|
||||||
|
if err := outW.Close(); err != nil {
|
||||||
|
log.Fatalf("closing ZIP file: %v", err)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue