diff options
author | 2019-06-17 14:12:41 -0700 | |
---|---|---|
committer | 2019-06-18 13:33:20 -0700 | |
commit | 9cb51dbc0b4fe0e60ec604f3fa1440014c669e13 (patch) | |
tree | a789d3a54ffd0dd5a26df021b0d4939de5833d61 /zip | |
parent | 5d7409ba0f13c2ed554035bba0dd19282b52a9a9 (diff) |
Support moving sources in srcjars in soong_zip
Add a -srcjar argument to soong_zip that causes it to read the
package statement of each .java file and use that to place the
source file at a path that matches the package.
Test: jar_test.go, zip_test.go
Change-Id: I36017e42445ba3b0a82a10a8d81e8ac0cca096f2
Diffstat (limited to 'zip')
-rw-r--r-- | zip/cmd/main.go | 2 | ||||
-rw-r--r-- | zip/zip.go | 88 | ||||
-rw-r--r-- | zip/zip_test.go | 95 |
3 files changed, 149 insertions, 36 deletions
diff --git a/zip/cmd/main.go b/zip/cmd/main.go index 6f40a3e0a..fba2e4b1e 100644 --- a/zip/cmd/main.go +++ b/zip/cmd/main.go @@ -136,6 +136,7 @@ func main() { writeIfChanged := flags.Bool("write_if_changed", false, "only update resultant .zip if it has changed") ignoreMissingFiles := flags.Bool("ignore_missing_files", false, "continue if a requested file does not exist") symlinks := flags.Bool("symlinks", true, "store symbolic links in zip instead of following them") + srcJar := flags.Bool("srcjar", false, "move .java files to locations that match their package statement") parallelJobs := flags.Int("parallel", runtime.NumCPU(), "number of parallel threads to use") cpuProfile := flags.String("cpuprofile", "", "write cpu profile to file") @@ -191,6 +192,7 @@ func main() { FileArgs: fileArgsBuilder.FileArgs(), OutputFilePath: *out, EmulateJar: *emulateJar, + SrcJar: *srcJar, AddDirectoryEntriesToZip: *directories, CompressionLevel: *compLevel, ManifestSourcePath: *manifest, diff --git a/zip/zip.go b/zip/zip.go index 1f5fe4335..707c4ef16 100644 --- a/zip/zip.go +++ b/zip/zip.go @@ -210,6 +210,7 @@ type ZipArgs struct { FileArgs []FileArg OutputFilePath string EmulateJar bool + SrcJar bool AddDirectoryEntriesToZip bool CompressionLevel int ManifestSourcePath string @@ -364,7 +365,7 @@ func ZipTo(args ZipArgs, w io.Writer) error { } } - return z.write(w, pathMappings, args.ManifestSourcePath, args.EmulateJar, args.NumParallelJobs) + return z.write(w, pathMappings, args.ManifestSourcePath, args.EmulateJar, args.SrcJar, args.NumParallelJobs) } func Zip(args ZipArgs) error { @@ -446,7 +447,9 @@ func jarSort(mappings []pathMapping) { sort.SliceStable(mappings, less) } -func (z *ZipWriter) write(f io.Writer, pathMappings []pathMapping, manifest string, emulateJar bool, parallelJobs int) error { +func (z *ZipWriter) write(f io.Writer, pathMappings []pathMapping, manifest string, emulateJar, srcJar bool, + parallelJobs int) error { + z.errors = make(chan error) defer close(z.errors) @@ -489,7 +492,7 @@ func (z *ZipWriter) write(f io.Writer, pathMappings []pathMapping, manifest stri if emulateJar && ele.dest == jar.ManifestFile { err = z.addManifest(ele.dest, ele.src, ele.zipMethod) } else { - err = z.addFile(ele.dest, ele.src, ele.zipMethod, emulateJar) + err = z.addFile(ele.dest, ele.src, ele.zipMethod, emulateJar, srcJar) } if err != nil { z.errors <- err @@ -588,7 +591,7 @@ func (z *ZipWriter) write(f io.Writer, pathMappings []pathMapping, manifest stri } // imports (possibly with compression) <src> into the zip at sub-path <dest> -func (z *ZipWriter) addFile(dest, src string, method uint16, emulateJar bool) error { +func (z *ZipWriter) addFile(dest, src string, method uint16, emulateJar, srcJar bool) error { var fileSize int64 var executable bool @@ -606,12 +609,9 @@ func (z *ZipWriter) addFile(dest, src string, method uint16, emulateJar bool) er return nil } return err - } else if s.IsDir() { - if z.directories { - return z.writeDirectory(dest, src, emulateJar) - } - return nil - } else { + } + + createParentDirs := func(dest, src string) error { if err := z.writeDirectory(filepath.Dir(dest), src, emulateJar); err != nil { return err } @@ -625,32 +625,64 @@ func (z *ZipWriter) addFile(dest, src string, method uint16, emulateJar bool) er 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) + return nil + } + + if s.IsDir() { + if z.directories { + return z.writeDirectory(dest, src, emulateJar) + } + return nil + } else if s.Mode()&os.ModeSymlink != 0 { + err = createParentDirs(dest, src) + if err != nil { + return err + } + + return z.writeSymlink(dest, src) + } else if s.Mode().IsRegular() { + r, err := z.fs.Open(src) + if err != nil { + return err + } + + if srcJar && filepath.Ext(src) == ".java" { + // rewrite the destination using the package path if it can be determined + pkg, err := jar.JavaPackage(r, src) + if err != nil { + // ignore errors for now, leaving the file at in its original location in the zip + } else { + dest = filepath.Join(filepath.Join(strings.Split(pkg, ".")...), filepath.Base(src)) + } + + _, err = r.Seek(0, io.SeekStart) + if err != nil { + return err + } } fileSize = s.Size() executable = s.Mode()&0100 != 0 - } - r, err := z.fs.Open(src) - if err != nil { - return err - } + header := &zip.FileHeader{ + Name: dest, + Method: method, + UncompressedSize64: uint64(fileSize), + } - header := &zip.FileHeader{ - Name: dest, - Method: method, - UncompressedSize64: uint64(fileSize), - } + if executable { + header.SetMode(0700) + } - if executable { - header.SetMode(0700) - } + err = createParentDirs(dest, src) + if err != nil { + return err + } - return z.writeFileContents(header, r) + return z.writeFileContents(header, r) + } else { + return fmt.Errorf("%s is not a file, directory, or symlink", src) + } } func (z *ZipWriter) addManifest(dest string, src string, method uint16) error { diff --git a/zip/zip_test.go b/zip/zip_test.go index 93c5f3dee..84317d1b6 100644 --- a/zip/zip_test.go +++ b/zip/zip_test.go @@ -40,14 +40,15 @@ var ( ) var mockFs = pathtools.MockFs(map[string][]byte{ - "a/a/a": fileA, - "a/a/b": fileB, - "a/a/c -> ../../c": nil, - "a/a/d -> b": nil, - "c": fileC, - "l": []byte("a/a/a\na/a/b\nc\n"), - "l2": []byte("missing\n"), - "manifest.txt": fileCustomManifest, + "a/a/a": fileA, + "a/a/b": fileB, + "a/a/c -> ../../c": nil, + "dangling -> missing": nil, + "a/a/d -> b": nil, + "c": fileC, + "l": []byte("a/a/a\na/a/b\nc\n"), + "l2": []byte("missing\n"), + "manifest.txt": fileCustomManifest, }) func fh(name string, contents []byte, method uint16) zip.FileHeader { @@ -210,6 +211,17 @@ func TestZip(t *testing.T) { }, }, { + name: "dangling symlinks", + args: fileArgsBuilder(). + File("dangling"), + compressionLevel: 9, + storeSymlinks: true, + + files: []zip.FileHeader{ + fhLink("dangling", "missing"), + }, + }, + { name: "list", args: fileArgsBuilder(). List("l"), @@ -554,3 +566,70 @@ func TestReadRespFile(t *testing.T) { }) } } + +func TestSrcJar(t *testing.T) { + mockFs := pathtools.MockFs(map[string][]byte{ + "wrong_package.java": []byte("package foo;"), + "foo/correct_package.java": []byte("package foo;"), + "src/no_package.java": nil, + "src2/parse_error.java": []byte("error"), + }) + + want := []string{ + "foo/", + "foo/wrong_package.java", + "foo/correct_package.java", + "no_package.java", + "src2/", + "src2/parse_error.java", + } + + args := ZipArgs{} + args.FileArgs = NewFileArgsBuilder().File("**/*.java").FileArgs() + + args.SrcJar = true + args.AddDirectoryEntriesToZip = true + args.Filesystem = mockFs + args.Stderr = &bytes.Buffer{} + + buf := &bytes.Buffer{} + err := ZipTo(args, buf) + if err != nil { + t.Fatalf("got error %v", err) + } + + br := bytes.NewReader(buf.Bytes()) + zr, err := zip.NewReader(br, int64(br.Len())) + if err != nil { + t.Fatal(err) + } + + var got []string + for _, f := range zr.File { + r, err := f.Open() + if err != nil { + t.Fatalf("error when opening %s: %s", f.Name, err) + } + + crc := crc32.NewIEEE() + len, err := io.Copy(crc, r) + r.Close() + if err != nil { + t.Fatalf("error when reading %s: %s", f.Name, err) + } + + if uint64(len) != f.UncompressedSize64 { + t.Errorf("incorrect length for %s, want %d got %d", f.Name, f.UncompressedSize64, len) + } + + if crc.Sum32() != f.CRC32 { + t.Errorf("incorrect crc for %s, want %x got %x", f.Name, f.CRC32, crc) + } + + got = append(got, f.Name) + } + + if !reflect.DeepEqual(want, got) { + t.Errorf("want files %q, got %q", want, got) + } +} |