[pm][delta] Separate source and target filters

Allow the filtering step of a package snapshot to use different filters
for the source and target snapshots, to, for example, allow showing the
side effects of adding or removing a single package to an OS image,
without having to actually produce 2 builds.

Test: manual
Change-Id: Iceb7d6fcdd7caca0dead6aa176527e0bb69cf289
diff --git a/go/src/pm/cmd/pm/delta/delta.go b/go/src/pm/cmd/pm/delta/delta.go
index 2d23aa6..afd090b 100644
--- a/go/src/pm/cmd/pm/delta/delta.go
+++ b/go/src/pm/cmd/pm/delta/delta.go
@@ -28,8 +28,10 @@
 	outputPath string
 
 	// filtering options
-	includeTags []string
-	excludeTags []string
+	sourceIncludeTags []string
+	sourceExcludeTags []string
+	targetIncludeTags []string
+	targetExcludeTags []string
 
 	// stdout display options (ignored if outputPath is specified)
 	summary           bool
@@ -68,15 +70,22 @@
 
 	var c deltaConfig
 
+	var includeTags []string
+	var excludeTags []string
+
 	fs.StringVar(&c.outputPath, "output", "", "Write delta as JSON to the provided path instead of writing to stdout ('-' to write json to stdout)")
 	fs.BoolVar(&c.detailed, "detailed", false, "Include all package and blob statistics, instead of just the top few")
 	fs.BoolVar(&c.summary, "summary", false, "Show summary of update statistics")
 	fs.BoolVar(&c.packages, "packages", false, "Show per-package statistics")
 	fs.BoolVar(&c.blobs, "blobs", false, "Show per-blob statistics")
-	fs.UintVar(&c.packageCount, "package_count", 0, "Show up to N packages with largest updates (implies --packages)")
-	fs.UintVar(&c.blobCount, "blob_count", 0, "Show up to N blobs with largest updates (implies --blobs)")
-	fs.Var((*stringSlice)(&c.includeTags), "include", "Include a tag in the analysis (default is to include all tags)")
-	fs.Var((*stringSlice)(&c.excludeTags), "exclude", "Exclude a tag from the analysis (default is to exclude no tags)")
+	fs.UintVar(&c.packageCount, "package-count", 0, "Show up to N packages with largest updates (implies --packages)")
+	fs.UintVar(&c.blobCount, "blob-count", 0, "Show up to N blobs with largest updates (implies --blobs)")
+	fs.Var((*stringSlice)(&c.sourceIncludeTags), "source-include", "Include a tag from source in the analysis (default is to include all tags)")
+	fs.Var((*stringSlice)(&c.sourceExcludeTags), "source-exclude", "Exclude a tag from source from the analysis (default is to exclude no tags)")
+	fs.Var((*stringSlice)(&c.targetIncludeTags), "target-include", "Include a tag from target in the analysis (default is to include all tags)")
+	fs.Var((*stringSlice)(&c.targetExcludeTags), "target-exclude", "Exclude a tag from target from the analysis (default is to exclude no tags)")
+	fs.Var((*stringSlice)(&includeTags), "include", "Include a tag from source and target in the analysis (default is to include all tags)")
+	fs.Var((*stringSlice)(&excludeTags), "exclude", "Exclude a tag from source and target from the analysis (default is to exclude no tags)")
 
 	fs.Usage = func() {
 		fmt.Fprintf(fs.Output(), usage, filepath.Base(os.Args[0]))
@@ -119,8 +128,17 @@
 	// Show section headers if more than one section will be shown
 	c.showSectionHeader = countTrueValues(c.summary, c.packages, c.blobs) > 1
 
-	if len(c.includeTags) == 0 {
-		c.includeTags = append(c.includeTags, "*")
+	c.sourceIncludeTags = append(c.sourceIncludeTags, includeTags...)
+	c.sourceExcludeTags = append(c.sourceExcludeTags, excludeTags...)
+	c.targetIncludeTags = append(c.targetIncludeTags, includeTags...)
+	c.targetExcludeTags = append(c.targetExcludeTags, excludeTags...)
+
+	if len(c.sourceIncludeTags) == 0 {
+		c.sourceIncludeTags = append(c.sourceIncludeTags, "*")
+	}
+
+	if len(c.targetIncludeTags) == 0 {
+		c.targetIncludeTags = append(c.targetIncludeTags, "*")
 	}
 
 	return &c, nil
@@ -143,8 +161,8 @@
 		return err
 	}
 
-	source = source.Filter(config.includeTags, config.excludeTags)
-	target = target.Filter(config.includeTags, config.excludeTags)
+	source = source.Filter(config.sourceIncludeTags, config.sourceExcludeTags)
+	target = target.Filter(config.targetIncludeTags, config.targetExcludeTags)
 
 	delta, err := build.DeltaSnapshots(source, target)
 	if err != nil {