zip2zip: add flag to uncompress files

Add -0 flag to convert files in a zip to stored instead of deflated.

Bug: 69500920
Test: zip2zip_test.go
Change-Id: I6c2b10f3b200a53a3339e3c97a78f65192b309ca
This commit is contained in:
Colin Cross
2018-10-07 21:30:12 -07:00
parent e40b4eaeb0
commit b1a5e9cadf
2 changed files with 138 additions and 18 deletions

View File

@@ -17,6 +17,7 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"io"
"log" "log"
"os" "os"
"path/filepath" "path/filepath"
@@ -39,11 +40,13 @@ var (
staticTime = time.Date(2009, 1, 1, 0, 0, 0, 0, time.UTC) staticTime = time.Date(2009, 1, 1, 0, 0, 0, 0, time.UTC)
excludes excludeArgs excludes multiFlag
uncompress multiFlag
) )
func init() { func init() {
flag.Var(&excludes, "x", "exclude a filespec from the output") flag.Var(&excludes, "x", "exclude a filespec from the output")
flag.Var(&uncompress, "0", "convert a filespec to uncompressed in the output")
} }
func main() { func main() {
@@ -93,7 +96,7 @@ func main() {
}() }()
if err := zip2zip(&reader.Reader, writer, *sortGlobs, *sortJava, *setTime, if err := zip2zip(&reader.Reader, writer, *sortGlobs, *sortJava, *setTime,
flag.Args(), excludes); err != nil { flag.Args(), excludes, uncompress); err != nil {
log.Fatal(err) log.Fatal(err)
} }
@@ -102,10 +105,11 @@ func main() {
type pair struct { type pair struct {
*zip.File *zip.File
newName string newName string
uncompress bool
} }
func zip2zip(reader *zip.Reader, writer *zip.Writer, sortOutput, sortJava, setTime bool, func zip2zip(reader *zip.Reader, writer *zip.Writer, sortOutput, sortJava, setTime bool,
includes []string, excludes []string) error { includes, excludes, uncompresses []string) error {
matches := []pair{} matches := []pair{}
@@ -149,7 +153,7 @@ func zip2zip(reader *zip.Reader, writer *zip.Writer, sortOutput, sortJava, setTi
newName = output newName = output
} }
} }
includeMatches = append(includeMatches, pair{file, newName}) includeMatches = append(includeMatches, pair{file, newName, false})
} }
} }
@@ -160,7 +164,7 @@ func zip2zip(reader *zip.Reader, writer *zip.Writer, sortOutput, sortJava, setTi
if len(includes) == 0 { if len(includes) == 0 {
// implicitly match everything // implicitly match everything
for _, file := range reader.File { for _, file := range reader.File {
matches = append(matches, pair{file, file.Name}) matches = append(matches, pair{file, file.Name, false})
} }
sortMatches(matches) sortMatches(matches)
} }
@@ -193,6 +197,15 @@ func zip2zip(reader *zip.Reader, writer *zip.Writer, sortOutput, sortJava, setTi
} }
seen[match.newName] = match.File seen[match.newName] = match.File
for _, u := range uncompresses {
if uncompressMatch, err := pathtools.Match(u, match.newName); err != nil {
return err
} else if uncompressMatch {
match.uncompress = true
break
}
}
matchesAfterExcludes = append(matchesAfterExcludes, match) matchesAfterExcludes = append(matchesAfterExcludes, match)
} }
@@ -200,9 +213,33 @@ func zip2zip(reader *zip.Reader, writer *zip.Writer, sortOutput, sortJava, setTi
if setTime { if setTime {
match.File.SetModTime(staticTime) match.File.SetModTime(staticTime)
} }
if err := writer.CopyFrom(match.File, match.newName); err != nil { if match.uncompress && match.File.FileHeader.Method != zip.Store {
fh := match.File.FileHeader
fh.Name = match.newName
fh.Method = zip.Store
fh.CompressedSize64 = fh.UncompressedSize64
zw, err := writer.CreateHeaderAndroid(&fh)
if err != nil {
return err return err
} }
zr, err := match.File.Open()
if err != nil {
return err
}
_, err = io.Copy(zw, zr)
zr.Close()
if err != nil {
return err
}
} else {
err := writer.CopyFrom(match.File, match.newName)
if err != nil {
return err
}
}
} }
return nil return nil
@@ -217,13 +254,13 @@ func includeSplit(s string) (string, string) {
} }
} }
type excludeArgs []string type multiFlag []string
func (e *excludeArgs) String() string { func (e *multiFlag) String() string {
return strings.Join(*e, " ") return strings.Join(*e, " ")
} }
func (e *excludeArgs) Set(s string) error { func (e *multiFlag) Set(s string) error {
*e = append(*e, s) *e = append(*e, s)
return nil return nil
} }

View File

@@ -31,8 +31,10 @@ var testCases = []struct {
sortJava bool sortJava bool
args []string args []string
excludes []string excludes []string
uncompresses []string
outputFiles []string outputFiles []string
storedFiles []string
err error err error
}{ }{
{ {
@@ -251,6 +253,79 @@ var testCases = []struct {
outputFiles: nil, outputFiles: nil,
}, },
{
name: "uncompress one",
inputFiles: []string{
"a/a",
"a/b",
},
uncompresses: []string{"a/a"},
outputFiles: []string{
"a/a",
"a/b",
},
storedFiles: []string{
"a/a",
},
},
{
name: "uncompress two",
inputFiles: []string{
"a/a",
"a/b",
},
uncompresses: []string{"a/a", "a/b"},
outputFiles: []string{
"a/a",
"a/b",
},
storedFiles: []string{
"a/a",
"a/b",
},
},
{
name: "uncompress glob",
inputFiles: []string{
"a/a",
"a/b",
"a/c.so",
"a/d.so",
},
uncompresses: []string{"a/*.so"},
outputFiles: []string{
"a/a",
"a/b",
"a/c.so",
"a/d.so",
},
storedFiles: []string{
"a/c.so",
"a/d.so",
},
},
{
name: "uncompress rename",
inputFiles: []string{
"a/a",
},
args: []string{"a/a:a/b"},
uncompresses: []string{"a/b"},
outputFiles: []string{
"a/b",
},
storedFiles: []string{
"a/b",
},
},
} }
func errorString(e error) string { func errorString(e error) string {
@@ -282,7 +357,8 @@ func TestZip2Zip(t *testing.T) {
} }
outputWriter := zip.NewWriter(outputBuf) outputWriter := zip.NewWriter(outputBuf)
err = zip2zip(inputReader, outputWriter, testCase.sortGlobs, testCase.sortJava, false, testCase.args, testCase.excludes) err = zip2zip(inputReader, outputWriter, testCase.sortGlobs, testCase.sortJava, false,
testCase.args, testCase.excludes, testCase.uncompresses)
if errorString(testCase.err) != errorString(err) { if errorString(testCase.err) != errorString(err) {
t.Fatalf("Unexpected error:\n got: %q\nwant: %q", errorString(err), errorString(testCase.err)) t.Fatalf("Unexpected error:\n got: %q\nwant: %q", errorString(err), errorString(testCase.err))
} }
@@ -294,15 +370,22 @@ func TestZip2Zip(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
var outputFiles []string var outputFiles []string
var storedFiles []string
if len(outputReader.File) > 0 { if len(outputReader.File) > 0 {
outputFiles = make([]string, len(outputReader.File)) outputFiles = make([]string, len(outputReader.File))
for i, file := range outputReader.File { for i, file := range outputReader.File {
outputFiles[i] = file.Name outputFiles[i] = file.Name
if file.Method == zip.Store {
storedFiles = append(storedFiles, file.Name)
}
} }
} }
if !reflect.DeepEqual(testCase.outputFiles, outputFiles) { if !reflect.DeepEqual(testCase.outputFiles, outputFiles) {
t.Fatalf("Output file list does not match:\n got: %v\nwant: %v", outputFiles, testCase.outputFiles) t.Fatalf("Output file list does not match:\nwant: %v\n got: %v", testCase.outputFiles, outputFiles)
}
if !reflect.DeepEqual(testCase.storedFiles, storedFiles) {
t.Fatalf("Stored file list does not match:\nwant: %v\n got: %v", testCase.storedFiles, storedFiles)
} }
}) })
} }