Extract jar-sorting to be accessible to soong_zip

Bug: 64536066
Test: m -j # which runs unit tests
Change-Id: I4830bd331c9dab0b1d300a18aefaf25a6af4cfdc
diff --git a/Android.bp b/Android.bp
index d1b8f00..cc28c98 100644
--- a/Android.bp
+++ b/Android.bp
@@ -4,6 +4,7 @@
     "cmd/*",
     "fs",
     "finder",
+    "jar",
     "third_party/zip",
     "ui/*",
 ]
diff --git a/cmd/zip2zip/Android.bp b/cmd/zip2zip/Android.bp
index 476be4f..6420219 100644
--- a/cmd/zip2zip/Android.bp
+++ b/cmd/zip2zip/Android.bp
@@ -14,7 +14,10 @@
 
 blueprint_go_binary {
     name: "zip2zip",
-    deps: ["android-archive-zip"],
+    deps: [
+      "android-archive-zip",
+      "soong-jar",
+    ],
     srcs: [
         "zip2zip.go",
     ],
diff --git a/cmd/zip2zip/zip2zip.go b/cmd/zip2zip/zip2zip.go
index 815059c..f48d458 100644
--- a/cmd/zip2zip/zip2zip.go
+++ b/cmd/zip2zip/zip2zip.go
@@ -24,6 +24,7 @@
 	"strings"
 	"time"
 
+	"android/soong/jar"
 	"android/soong/third_party/zip"
 )
 
@@ -178,37 +179,7 @@
 }
 
 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
-		}
+		return jar.EntryNamesLess(files[i].newName, files[j].newName)
 	})
 }
diff --git a/jar/Android.bp b/jar/Android.bp
new file mode 100644
index 0000000..23ad536
--- /dev/null
+++ b/jar/Android.bp
@@ -0,0 +1,22 @@
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+bootstrap_go_package {
+    name: "soong-jar",
+    pkgPath: "android/soong/jar",
+    srcs: [
+        "jar.go",
+    ],
+}
+
diff --git a/jar/jar.go b/jar/jar.go
new file mode 100644
index 0000000..d8f063c
--- /dev/null
+++ b/jar/jar.go
@@ -0,0 +1,55 @@
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package jar
+
+import (
+	"fmt"
+	"strings"
+)
+
+// EntryNamesLess tells whether <filepathA> should precede <filepathB> in
+// the order of files with a .jar
+func EntryNamesLess(filepathA string, filepathB string) (less bool) {
+	diff := index(filepathA) - index(filepathB)
+	if diff == 0 {
+		return filepathA < filepathB
+	}
+	return diff < 0
+}
+
+// Treats trailing * as a prefix match
+func patternMatch(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/*",
+	"*",
+}
+
+func index(name string) int {
+	for i, pattern := range jarOrder {
+		if patternMatch(pattern, name) {
+			return i
+		}
+	}
+	panic(fmt.Errorf("file %q did not match any pattern", name))
+}