Add jar sorting to zip2zip
Jars have a strange sorting order; the META-INF/ directory should come first, then META-INF/MANIFEST.MF, then any other files in META-INF/, and then any files outside META-INF. Add a -j argument to zip2zip that sorts using jar ordering. Test: zip2zip_test Change-Id: I80e2bc7e284ef74f6561c26cb6541298834db1bc
This commit is contained in:
@@ -31,6 +31,7 @@ var (
|
|||||||
input = flag.String("i", "", "zip file to read from")
|
input = flag.String("i", "", "zip file to read from")
|
||||||
output = flag.String("o", "", "output file")
|
output = flag.String("o", "", "output file")
|
||||||
sortGlobs = flag.Bool("s", false, "sort matches from each glob (defaults to the order from the input zip file)")
|
sortGlobs = flag.Bool("s", false, "sort matches from each glob (defaults to the order from the input zip file)")
|
||||||
|
sortJava = flag.Bool("j", false, "sort using jar ordering within each glob (META-INF/MANIFEST.MF first)")
|
||||||
setTime = flag.Bool("t", false, "set timestamps to 2009-01-01 00:00:00")
|
setTime = flag.Bool("t", false, "set timestamps to 2009-01-01 00:00:00")
|
||||||
|
|
||||||
staticTime = time.Date(2009, 1, 1, 0, 0, 0, 0, time.UTC)
|
staticTime = time.Date(2009, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
@@ -38,7 +39,7 @@ var (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
fmt.Fprintln(os.Stderr, "usage: zip2zip -i zipfile -o zipfile [-s] [-t] [filespec]...")
|
fmt.Fprintln(os.Stderr, "usage: zip2zip -i zipfile -o zipfile [-s|-j] [-t] [filespec]...")
|
||||||
flag.PrintDefaults()
|
flag.PrintDefaults()
|
||||||
fmt.Fprintln(os.Stderr, " filespec:")
|
fmt.Fprintln(os.Stderr, " filespec:")
|
||||||
fmt.Fprintln(os.Stderr, " <name>")
|
fmt.Fprintln(os.Stderr, " <name>")
|
||||||
@@ -81,12 +82,17 @@ func main() {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err := zip2zip(&reader.Reader, writer, *sortGlobs, *setTime, flag.Args()); err != nil {
|
if err := zip2zip(&reader.Reader, writer, *sortGlobs, *sortJava, *setTime, flag.Args()); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func zip2zip(reader *zip.Reader, writer *zip.Writer, sortGlobs, setTime bool, args []string) error {
|
type pair struct {
|
||||||
|
*zip.File
|
||||||
|
newName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func zip2zip(reader *zip.Reader, writer *zip.Writer, sortGlobs, sortJava, setTime bool, args []string) error {
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
var input string
|
var input string
|
||||||
var output string
|
var output string
|
||||||
@@ -103,11 +109,6 @@ func zip2zip(reader *zip.Reader, writer *zip.Writer, sortGlobs, setTime bool, ar
|
|||||||
output = args[1]
|
output = args[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
type pair struct {
|
|
||||||
*zip.File
|
|
||||||
newName string
|
|
||||||
}
|
|
||||||
|
|
||||||
matches := []pair{}
|
matches := []pair{}
|
||||||
if strings.IndexAny(input, "*?[") >= 0 {
|
if strings.IndexAny(input, "*?[") >= 0 {
|
||||||
matchAll := input == "**"
|
matchAll := input == "**"
|
||||||
@@ -138,7 +139,9 @@ func zip2zip(reader *zip.Reader, writer *zip.Writer, sortGlobs, setTime bool, ar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if sortGlobs {
|
if sortJava {
|
||||||
|
jarSort(matches)
|
||||||
|
} else if sortGlobs {
|
||||||
sort.SliceStable(matches, func(i, j int) bool {
|
sort.SliceStable(matches, func(i, j int) bool {
|
||||||
return matches[i].newName < matches[j].newName
|
return matches[i].newName < matches[j].newName
|
||||||
})
|
})
|
||||||
@@ -167,3 +170,39 @@ func zip2zip(reader *zip.Reader, writer *zip.Writer, sortGlobs, setTime bool, ar
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func jarSort(files []pair) {
|
||||||
|
// Treats trailing * as a prefix match
|
||||||
|
match := func(pattern, name string) bool {
|
||||||
|
if strings.HasSuffix(pattern, "*") {
|
||||||
|
return strings.HasPrefix(name, strings.TrimSuffix(pattern, "*"))
|
||||||
|
} else {
|
||||||
|
return name == pattern
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var jarOrder = []string{
|
||||||
|
"META-INF/",
|
||||||
|
"META-INF/MANIFEST.MF",
|
||||||
|
"META-INF/*",
|
||||||
|
"*",
|
||||||
|
}
|
||||||
|
|
||||||
|
index := func(name string) int {
|
||||||
|
for i, pattern := range jarOrder {
|
||||||
|
if match(pattern, name) {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic(fmt.Errorf("file %q did not match any pattern", name))
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.SliceStable(files, func(i, j int) bool {
|
||||||
|
diff := index(files[i].newName) - index(files[j].newName)
|
||||||
|
if diff == 0 {
|
||||||
|
return files[i].newName < files[j].newName
|
||||||
|
} else {
|
||||||
|
return diff < 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@@ -28,6 +28,7 @@ var testCases = []struct {
|
|||||||
|
|
||||||
inputFiles []string
|
inputFiles []string
|
||||||
sortGlobs bool
|
sortGlobs bool
|
||||||
|
sortJava bool
|
||||||
args []string
|
args []string
|
||||||
|
|
||||||
outputFiles []string
|
outputFiles []string
|
||||||
@@ -115,6 +116,35 @@ var testCases = []struct {
|
|||||||
"RADIO/a",
|
"RADIO/a",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "sort jar",
|
||||||
|
|
||||||
|
inputFiles: []string{
|
||||||
|
"MANIFEST.MF",
|
||||||
|
"META-INF/MANIFEST.MF",
|
||||||
|
"META-INF/aaa/",
|
||||||
|
"META-INF/aaa/aaa",
|
||||||
|
"META-INF/AAA",
|
||||||
|
"META-INF.txt",
|
||||||
|
"META-INF/",
|
||||||
|
"AAA",
|
||||||
|
"aaa",
|
||||||
|
},
|
||||||
|
sortJava: true,
|
||||||
|
args: nil,
|
||||||
|
|
||||||
|
outputFiles: []string{
|
||||||
|
"META-INF/",
|
||||||
|
"META-INF/MANIFEST.MF",
|
||||||
|
"META-INF/AAA",
|
||||||
|
"META-INF/aaa/",
|
||||||
|
"META-INF/aaa/aaa",
|
||||||
|
"AAA",
|
||||||
|
"MANIFEST.MF",
|
||||||
|
"META-INF.txt",
|
||||||
|
"aaa",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "double input",
|
name: "double input",
|
||||||
|
|
||||||
@@ -161,7 +191,7 @@ func TestZip2Zip(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
outputWriter := zip.NewWriter(outputBuf)
|
outputWriter := zip.NewWriter(outputBuf)
|
||||||
err = zip2zip(inputReader, outputWriter, testCase.sortGlobs, false, testCase.args)
|
err = zip2zip(inputReader, outputWriter, testCase.sortGlobs, testCase.sortJava, false, testCase.args)
|
||||||
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))
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user