exp/vulndb/govulncheck: show only one finding per vuln by default

All findings for a vulnerability can be printed using --all flag.

Change-Id: I0d2486861613878406cf6e5de2f8884d36d4ee4d
Reviewed-on: https://go-review.googlesource.com/c/exp/+/340552
Trust: Zvonimir Pavlinovic <zpavlinovic@google.com>
Run-TryBot: Zvonimir Pavlinovic <zpavlinovic@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Guodong Li <guodongli@google.com>
Reviewed-by: Tim King <taking@google.com>
diff --git a/vulndb/govulncheck/main.go b/vulndb/govulncheck/main.go
index 4ea2589..ba555f2 100644
--- a/vulndb/govulncheck/main.go
+++ b/vulndb/govulncheck/main.go
@@ -35,13 +35,14 @@
 	jsonFlag    = flag.Bool("json", false, "")
 	verboseFlag = flag.Bool("verbose", false, "")
 	importsFlag = flag.Bool("imports", false, "")
+	allFlag     = flag.Bool("all", false, "")
 )
 
 const usage = `govulncheck: identify known vulnerabilities by call graph traversal.
 
 Usage:
 
-	govulncheck [-imports] {package pattern...}
+	govulncheck [-imports] [-json] [-all] {package pattern...}
 
 	govulncheck {binary path}
 
@@ -53,6 +54,10 @@
 
 	-json  	   Print vulnerability findings in JSON format.
 
+	-all       Show all representative findings for each vulnerability. A best effort
+		   is made to order findings by relevance. When false [default], show only
+		   the most relevant finding.
+
 	-verbose   Print progress information.
 
 govulncheck can be used with either one or more package patterns (i.e. golang.org/x/crypto/...
@@ -89,9 +94,29 @@
 		os.Exit(1)
 	}
 
+	if !*allFlag {
+		r = projectToSingleFinding(r)
+	}
+
 	writeOut(r, *jsonFlag)
 }
 
+func projectToSingleFinding(r *audit.Results) *audit.Results {
+	nr := &audit.Results{
+		SearchMode:      r.SearchMode,
+		Vulnerabilities: r.Vulnerabilities,
+		VulnFindings:    make(map[string][]audit.Finding),
+	}
+
+	for id, findings := range r.VulnFindings {
+		if len(findings) > 0 {
+			nr.VulnFindings[id] = []audit.Finding{findings[0]}
+		}
+	}
+
+	return nr
+}
+
 func writeOut(r *audit.Results, toJson bool) {
 	if !toJson {
 		os.Stdout.Write([]byte(r.String()))