internal/scan: add -version flag

Only print the config block when -version is present
Change to be more verbose but more readable now it is not always printed.
Also don't print the usage just because there were no patterns.

Fixes #53867

Change-Id: I282a5332c11eef535286133fc2425afa7f46942b
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/519815
Run-TryBot: Ian Cottrell <iancottrell@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Maceo Thompson <maceothompson@google.com>
Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com>
Auto-Submit: Ian Cottrell <iancottrell@google.com>
diff --git a/cmd/govulncheck/main_command_118_test.go b/cmd/govulncheck/main_command_118_test.go
index 4a5eeac..7f056c4 100644
--- a/cmd/govulncheck/main_command_118_test.go
+++ b/cmd/govulncheck/main_command_118_test.go
@@ -59,8 +59,8 @@
 		pattern: `Scanning your code and (\d+) packages across (\d+)`,
 		replace: `Scanning your code and P packages across M`,
 	}, {
-		pattern: `govulncheck@v([^ ]*) `,
-		replace: `govulncheck@v0.0.0-00000000000-20000101010101 `,
+		pattern: `Scanner: govulncheck@v.*`,
+		replace: `Scanner: govulncheck@v1.0.0`,
 	}, {
 		pattern: `"([^"]*") is a file`,
 		replace: `govulncheck: myfile is a file`,
@@ -77,8 +77,8 @@
 		pattern: `modified (.*)\)`,
 		replace: `modified 01 Jan 21 00:00 UTC)`,
 	}, {
-		pattern: `Using (go1.[\.\d]*|devel).* and`,
-		replace: `Using go1.18 and`,
+		pattern: `Go: (go1.[\.\d]*|devel).*`,
+		replace: `Go: go1.18`,
 	}, {
 		pattern: `"go_version": "go[^\s"]*"`,
 		replace: `"go_version": "go1.18"`,
diff --git a/cmd/govulncheck/testdata/binary_fail.ct b/cmd/govulncheck/testdata/binary_fail.ct
index e2d6120..07548d0 100644
--- a/cmd/govulncheck/testdata/binary_fail.ct
+++ b/cmd/govulncheck/testdata/binary_fail.ct
@@ -6,8 +6,6 @@
 #####
 # Test of passing a non-binary file to -mode=binary
 $ govulncheck -mode=binary ${moddir}/vuln/go.mod --> FAIL 1
-Using govulncheck@v0.0.0-00000000000-20000101010101 with vulnerability data from testdata/vulndb-v1 (last modified 01 Jan 21 00:00 UTC).
-
 Scanning your binary for known vulnerabilities...
 
 govulncheck: could not parse provided binary: unrecognized file format
diff --git a/cmd/govulncheck/testdata/binary_text.ct b/cmd/govulncheck/testdata/binary_text.ct
index 453f610..1c151d3 100644
--- a/cmd/govulncheck/testdata/binary_text.ct
+++ b/cmd/govulncheck/testdata/binary_text.ct
@@ -1,8 +1,6 @@
 #####
 # Test basic binary scanning with text output
 $ govulncheck -mode=binary ${vuln_binary} --> FAIL 3
-Using govulncheck@v0.0.0-00000000000-20000101010101 with vulnerability data from testdata/vulndb-v1 (last modified 01 Jan 21 00:00 UTC).
-
 Scanning your binary for known vulnerabilities...
 
 Vulnerability #1: GO-2021-0265
diff --git a/cmd/govulncheck/testdata/convert_text.ct b/cmd/govulncheck/testdata/convert_text.ct
index 7accd04..e12cbc2 100644
--- a/cmd/govulncheck/testdata/convert_text.ct
+++ b/cmd/govulncheck/testdata/convert_text.ct
@@ -1,8 +1,6 @@
 #####
 # Test using the conversion from json on stdin to text on stdout
 $ govulncheck -mode=convert < convert_input.json
-Using go1.18 and govulncheck@v0.0.0-00000000000-20000101010101 with vulnerability data from testdata/vulndb-v1 (last modified 01 Jan 21 00:00 UTC).
-
 Scanning your code and P packages across M dependent modules for known vulnerabilities...
 
 Vulnerability #1: GO-2021-0265
diff --git a/cmd/govulncheck/testdata/source_fail.ct b/cmd/govulncheck/testdata/source_fail.ct
index 7128a2d..1853e8f 100644
--- a/cmd/govulncheck/testdata/source_fail.ct
+++ b/cmd/govulncheck/testdata/source_fail.ct
@@ -1,8 +1,6 @@
 #####
 # Test of missing go.mod error message.
 $ govulncheck -C ${moddir}/nogomod . --> FAIL 1
-Using go1.18 and govulncheck@v0.0.0-00000000000-20000101010101 with vulnerability data from testdata/vulndb-v1 (last modified 01 Jan 21 00:00 UTC).
-
 govulncheck: no go.mod file
 
 govulncheck only works with Go modules. Try navigating to your module directory.
@@ -24,8 +22,6 @@
 #####
 # Test of handing an invalid package pattern to source mode
 $ govulncheck -C ${moddir}/vuln blah --> FAIL 1
-Using go1.18 and govulncheck@v0.0.0-00000000000-20000101010101 with vulnerability data from testdata/vulndb-v1 (last modified 01 Jan 21 00:00 UTC).
-
 govulncheck: loading packages: 
 There are errors with the provided package patterns:
 
diff --git a/cmd/govulncheck/testdata/source_informational_text.ct b/cmd/govulncheck/testdata/source_informational_text.ct
index a8d1047..1e6e36c 100644
--- a/cmd/govulncheck/testdata/source_informational_text.ct
+++ b/cmd/govulncheck/testdata/source_informational_text.ct
@@ -1,8 +1,6 @@
 #####
 # Test souce mode with no callstacks
 $ govulncheck -C ${moddir}/informational -show=traces .
-Using go1.18 and govulncheck@v0.0.0-00000000000-20000101010101 with vulnerability data from testdata/vulndb-v1 (last modified 01 Jan 21 00:00 UTC).
-
 Scanning your code and P packages across M dependent modules for known vulnerabilities...
 
 === Informational ===
diff --git a/cmd/govulncheck/testdata/source_multientry_text.ct b/cmd/govulncheck/testdata/source_multientry_text.ct
index d2776ee..575fa63 100644
--- a/cmd/govulncheck/testdata/source_multientry_text.ct
+++ b/cmd/govulncheck/testdata/source_multientry_text.ct
@@ -1,8 +1,6 @@
 #####
 # Test for multiple call stacks in source mode with expanded traces
 $ govulncheck -C ${moddir}/multientry . --> FAIL 3
-Using go1.18 and govulncheck@v0.0.0-00000000000-20000101010101 with vulnerability data from testdata/vulndb-v1 (last modified 01 Jan 21 00:00 UTC).
-
 Scanning your code and P packages across M dependent module for known vulnerabilities...
 
 Vulnerability #1: GO-2021-0113
@@ -25,8 +23,6 @@
 #####
 # Test for multple call stacks in source mode with expanded traces
 $ govulncheck -C ${moddir}/multientry -show=traces ./... --> FAIL 3
-Using go1.18 and govulncheck@v0.0.0-00000000000-20000101010101 with vulnerability data from testdata/vulndb-v1 (last modified 01 Jan 21 00:00 UTC).
-
 Scanning your code and P packages across M dependent module for known vulnerabilities...
 
 Vulnerability #1: GO-2021-0113
diff --git a/cmd/govulncheck/testdata/source_replace_text.ct b/cmd/govulncheck/testdata/source_replace_text.ct
index 5861e67..efcad00 100644
--- a/cmd/govulncheck/testdata/source_replace_text.ct
+++ b/cmd/govulncheck/testdata/source_replace_text.ct
@@ -2,8 +2,6 @@
 # Test of source mode on a module with a replace directive.
 
 $ govulncheck -C ${moddir}/replace ./... --> FAIL 3
-Using go1.18 and govulncheck@v0.0.0-00000000000-20000101010101 with vulnerability data from testdata/vulndb-v1 (last modified 01 Jan 21 00:00 UTC).
-
 Scanning your code and P packages across M dependent module for known vulnerabilities...
 
 Vulnerability #1: GO-2021-0113
diff --git a/cmd/govulncheck/testdata/source_stdlib_text.ct b/cmd/govulncheck/testdata/source_stdlib_text.ct
index 5b4f204..2b4a0ce 100644
--- a/cmd/govulncheck/testdata/source_stdlib_text.ct
+++ b/cmd/govulncheck/testdata/source_stdlib_text.ct
@@ -1,8 +1,6 @@
 #####
 # Test finding stdlib vulnerability in source mode
 $ govulncheck -C ${moddir}/stdlib . --> FAIL 3
-Using go1.18 and govulncheck@v0.0.0-00000000000-20000101010101 with vulnerability data from testdata/vulndb-v1 (last modified 01 Jan 21 00:00 UTC).
-
 Scanning your code and P packages across M dependent modules for known vulnerabilities...
 
 Vulnerability #1: GO-2022-0969
@@ -23,8 +21,6 @@
 #####
 # Test finding stdlib vulnerability in source mode with expanded traces
 $ govulncheck -C ${moddir}/stdlib -show=traces . --> FAIL 3
-Using go1.18 and govulncheck@v0.0.0-00000000000-20000101010101 with vulnerability data from testdata/vulndb-v1 (last modified 01 Jan 21 00:00 UTC).
-
 Scanning your code and P packages across M dependent modules for known vulnerabilities...
 
 Vulnerability #1: GO-2022-0969
diff --git a/cmd/govulncheck/testdata/source_subdir_text.ct b/cmd/govulncheck/testdata/source_subdir_text.ct
index 8faabf0..1899055 100644
--- a/cmd/govulncheck/testdata/source_subdir_text.ct
+++ b/cmd/govulncheck/testdata/source_subdir_text.ct
@@ -1,8 +1,6 @@
 #####
 # Test govulncheck runs on the subdirectory of a module
 $ govulncheck -C ${moddir}/vuln/subdir . --> FAIL 3
-Using go1.18 and govulncheck@v0.0.0-00000000000-20000101010101 with vulnerability data from testdata/vulndb-v1 (last modified 01 Jan 21 00:00 UTC).
-
 Scanning your code and P packages across M dependent module for known vulnerabilities...
 
 Vulnerability #1: GO-2021-0113
@@ -24,8 +22,6 @@
 #####
 # Test govulncheck runs on the subdirectory of a module
 $ govulncheck -C ${moddir}/vuln/subdir -show=traces . --> FAIL 3
-Using go1.18 and govulncheck@v0.0.0-00000000000-20000101010101 with vulnerability data from testdata/vulndb-v1 (last modified 01 Jan 21 00:00 UTC).
-
 Scanning your code and P packages across M dependent module for known vulnerabilities...
 
 Vulnerability #1: GO-2021-0113
diff --git a/cmd/govulncheck/testdata/source_vuln_text.ct b/cmd/govulncheck/testdata/source_vuln_text.ct
index 47dad38..9016385 100644
--- a/cmd/govulncheck/testdata/source_vuln_text.ct
+++ b/cmd/govulncheck/testdata/source_vuln_text.ct
@@ -1,8 +1,6 @@
 #####
 # Test of basic govulncheck in source mode
 $ govulncheck -C ${moddir}/vuln ./... --> FAIL 3
-Using go1.18 and govulncheck@v0.0.0-00000000000-20000101010101 with vulnerability data from testdata/vulndb-v1 (last modified 01 Jan 21 00:00 UTC).
-
 Scanning your code and P packages across M dependent modules for known vulnerabilities...
 
 Vulnerability #1: GO-2021-0265
@@ -50,8 +48,6 @@
 #####
 # Test of basic govulncheck in source mode with expanded traces
 $ govulncheck -C ${moddir}/vuln -show=traces ./... --> FAIL 3
-Using go1.18 and govulncheck@v0.0.0-00000000000-20000101010101 with vulnerability data from testdata/vulndb-v1 (last modified 01 Jan 21 00:00 UTC).
-
 Scanning your code and P packages across M dependent modules for known vulnerabilities...
 
 Vulnerability #1: GO-2021-0265
diff --git a/cmd/govulncheck/testdata/strip/strip.ct b/cmd/govulncheck/testdata/strip/strip.ct
index 0ca35eb..04f07c7 100644
--- a/cmd/govulncheck/testdata/strip/strip.ct
+++ b/cmd/govulncheck/testdata/strip/strip.ct
@@ -1,8 +1,6 @@
 # Test for stripped binaries (see #57764).
 
 $ govulncheck -mode=binary ${strip_binary} --> FAIL 3
-Using govulncheck@v0.0.0-00000000000-20000101010101 with vulnerability data from testdata/vulndb-v1 (last modified 01 Jan 21 00:00 UTC).
-
 Scanning your binary for known vulnerabilities...
 
 Vulnerability #1: GO-2021-0113
diff --git a/cmd/govulncheck/testdata/usage.ct b/cmd/govulncheck/testdata/usage.ct
index b9fa3fb..778aec8 100644
--- a/cmd/govulncheck/testdata/usage.ct
+++ b/cmd/govulncheck/testdata/usage.ct
@@ -25,35 +25,26 @@
     	comma-separated list of build tags
   -test
     	analyze test files (only valid for source mode)
+  -version
+    	print the version information
 
 For details, see https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck.
 
 #####
-# Same output as -h, but failure.
-$ govulncheck --> FAIL 2
-Govulncheck reports known vulnerabilities in dependencies.
+# Not scanning anything.
+$ govulncheck
+No vulnerabilities found.
 
-Usage:
+Share feedback at https://go.dev/s/govulncheck-feedback.
 
-	govulncheck [flags] [patterns]
-	govulncheck -mode=binary [flags] [binary]
+#####
+# Reporting version without scanning anything.
+$ govulncheck -version
+Go: go1.18
+Scanner: govulncheck@v1.0.0
+DB: testdata/vulndb-v1
+DB updated: 2023-04-03 15:57:51 +0000 UTC
 
-  -C dir
-    	change to dir before running govulncheck
-  -db url
-    	vulnerability database url (default "https://vuln.go.dev")
-  -json
-    	output JSON
-  -mode string
-    	supports source or binary (default "source")
-  -scan string
-    	set the scanning level desired, one of module, package or symbol (default "symbol")
-  -show list
-    	enable display of additional information specified by the comma separated list
-    	The only supported value is 'traces'
-  -tags list
-    	comma-separated list of build tags
-  -test
-    	analyze test files (only valid for source mode)
+No vulnerabilities found.
 
-For details, see https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck.
+Share feedback at https://go.dev/s/govulncheck-feedback.
\ No newline at end of file
diff --git a/internal/scan/flags.go b/internal/scan/flags.go
index 071a336..ce7096d 100644
--- a/internal/scan/flags.go
+++ b/internal/scan/flags.go
@@ -39,6 +39,7 @@
 func parseFlags(cfg *config, stderr io.Writer, args []string) error {
 	var tagsFlag buildutil.TagsFlag
 	var showFlag showFlag
+	var version bool
 	flags := flag.NewFlagSet("", flag.ContinueOnError)
 	flags.SetOutput(stderr)
 	flags.BoolVar(&cfg.json, "json", false, "output JSON")
@@ -48,6 +49,7 @@
 	flags.StringVar(&cfg.mode, "mode", modeSource, "supports source or binary")
 	flags.Var(&tagsFlag, "tags", "comma-separated `list` of build tags")
 	flags.Var(&showFlag, "show", "enable display of additional information specified by the comma separated `list`\nThe only supported value is 'traces'")
+	flags.BoolVar(&version, "version", false, "print the version information")
 	scanLevel := flags.String("scan", "symbol", "set the scanning level desired, one of module, package or symbol")
 	flags.Usage = func() {
 		fmt.Fprint(flags.Output(), `Govulncheck reports known vulnerabilities in dependencies.
@@ -68,12 +70,11 @@
 		return err
 	}
 	cfg.patterns = flags.Args()
-	if cfg.mode != modeConvert && len(cfg.patterns) == 0 {
-		flags.Usage()
-		return errUsage
-	}
 	cfg.tags = tagsFlag
 	cfg.show = showFlag
+	if version {
+		cfg.show = append(cfg.show, "version")
+	}
 	cfg.ScanLevel = govulncheck.ScanLevel(*scanLevel)
 	if err := validateConfig(cfg); err != nil {
 		fmt.Fprintln(flags.Output(), err)
diff --git a/internal/scan/source.go b/internal/scan/source.go
index cfdc122..ca3f2e0 100644
--- a/internal/scan/source.go
+++ b/internal/scan/source.go
@@ -23,6 +23,9 @@
 // symbol is actually exercised) or just imported by the package
 // (likely having a non-affecting outcome).
 func runSource(ctx context.Context, handler govulncheck.Handler, cfg *config, client *client.Client, dir string) error {
+	if len(cfg.patterns) == 0 {
+		return nil
+	}
 	var pkgs []*packages.Package
 	graph := vulncheck.NewPackageGraph(cfg.GoVersion)
 	pkgConfig := &packages.Config{
diff --git a/internal/scan/testdata/binary.txt b/internal/scan/testdata/binary.txt
index 9bbd751..aabc895 100644
--- a/internal/scan/testdata/binary.txt
+++ b/internal/scan/testdata/binary.txt
@@ -1,5 +1,3 @@
-Using govulncheck with vulnerability data from .
-
 Vulnerability #1: GO-0000-0002
     Stdlib vulnerability
   More info: https://pkg.go.dev/vuln/GO-0000-0002
diff --git a/internal/scan/testdata/multi-stacks.txt b/internal/scan/testdata/multi-stacks.txt
index 8fd6a20..fd8a629 100644
--- a/internal/scan/testdata/multi-stacks.txt
+++ b/internal/scan/testdata/multi-stacks.txt
@@ -1,5 +1,3 @@
-Using govulncheck with vulnerability data from .
-
 Vulnerability #1: GO-0000-0001
     Third-party vulnerability
   More info: https://pkg.go.dev/vuln/GO-0000-0001
diff --git a/internal/scan/testdata/no-vulns.txt b/internal/scan/testdata/no-vulns.txt
index dd753c1..45389ff 100644
--- a/internal/scan/testdata/no-vulns.txt
+++ b/internal/scan/testdata/no-vulns.txt
@@ -1,5 +1,3 @@
-Using govulncheck with vulnerability data from .
-
 === Informational ===
 
 Found 1 vulnerability in packages that you import, but there are no call
diff --git a/internal/scan/testdata/platform-all.txt b/internal/scan/testdata/platform-all.txt
index 1c456fe..d3ae80b 100644
--- a/internal/scan/testdata/platform-all.txt
+++ b/internal/scan/testdata/platform-all.txt
@@ -1,5 +1,3 @@
-Using govulncheck with vulnerability data from .
-
 === Informational ===
 
 Found 1 vulnerability in packages that you import, but there are no call
diff --git a/internal/scan/testdata/platform-one-arch-only.txt b/internal/scan/testdata/platform-one-arch-only.txt
index 2884b45..81283df 100644
--- a/internal/scan/testdata/platform-one-arch-only.txt
+++ b/internal/scan/testdata/platform-one-arch-only.txt
@@ -1,5 +1,3 @@
-Using govulncheck with vulnerability data from .
-
 === Informational ===
 
 Found 1 vulnerability in packages that you import, but there are no call
diff --git a/internal/scan/testdata/platform-one-import.txt b/internal/scan/testdata/platform-one-import.txt
index 80d3cc8..9f372a7 100644
--- a/internal/scan/testdata/platform-one-import.txt
+++ b/internal/scan/testdata/platform-one-import.txt
@@ -1,5 +1,3 @@
-Using govulncheck with vulnerability data from .
-
 === Informational ===
 
 Found 1 vulnerability in packages that you import, but there are no call
diff --git a/internal/scan/testdata/platform-two-imports.txt b/internal/scan/testdata/platform-two-imports.txt
index 0445288..554e5f8 100644
--- a/internal/scan/testdata/platform-two-imports.txt
+++ b/internal/scan/testdata/platform-two-imports.txt
@@ -1,5 +1,3 @@
-Using govulncheck with vulnerability data from .
-
 === Informational ===
 
 Found 1 vulnerability in packages that you import, but there are no call
diff --git a/internal/scan/testdata/platform-two-os-only.txt b/internal/scan/testdata/platform-two-os-only.txt
index 68e54c8..d3d6b18 100644
--- a/internal/scan/testdata/platform-two-os-only.txt
+++ b/internal/scan/testdata/platform-two-os-only.txt
@@ -1,5 +1,3 @@
-Using govulncheck with vulnerability data from .
-
 === Informational ===
 
 Found 1 vulnerability in packages that you import, but there are no call
diff --git a/internal/scan/testdata/source.txt b/internal/scan/testdata/source.txt
index abdf57a..5278bc8 100644
--- a/internal/scan/testdata/source.txt
+++ b/internal/scan/testdata/source.txt
@@ -1,5 +1,3 @@
-Using govulncheck with vulnerability data from .
-
 Vulnerability #1: GO-0000-0001
     Third-party vulnerability
   More info: https://pkg.go.dev/vuln/GO-0000-0001
diff --git a/internal/scan/testdata/source_traces.txt b/internal/scan/testdata/source_traces.txt
index 18769f5..7155ef3 100644
--- a/internal/scan/testdata/source_traces.txt
+++ b/internal/scan/testdata/source_traces.txt
@@ -1,5 +1,3 @@
-Using govulncheck with vulnerability data from .
-
 Vulnerability #1: GO-0000-0001
     Third-party vulnerability
   More info: https://pkg.go.dev/vuln/GO-0000-0001
diff --git a/internal/scan/text.go b/internal/scan/text.go
index 0364d5e..879f5ab 100644
--- a/internal/scan/text.go
+++ b/internal/scan/text.go
@@ -18,8 +18,6 @@
 
 const (
 	defaultStyle = style(iota)
-	goStyle
-	scannerStyle
 	osvCalledStyle
 	osvImportedStyle
 	detailsStyle
@@ -40,8 +38,9 @@
 
 	err error
 
-	showColor  bool
-	showTraces bool
+	showColor   bool
+	showTraces  bool
+	showVersion bool
 }
 
 const (
@@ -57,6 +56,8 @@
 			h.showTraces = true
 		case "color":
 			h.showColor = true
+		case "version":
+			h.showVersion = true
 		}
 	}
 }
@@ -82,25 +83,32 @@
 	return nil
 }
 
-// Config writes text output formatted according to govulncheck-intro.tmpl.
+// Config writes version information only if --version was set.
 func (h *TextHandler) Config(config *govulncheck.Config) error {
-	h.print("Using ")
+	if !h.showVersion {
+		return nil
+	}
 	if config.GoVersion != "" {
-		h.style(goStyle, config.GoVersion)
-		h.print(` and `)
+		h.style(keyStyle, "Go: ")
+		h.print(config.GoVersion, "\n")
 	}
 	if config.ScannerName != "" {
-		h.style(scannerStyle, config.ScannerName)
+		h.style(keyStyle, "Scanner: ")
+		h.print(config.ScannerName)
 		if config.ScannerVersion != "" {
 			h.print(`@`, config.ScannerVersion)
 		}
-		h.print(` with `)
+		h.print("\n")
 	}
-	h.print(`vulnerability data from `, config.DB)
-	if config.DBLastModified != nil {
-		h.print(` (last modified `, *config.DBLastModified, `)`)
+	if config.DB != "" {
+		h.style(keyStyle, "DB: ")
+		h.print(config.DB, "\n")
+		if config.DBLastModified != nil {
+			h.style(keyStyle, "DB updated: ")
+			h.print(*config.DBLastModified, "\n")
+		}
 	}
-	h.print(".\n\n")
+	h.print("\n")
 	return h.err
 }
 
@@ -279,10 +287,6 @@
 		switch style {
 		default:
 			h.print(colorReset)
-		case goStyle:
-			h.print(colorBold)
-		case scannerStyle:
-			h.print(colorBold)
 		case osvCalledStyle:
 			h.print(colorBold, fgRed)
 		case osvImportedStyle: