Merge changes Iac19fbd3,Id4707189

* changes:
  Improve soong_zip filename collisions
  Add soong_zip -D to zip whole directories
This commit is contained in:
Colin Cross
2017-08-31 20:29:27 +00:00
committed by Gerrit Code Review

View File

@@ -68,6 +68,7 @@ const manifestDest = "META-INF/MANIFEST.MF"
type fileArg struct {
pathPrefixInZip, sourcePrefixToStrip string
sourceFiles []string
globDir string
}
type pathMapping struct {
@@ -97,13 +98,15 @@ type file struct{}
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) String() string {
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 @@ func (l *listFiles) Set(s string) error {
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 @@ var (
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 @@ func usage() {
}
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 @@ func main() {
}
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 main() {
}
}
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 @@ func fillPathPairs(prefix, rel, src string, set map[string]string, pathMappings
}
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 @@ func (z *zipWriter) addFile(dest, src string, method uint16) error {
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 @@ func (z *zipWriter) addFile(dest, src string, method uint16) error {
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 @@ func (z *zipWriter) writeFileContents(header *zip.FileHeader, r readerSeekerClos
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 @@ func (z *zipWriter) addExtraField(zipHeader *zip.FileHeader, fieldHeader [2]byte
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 @@ func (z *zipWriter) writeSymlink(rel, file string) error {
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
}