[cli] Add `shac version` command

Change-Id: I5c76487863a8554e29cd83441f3a7d997bc7d125
Reviewed-on: https://fuchsia-review.googlesource.com/c/shac-project/shac/+/904699
Fuchsia-Auto-Submit: Oliver Newman <olivernewman@google.com>
Reviewed-by: Marc-Antoine Ruel <maruel@google.com>
Commit-Queue: Auto-Submit <auto-submit@fuchsia-infra.iam.gserviceaccount.com>
diff --git a/internal/cli/main.go b/internal/cli/main.go
index 115de4c..8bb7616 100644
--- a/internal/cli/main.go
+++ b/internal/cli/main.go
@@ -74,6 +74,7 @@
 		&fmtCmd{},
 		&fixCmd{},
 		&docCmd{},
+		&versionCmd{},
 		&helpCmd{},
 	}
 	a := app{}
diff --git a/internal/cli/version.go b/internal/cli/version.go
new file mode 100644
index 0000000..227c72c
--- /dev/null
+++ b/internal/cli/version.go
@@ -0,0 +1,47 @@
+// Copyright 2023 The Shac Authors
+//
+// 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 cli
+
+import (
+	"context"
+	"fmt"
+	"os"
+
+	flag "github.com/spf13/pflag"
+	"go.fuchsia.dev/shac-project/shac/internal/engine"
+)
+
+type versionCmd struct {
+}
+
+func (*versionCmd) Name() string {
+	return "version"
+}
+
+func (*versionCmd) Description() string {
+	return "Print shac version."
+}
+
+func (*versionCmd) SetFlags(f *flag.FlagSet) {
+}
+
+func (*versionCmd) Execute(ctx context.Context, args []string) error {
+	_, err := fmt.Fprintf(os.Stdout, "shac v%d.%d.%d\n",
+		engine.Version[0],
+		engine.Version[1],
+		engine.Version[2],
+	)
+	return err
+}
diff --git a/internal/engine/config.go b/internal/engine/config.go
index d816dc8..9fa74c8 100644
--- a/internal/engine/config.go
+++ b/internal/engine/config.go
@@ -27,14 +27,14 @@
 func (doc *Document) Validate() error {
 	if doc.MinShacVersion != "" {
 		v := parseVersion(doc.MinShacVersion)
-		if v == nil || len(v) > len(version) {
+		if v == nil || len(v) > len(Version) {
 			return errors.New("min_shac_version is invalid")
 		}
 		for i := range v {
-			if v[i] > version[i] {
-				return fmt.Errorf("min_shac_version specifies unsupported version %q, running %d.%d.%d", doc.MinShacVersion, version[0], version[1], version[2])
+			if v[i] > Version[i] {
+				return fmt.Errorf("min_shac_version specifies unsupported version %q, running %d.%d.%d", doc.MinShacVersion, Version[0], Version[1], Version[2])
 			}
-			if v[i] < version[i] {
+			if v[i] < Version[i] {
 				break
 			}
 		}
diff --git a/internal/engine/config_test.go b/internal/engine/config_test.go
index bb4abfe..d5aaed2 100644
--- a/internal/engine/config_test.go
+++ b/internal/engine/config_test.go
@@ -16,6 +16,7 @@
 
 import (
 	"errors"
+	"fmt"
 	"strconv"
 	"testing"
 
@@ -252,7 +253,14 @@
 		},
 		{
 			"min_shac_version: \"1000\"\n",
-			"min_shac_version specifies unsupported version \"1000\", running 0.0.1",
+			func() string {
+				return fmt.Sprintf(
+					"min_shac_version specifies unsupported version \"1000\", running %d.%d.%d",
+					Version[0],
+					Version[1],
+					Version[2],
+				)
+			}(),
 		},
 		{
 			"min_shac_version: \"1.2.c\"\n",
diff --git a/internal/engine/run_test.go b/internal/engine/run_test.go
index 8a21456..3c187b6 100644
--- a/internal/engine/run_test.go
+++ b/internal/engine/run_test.go
@@ -1543,7 +1543,7 @@
 func TestTestDataPrint(t *testing.T) {
 	t.Parallel()
 	p, got := enumDir(t, "print")
-	v := fmt.Sprintf("(%d, %d, %d)", version[0], version[1], version[2])
+	v := fmt.Sprintf("(%d, %d, %d)", Version[0], Version[1], Version[2])
 	data := []struct {
 		name string
 		want string
diff --git a/internal/engine/runtime_shac.go b/internal/engine/runtime_shac.go
index 9ee8757..a4b0b61 100644
--- a/internal/engine/runtime_shac.go
+++ b/internal/engine/runtime_shac.go
@@ -24,10 +24,10 @@
 )
 
 var (
-	// version is the current tool version.
+	// Version is the current tool version.
 	//
 	// TODO(maruel): Add proper version, preferably from git tag.
-	version = [...]int{0, 0, 1}
+	Version = [...]int{0, 1, 0}
 )
 
 // getShac returns the global shac object.
@@ -39,7 +39,7 @@
 		"commit_hash":    starlark.String(getCommitHash()),
 		"register_check": newBuiltinNone("shac.register_check", shacRegisterCheck),
 		"version": starlark.Tuple{
-			starlark.MakeInt(version[0]), starlark.MakeInt(version[1]), starlark.MakeInt(version[2]),
+			starlark.MakeInt(Version[0]), starlark.MakeInt(Version[1]), starlark.MakeInt(Version[2]),
 		},
 	}
 }
diff --git a/shac.textproto b/shac.textproto
index f0a7b5f..b1abc41 100644
--- a/shac.textproto
+++ b/shac.textproto
@@ -15,7 +15,7 @@
 # TODO(olivernewman): Build github.com/protocolbuffers/txtpbfmt into shac and
 # enforce formatting of shac.textproto files in all repos that use shac.
 
-min_shac_version: "0.0.0"
+min_shac_version: "0.1.0"
 allow_network: False
 ignore: "/vendor/"
 # Vendored code for test data only.