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>
		
			
				
	
	
		
			97 lines
		
	
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			97 lines
		
	
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 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)
 | |
| 	}
 | |
| }
 |