github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/cmd/zipsync/zipsync.go (about)

     1  // Copyright 2018 Google Inc. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (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
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package main
    16  
    17  import (
    18  	"archive/zip"
    19  	"flag"
    20  	"fmt"
    21  	"io"
    22  	"io/ioutil"
    23  	"log"
    24  	"os"
    25  	"path/filepath"
    26  	"strings"
    27  )
    28  
    29  var (
    30  	outputDir  = flag.String("d", "", "output dir")
    31  	outputFile = flag.String("l", "", "output list file")
    32  	filter     = flag.String("f", "", "optional filter pattern")
    33  )
    34  
    35  func must(err error) {
    36  	if err != nil {
    37  		log.Fatal(err)
    38  	}
    39  }
    40  
    41  func writeFile(filename string, in io.Reader, perm os.FileMode) error {
    42  	out, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
    43  	if err != nil {
    44  		return err
    45  	}
    46  	_, err = io.Copy(out, in)
    47  	if err != nil {
    48  		out.Close()
    49  		return err
    50  	}
    51  
    52  	return out.Close()
    53  }
    54  
    55  func main() {
    56  	flag.Usage = func() {
    57  		fmt.Fprintln(os.Stderr, "usage: zipsync -d <output dir> [-l <output file>] [-f <pattern>] [zip]...")
    58  		flag.PrintDefaults()
    59  	}
    60  
    61  	flag.Parse()
    62  
    63  	if *outputDir == "" {
    64  		flag.Usage()
    65  		os.Exit(1)
    66  	}
    67  
    68  	inputs := flag.Args()
    69  
    70  	// For now, just wipe the output directory and replace its contents with the zip files
    71  	// Eventually this could only modify the directory contents as necessary to bring it up
    72  	// to date with the zip files.
    73  	must(os.RemoveAll(*outputDir))
    74  
    75  	must(os.MkdirAll(*outputDir, 0777))
    76  
    77  	var files []string
    78  	seen := make(map[string]string)
    79  
    80  	for _, input := range inputs {
    81  		reader, err := zip.OpenReader(input)
    82  		if err != nil {
    83  			log.Fatal(err)
    84  		}
    85  		defer reader.Close()
    86  
    87  		for _, f := range reader.File {
    88  			if *filter != "" {
    89  				if match, err := filepath.Match(*filter, filepath.Base(f.Name)); err != nil {
    90  					log.Fatal(err)
    91  				} else if !match {
    92  					continue
    93  				}
    94  			}
    95  			if filepath.IsAbs(f.Name) {
    96  				log.Fatalf("%q in %q is an absolute path", f.Name, input)
    97  			}
    98  
    99  			if prev, exists := seen[f.Name]; exists {
   100  				log.Fatalf("%q found in both %q and %q", f.Name, prev, input)
   101  			}
   102  			seen[f.Name] = input
   103  
   104  			filename := filepath.Join(*outputDir, f.Name)
   105  			if f.FileInfo().IsDir() {
   106  				must(os.MkdirAll(filename, f.FileInfo().Mode()))
   107  			} else {
   108  				must(os.MkdirAll(filepath.Dir(filename), 0777))
   109  				in, err := f.Open()
   110  				if err != nil {
   111  					log.Fatal(err)
   112  				}
   113  				must(writeFile(filename, in, f.FileInfo().Mode()))
   114  				in.Close()
   115  				files = append(files, filename)
   116  			}
   117  		}
   118  	}
   119  
   120  	if *outputFile != "" {
   121  		data := strings.Join(files, "\n") + "\n"
   122  		must(ioutil.WriteFile(*outputFile, []byte(data), 0666))
   123  	}
   124  }