soong_zip: add support for -j to junk paths

When -j is specified ignore the path to the source file and just
zip it with its filename.  -j overrides -C, and -C overrides -j,
so -j -f path1 -C dir -f path2 will junk the path for path1, but
treat path2 as relative to dir.

Remove the filepath.Clean for the FileArgs, it would convert ""
to "." sometimes, and everything gets cleaned in zip already for
the non-command-line use cases.

Test: m checkbuild
Change-Id: I7d90572c622ee0c6f35967ff31d067b5312c72eb
diff --git a/zip/cmd/main.go b/zip/cmd/main.go
index 5c6199e..dfd56dc 100644
--- a/zip/cmd/main.go
+++ b/zip/cmd/main.go
@@ -21,8 +21,8 @@
 	"io"
 	"io/ioutil"
 	"os"
-	"path/filepath"
 	"runtime"
+	"strconv"
 	"strings"
 
 	"android/soong/zip"
@@ -65,13 +65,14 @@
 }
 
 func (f *file) Set(s string) error {
-	if *relativeRoot == "" {
-		return fmt.Errorf("must pass -C before -f")
+	if relativeRoot == "" && !junkPaths {
+		return fmt.Errorf("must pass -C or -j before -f")
 	}
 
 	fArgs = append(fArgs, zip.FileArg{
-		PathPrefixInZip:     filepath.Clean(*rootPrefix),
-		SourcePrefixToStrip: filepath.Clean(*relativeRoot),
+		PathPrefixInZip:     *rootPrefix,
+		SourcePrefixToStrip: relativeRoot,
+		JunkPaths:           junkPaths,
 		SourceFiles:         []string{s},
 	})
 
@@ -83,8 +84,8 @@
 }
 
 func (l *listFiles) Set(s string) error {
-	if *relativeRoot == "" {
-		return fmt.Errorf("must pass -C before -l")
+	if relativeRoot == "" && !junkPaths {
+		return fmt.Errorf("must pass -C or -j before -l")
 	}
 
 	list, err := ioutil.ReadFile(s)
@@ -93,8 +94,9 @@
 	}
 
 	fArgs = append(fArgs, zip.FileArg{
-		PathPrefixInZip:     filepath.Clean(*rootPrefix),
-		SourcePrefixToStrip: filepath.Clean(*relativeRoot),
+		PathPrefixInZip:     *rootPrefix,
+		SourcePrefixToStrip: relativeRoot,
+		JunkPaths:           junkPaths,
 		SourceFiles:         strings.Split(string(list), "\n"),
 	})
 
@@ -106,21 +108,47 @@
 }
 
 func (d *dir) Set(s string) error {
-	if *relativeRoot == "" {
-		return fmt.Errorf("must pass -C before -D")
+	if relativeRoot == "" && !junkPaths {
+		return fmt.Errorf("must pass -C or -j before -D")
 	}
 
 	fArgs = append(fArgs, zip.FileArg{
-		PathPrefixInZip:     filepath.Clean(*rootPrefix),
-		SourcePrefixToStrip: filepath.Clean(*relativeRoot),
-		GlobDir:             filepath.Clean(s),
+		PathPrefixInZip:     *rootPrefix,
+		SourcePrefixToStrip: relativeRoot,
+		JunkPaths:           junkPaths,
+		GlobDir:             s,
 	})
 
 	return nil
 }
 
+type relativeRootImpl struct{}
+
+func (*relativeRootImpl) String() string { return relativeRoot }
+
+func (*relativeRootImpl) Set(s string) error {
+	relativeRoot = s
+	junkPaths = false
+	return nil
+}
+
+type junkPathsImpl struct{}
+
+func (*junkPathsImpl) IsBoolFlag() bool { return true }
+
+func (*junkPathsImpl) String() string { return relativeRoot }
+
+func (*junkPathsImpl) Set(s string) error {
+	var err error
+	junkPaths, err = strconv.ParseBool(s)
+	relativeRoot = ""
+	return err
+}
+
 var (
-	rootPrefix, relativeRoot *string
+	rootPrefix   *string
+	relativeRoot string
+	junkPaths    bool
 
 	fArgs            zip.FileArgs
 	nonDeflatedFiles = make(uniqueSet)
@@ -154,7 +182,6 @@
 	manifest := flags.String("m", "", "input jar manifest file name")
 	directories := flags.Bool("d", false, "include directories in zip")
 	rootPrefix = flags.String("P", "", "path prefix within the zip at which to place files")
-	relativeRoot = flags.String("C", "", "path to use as relative root of files in following -f, -l, or -D arguments")
 	compLevel := flags.Int("L", 5, "deflate compression level (0-9)")
 	emulateJar := flags.Bool("jar", false, "modify the resultant .zip to emulate the output of 'jar'")
 	writeIfChanged := flags.Bool("write_if_changed", false, "only update resultant .zip if it has changed")
@@ -167,6 +194,8 @@
 	flags.Var(&dir{}, "D", "directory to include in zip")
 	flags.Var(&file{}, "f", "file to include in zip")
 	flags.Var(&nonDeflatedFiles, "s", "file path to be stored within the zip without compression")
+	flags.Var(&relativeRootImpl{}, "C", "path to use as relative root of files in following -f, -l, or -D arguments")
+	flags.Var(&junkPathsImpl{}, "j", "junk paths, zip files without directory names")
 
 	flags.Parse(expandedArgs[1:])
 
diff --git a/zip/zip.go b/zip/zip.go
index a8df51e..6b36e10 100644
--- a/zip/zip.go
+++ b/zip/zip.go
@@ -87,6 +87,7 @@
 type FileArg struct {
 	PathPrefixInZip, SourcePrefixToStrip string
 	SourceFiles                          []string
+	JunkPaths                            bool
 	GlobDir                              string
 }
 
@@ -228,8 +229,7 @@
 			srcs = append(srcs, recursiveGlobFiles(fa.GlobDir)...)
 		}
 		for _, src := range srcs {
-			err := fillPathPairs(fa.PathPrefixInZip, fa.SourcePrefixToStrip, src,
-				&pathMappings, args.NonDeflatedFiles, noCompression)
+			err := fillPathPairs(fa, src, &pathMappings, args.NonDeflatedFiles, noCompression)
 			if err != nil {
 				log.Fatal(err)
 			}
@@ -270,7 +270,7 @@
 	return nil
 }
 
-func fillPathPairs(prefix, rel, src string, pathMappings *[]pathMapping,
+func fillPathPairs(fa FileArg, src string, pathMappings *[]pathMapping,
 	nonDeflatedFiles map[string]bool, noCompression bool) error {
 
 	src = strings.TrimSpace(src)
@@ -278,11 +278,18 @@
 		return nil
 	}
 	src = filepath.Clean(src)
-	dest, err := filepath.Rel(rel, src)
-	if err != nil {
-		return err
+	var dest string
+
+	if fa.JunkPaths {
+		dest = filepath.Base(src)
+	} else {
+		var err error
+		dest, err = filepath.Rel(fa.SourcePrefixToStrip, src)
+		if err != nil {
+			return err
+		}
 	}
-	dest = filepath.Join(prefix, dest)
+	dest = filepath.Join(fa.PathPrefixInZip, dest)
 
 	zipMethod := zip.Deflate
 	if _, found := nonDeflatedFiles[dest]; found || noCompression {