Merge changes Iac19fbd3,Id4707189
* changes:
Improve soong_zip filename collisions
Add soong_zip -D to zip whole directories
diff --git a/cmd/soong_zip/soong_zip.go b/cmd/soong_zip/soong_zip.go
index 4eb4ebe..ae176df 100644
--- a/cmd/soong_zip/soong_zip.go
+++ b/cmd/soong_zip/soong_zip.go
@@ -68,6 +68,7 @@
type fileArg struct {
pathPrefixInZip, sourcePrefixToStrip string
sourceFiles []string
+ globDir string
}
type pathMapping struct {
@@ -97,13 +98,15 @@
type listFiles struct{}
+type dir struct{}
+
func (f *file) String() string {
return `""`
}
func (f *file) Set(s string) error {
if *relativeRoot == "" {
- return fmt.Errorf("must pass -C before -f or -l")
+ return fmt.Errorf("must pass -C before -f")
}
fArgs = append(fArgs, fileArg{
@@ -121,7 +124,7 @@
func (l *listFiles) Set(s string) error {
if *relativeRoot == "" {
- return fmt.Errorf("must pass -C before -f or -l")
+ return fmt.Errorf("must pass -C before -l")
}
list, err := ioutil.ReadFile(s)
@@ -138,12 +141,30 @@
return nil
}
+func (d *dir) String() string {
+ return `""`
+}
+
+func (d *dir) Set(s string) error {
+ if *relativeRoot == "" {
+ return fmt.Errorf("must pass -C before -D")
+ }
+
+ fArgs = append(fArgs, fileArg{
+ pathPrefixInZip: filepath.Clean(*rootPrefix),
+ sourcePrefixToStrip: filepath.Clean(*relativeRoot),
+ globDir: filepath.Clean(s),
+ })
+
+ return nil
+}
+
var (
out = flag.String("o", "", "file to write zip file to")
manifest = flag.String("m", "", "input jar manifest file name")
directories = flag.Bool("d", false, "include directories in zip")
rootPrefix = flag.String("P", "", "path prefix within the zip at which to place files")
- relativeRoot = flag.String("C", "", "path to use as relative root of files in next -f or -l argument")
+ relativeRoot = flag.String("C", "", "path to use as relative root of files in following -f, -l, or -D arguments")
parallelJobs = flag.Int("j", runtime.NumCPU(), "number of parallel threads to use")
compLevel = flag.Int("L", 5, "deflate compression level (0-9)")
emulateJar = flag.Bool("jar", false, "modify the resultant .zip to emulate the output of 'jar'")
@@ -157,6 +178,7 @@
func init() {
flag.Var(&listFiles{}, "l", "file containing list of .class files")
+ flag.Var(&dir{}, "D", "directory to include in zip")
flag.Var(&file{}, "f", "file to include in zip")
flag.Var(&nonDeflatedFiles, "s", "file path to be stored within the zip without compression")
}
@@ -168,9 +190,10 @@
}
type zipWriter struct {
- time time.Time
- createdDirs map[string]bool
- directories bool
+ time time.Time
+ createdFiles map[string]string
+ createdDirs map[string]string
+ directories bool
errors chan error
writeOps chan chan *zipEntry
@@ -232,19 +255,23 @@
}
w := &zipWriter{
- time: time.Date(2009, 1, 1, 0, 0, 0, 0, time.UTC),
- createdDirs: make(map[string]bool),
- directories: *directories,
- compLevel: *compLevel,
+ time: time.Date(2009, 1, 1, 0, 0, 0, 0, time.UTC),
+ createdDirs: make(map[string]string),
+ createdFiles: make(map[string]string),
+ directories: *directories,
+ compLevel: *compLevel,
}
pathMappings := []pathMapping{}
- set := make(map[string]string)
for _, fa := range fArgs {
- for _, src := range fa.sourceFiles {
+ srcs := fa.sourceFiles
+ if fa.globDir != "" {
+ srcs = append(srcs, recursiveGlobFiles(fa.globDir)...)
+ }
+ for _, src := range srcs {
if err := fillPathPairs(fa.pathPrefixInZip,
- fa.sourcePrefixToStrip, src, set, &pathMappings); err != nil {
+ fa.sourcePrefixToStrip, src, &pathMappings); err != nil {
log.Fatal(err)
}
}
@@ -257,7 +284,7 @@
}
}
-func fillPathPairs(prefix, rel, src string, set map[string]string, pathMappings *[]pathMapping) error {
+func fillPathPairs(prefix, rel, src string, pathMappings *[]pathMapping) error {
src = strings.TrimSpace(src)
if src == "" {
return nil
@@ -269,14 +296,6 @@
}
dest = filepath.Join(prefix, dest)
- if _, found := set[dest]; found {
- return fmt.Errorf("found two file paths to be copied into dest path: %q,"+
- " both [%q]%q and [%q]%q!",
- dest, dest, src, dest, set[dest])
- } else {
- set[dest] = src
- }
-
zipMethod := zip.Deflate
if _, found := nonDeflatedFiles[dest]; found {
zipMethod = zip.Store
@@ -462,14 +481,29 @@
return err
} else if s.IsDir() {
if z.directories {
- return z.writeDirectory(dest)
+ return z.writeDirectory(dest, src)
}
return nil
- } else if s.Mode()&os.ModeSymlink != 0 {
- return z.writeSymlink(dest, src)
- } else if !s.Mode().IsRegular() {
- return fmt.Errorf("%s is not a file, directory, or symlink", src)
} else {
+ if err := z.writeDirectory(filepath.Dir(dest), src); err != nil {
+ return err
+ }
+
+ if prev, exists := z.createdDirs[dest]; exists {
+ return fmt.Errorf("destination %q is both a directory %q and a file %q", dest, prev, src)
+ }
+ if prev, exists := z.createdFiles[dest]; exists {
+ return fmt.Errorf("destination %q has two files %q and %q", dest, prev, src)
+ }
+
+ z.createdFiles[dest] = src
+
+ if s.Mode()&os.ModeSymlink != 0 {
+ return z.writeSymlink(dest, src)
+ } else if !s.Mode().IsRegular() {
+ return fmt.Errorf("%s is not a file, directory, or symlink", src)
+ }
+
fileSize = s.Size()
executable = s.Mode()&0100 != 0
}
@@ -492,13 +526,19 @@
return z.writeFileContents(header, r)
}
-// writes the contents of r according to the specifications in header
func (z *zipWriter) addManifest(dest string, src string, method uint16) error {
givenBytes, err := ioutil.ReadFile(src)
if err != nil {
return err
}
+ if prev, exists := z.createdDirs[dest]; exists {
+ return fmt.Errorf("destination %q is both a directory %q and a file %q", dest, prev, src)
+ }
+ if prev, exists := z.createdFiles[dest]; exists {
+ return fmt.Errorf("destination %q has two files %q and %q", dest, prev, src)
+ }
+
manifestMarker := []byte("Manifest-Version:")
header := append(manifestMarker, []byte(" 1.0\nCreated-By: soong_zip\n")...)
@@ -526,15 +566,6 @@
header.SetModTime(z.time)
- if z.directories {
- dest := header.Name
- dir, _ := filepath.Split(dest)
- err := z.writeDirectory(dir)
- if err != nil {
- return err
- }
- }
-
compressChan := make(chan *zipEntry, 1)
z.writeOps <- compressChan
@@ -755,53 +786,57 @@
zipHeader.Extra = append(zipHeader.Extra, data...)
}
-func (z *zipWriter) writeDirectory(dir string) error {
+// writeDirectory annotates that dir is a directory created for the src file or directory, and adds
+// the directory entry to the zip file if directories are enabled.
+func (z *zipWriter) writeDirectory(dir, src string) error {
// clean the input
- cleanDir := filepath.Clean(dir)
+ dir = filepath.Clean(dir)
// discover any uncreated directories in the path
zipDirs := []string{}
- for cleanDir != "" && cleanDir != "." && !z.createdDirs[cleanDir] {
+ for dir != "" && dir != "." {
+ if _, exists := z.createdDirs[dir]; exists {
+ break
+ }
- z.createdDirs[cleanDir] = true
+ if prev, exists := z.createdFiles[dir]; exists {
+ return fmt.Errorf("destination %q is both a directory %q and a file %q", dir, src, prev)
+ }
+
+ z.createdDirs[dir] = src
// parent directories precede their children
- zipDirs = append([]string{cleanDir}, zipDirs...)
+ zipDirs = append([]string{dir}, zipDirs...)
- cleanDir = filepath.Dir(cleanDir)
+ dir = filepath.Dir(dir)
}
- // make a directory entry for each uncreated directory
- for _, cleanDir := range zipDirs {
- dirHeader := &zip.FileHeader{
- Name: cleanDir + "/",
- }
- dirHeader.SetMode(0700 | os.ModeDir)
- dirHeader.SetModTime(z.time)
+ if z.directories {
+ // make a directory entry for each uncreated directory
+ for _, cleanDir := range zipDirs {
+ dirHeader := &zip.FileHeader{
+ Name: cleanDir + "/",
+ }
+ dirHeader.SetMode(0700 | os.ModeDir)
+ dirHeader.SetModTime(z.time)
- if *emulateJar && dir == "META-INF/" {
- // Jar files have a 0-length extra field with header "CAFE"
- z.addExtraField(dirHeader, [2]byte{0xca, 0xfe}, []byte{})
- }
+ if *emulateJar && dir == "META-INF/" {
+ // Jar files have a 0-length extra field with header "CAFE"
+ z.addExtraField(dirHeader, [2]byte{0xca, 0xfe}, []byte{})
+ }
- ze := make(chan *zipEntry, 1)
- ze <- &zipEntry{
- fh: dirHeader,
+ ze := make(chan *zipEntry, 1)
+ ze <- &zipEntry{
+ fh: dirHeader,
+ }
+ close(ze)
+ z.writeOps <- ze
}
- close(ze)
- z.writeOps <- ze
}
return nil
}
func (z *zipWriter) writeSymlink(rel, file string) error {
- if z.directories {
- dir, _ := filepath.Split(rel)
- if err := z.writeDirectory(dir); err != nil {
- return err
- }
- }
-
fileHeader := &zip.FileHeader{
Name: rel,
}
@@ -830,3 +865,15 @@
return nil
}
+
+func recursiveGlobFiles(path string) []string {
+ var files []string
+ filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
+ if !info.IsDir() {
+ files = append(files, path)
+ }
+ return nil
+ })
+
+ return files
+}