Merge changes Iac19fbd3,Id4707189
* changes: Improve soong_zip filename collisions Add soong_zip -D to zip whole directories
This commit is contained in:
@@ -68,6 +68,7 @@ const manifestDest = "META-INF/MANIFEST.MF"
|
|||||||
type fileArg struct {
|
type fileArg struct {
|
||||||
pathPrefixInZip, sourcePrefixToStrip string
|
pathPrefixInZip, sourcePrefixToStrip string
|
||||||
sourceFiles []string
|
sourceFiles []string
|
||||||
|
globDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
type pathMapping struct {
|
type pathMapping struct {
|
||||||
@@ -97,13 +98,15 @@ type file struct{}
|
|||||||
|
|
||||||
type listFiles struct{}
|
type listFiles struct{}
|
||||||
|
|
||||||
|
type dir struct{}
|
||||||
|
|
||||||
func (f *file) String() string {
|
func (f *file) String() string {
|
||||||
return `""`
|
return `""`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *file) Set(s string) error {
|
func (f *file) Set(s string) error {
|
||||||
if *relativeRoot == "" {
|
if *relativeRoot == "" {
|
||||||
return fmt.Errorf("must pass -C before -f or -l")
|
return fmt.Errorf("must pass -C before -f")
|
||||||
}
|
}
|
||||||
|
|
||||||
fArgs = append(fArgs, fileArg{
|
fArgs = append(fArgs, fileArg{
|
||||||
@@ -121,7 +124,7 @@ func (l *listFiles) String() string {
|
|||||||
|
|
||||||
func (l *listFiles) Set(s string) error {
|
func (l *listFiles) Set(s string) error {
|
||||||
if *relativeRoot == "" {
|
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)
|
list, err := ioutil.ReadFile(s)
|
||||||
@@ -138,12 +141,30 @@ func (l *listFiles) Set(s string) error {
|
|||||||
return nil
|
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 (
|
var (
|
||||||
out = flag.String("o", "", "file to write zip file to")
|
out = flag.String("o", "", "file to write zip file to")
|
||||||
manifest = flag.String("m", "", "input jar manifest file name")
|
manifest = flag.String("m", "", "input jar manifest file name")
|
||||||
directories = flag.Bool("d", false, "include directories in zip")
|
directories = flag.Bool("d", false, "include directories in zip")
|
||||||
rootPrefix = flag.String("P", "", "path prefix within the zip at which to place files")
|
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")
|
parallelJobs = flag.Int("j", runtime.NumCPU(), "number of parallel threads to use")
|
||||||
compLevel = flag.Int("L", 5, "deflate compression level (0-9)")
|
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'")
|
emulateJar = flag.Bool("jar", false, "modify the resultant .zip to emulate the output of 'jar'")
|
||||||
@@ -157,6 +178,7 @@ var (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
flag.Var(&listFiles{}, "l", "file containing list of .class files")
|
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(&file{}, "f", "file to include in zip")
|
||||||
flag.Var(&nonDeflatedFiles, "s", "file path to be stored within the zip without compression")
|
flag.Var(&nonDeflatedFiles, "s", "file path to be stored within the zip without compression")
|
||||||
}
|
}
|
||||||
@@ -168,9 +190,10 @@ func usage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type zipWriter struct {
|
type zipWriter struct {
|
||||||
time time.Time
|
time time.Time
|
||||||
createdDirs map[string]bool
|
createdFiles map[string]string
|
||||||
directories bool
|
createdDirs map[string]string
|
||||||
|
directories bool
|
||||||
|
|
||||||
errors chan error
|
errors chan error
|
||||||
writeOps chan chan *zipEntry
|
writeOps chan chan *zipEntry
|
||||||
@@ -232,19 +255,23 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
w := &zipWriter{
|
w := &zipWriter{
|
||||||
time: time.Date(2009, 1, 1, 0, 0, 0, 0, time.UTC),
|
time: time.Date(2009, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||||
createdDirs: make(map[string]bool),
|
createdDirs: make(map[string]string),
|
||||||
directories: *directories,
|
createdFiles: make(map[string]string),
|
||||||
compLevel: *compLevel,
|
directories: *directories,
|
||||||
|
compLevel: *compLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
pathMappings := []pathMapping{}
|
pathMappings := []pathMapping{}
|
||||||
set := make(map[string]string)
|
|
||||||
|
|
||||||
for _, fa := range fArgs {
|
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,
|
if err := fillPathPairs(fa.pathPrefixInZip,
|
||||||
fa.sourcePrefixToStrip, src, set, &pathMappings); err != nil {
|
fa.sourcePrefixToStrip, src, &pathMappings); err != nil {
|
||||||
log.Fatal(err)
|
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)
|
src = strings.TrimSpace(src)
|
||||||
if src == "" {
|
if src == "" {
|
||||||
return nil
|
return nil
|
||||||
@@ -269,14 +296,6 @@ func fillPathPairs(prefix, rel, src string, set map[string]string, pathMappings
|
|||||||
}
|
}
|
||||||
dest = filepath.Join(prefix, dest)
|
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
|
zipMethod := zip.Deflate
|
||||||
if _, found := nonDeflatedFiles[dest]; found {
|
if _, found := nonDeflatedFiles[dest]; found {
|
||||||
zipMethod = zip.Store
|
zipMethod = zip.Store
|
||||||
@@ -462,14 +481,29 @@ func (z *zipWriter) addFile(dest, src string, method uint16) error {
|
|||||||
return err
|
return err
|
||||||
} else if s.IsDir() {
|
} else if s.IsDir() {
|
||||||
if z.directories {
|
if z.directories {
|
||||||
return z.writeDirectory(dest)
|
return z.writeDirectory(dest, src)
|
||||||
}
|
}
|
||||||
return nil
|
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 {
|
} 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()
|
fileSize = s.Size()
|
||||||
executable = s.Mode()&0100 != 0
|
executable = s.Mode()&0100 != 0
|
||||||
}
|
}
|
||||||
@@ -492,13 +526,19 @@ func (z *zipWriter) addFile(dest, src string, method uint16) error {
|
|||||||
return z.writeFileContents(header, r)
|
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 {
|
func (z *zipWriter) addManifest(dest string, src string, method uint16) error {
|
||||||
givenBytes, err := ioutil.ReadFile(src)
|
givenBytes, err := ioutil.ReadFile(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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:")
|
manifestMarker := []byte("Manifest-Version:")
|
||||||
header := append(manifestMarker, []byte(" 1.0\nCreated-By: soong_zip\n")...)
|
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)
|
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)
|
compressChan := make(chan *zipEntry, 1)
|
||||||
z.writeOps <- compressChan
|
z.writeOps <- compressChan
|
||||||
|
|
||||||
@@ -755,53 +786,57 @@ func (z *zipWriter) addExtraField(zipHeader *zip.FileHeader, fieldHeader [2]byte
|
|||||||
zipHeader.Extra = append(zipHeader.Extra, data...)
|
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
|
// clean the input
|
||||||
cleanDir := filepath.Clean(dir)
|
dir = filepath.Clean(dir)
|
||||||
|
|
||||||
// discover any uncreated directories in the path
|
// discover any uncreated directories in the path
|
||||||
zipDirs := []string{}
|
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
|
// 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
|
if z.directories {
|
||||||
for _, cleanDir := range zipDirs {
|
// make a directory entry for each uncreated directory
|
||||||
dirHeader := &zip.FileHeader{
|
for _, cleanDir := range zipDirs {
|
||||||
Name: cleanDir + "/",
|
dirHeader := &zip.FileHeader{
|
||||||
}
|
Name: cleanDir + "/",
|
||||||
dirHeader.SetMode(0700 | os.ModeDir)
|
}
|
||||||
dirHeader.SetModTime(z.time)
|
dirHeader.SetMode(0700 | os.ModeDir)
|
||||||
|
dirHeader.SetModTime(z.time)
|
||||||
|
|
||||||
if *emulateJar && dir == "META-INF/" {
|
if *emulateJar && dir == "META-INF/" {
|
||||||
// Jar files have a 0-length extra field with header "CAFE"
|
// Jar files have a 0-length extra field with header "CAFE"
|
||||||
z.addExtraField(dirHeader, [2]byte{0xca, 0xfe}, []byte{})
|
z.addExtraField(dirHeader, [2]byte{0xca, 0xfe}, []byte{})
|
||||||
}
|
}
|
||||||
|
|
||||||
ze := make(chan *zipEntry, 1)
|
ze := make(chan *zipEntry, 1)
|
||||||
ze <- &zipEntry{
|
ze <- &zipEntry{
|
||||||
fh: dirHeader,
|
fh: dirHeader,
|
||||||
|
}
|
||||||
|
close(ze)
|
||||||
|
z.writeOps <- ze
|
||||||
}
|
}
|
||||||
close(ze)
|
|
||||||
z.writeOps <- ze
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (z *zipWriter) writeSymlink(rel, file string) error {
|
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{
|
fileHeader := &zip.FileHeader{
|
||||||
Name: rel,
|
Name: rel,
|
||||||
}
|
}
|
||||||
@@ -830,3 +865,15 @@ func (z *zipWriter) writeSymlink(rel, file string) error {
|
|||||||
|
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user