cmd: centralize flag handling for indexers

Change-Id: Ia2129b15c4f222daee33117e849f9ce763620d51
diff --git a/cmd/flags.go b/cmd/flags.go
new file mode 100644
index 0000000..20c64a6
--- /dev/null
+++ b/cmd/flags.go
@@ -0,0 +1,52 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// 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 cmd
+
+import (
+	"flag"
+	"fmt"
+	"os"
+	"path/filepath"
+
+	"github.com/google/zoekt"
+	"github.com/google/zoekt/build"
+)
+
+var (
+	sizeMax     = flag.Int("file_limit", 128*1024, "maximum file size")
+	shardLimit  = flag.Int("shard_limit", 100<<20, "maximum corpus size for a shard")
+	parallelism = flag.Int("parallelism", 4, "maximum number of parallel indexing processes.")
+	indexDir    = flag.String("index", build.DefaultDir, "directory for search indices")
+	version     = flag.Bool("version", false, "Print version number")
+	ctags       = flag.Bool("require_ctags", false, "If set, ctags calls must succeed.")
+)
+
+func OptionsFromFlags() *build.Options {
+	if *version {
+		name := filepath.Base(os.Args[0])
+		fmt.Printf("%s version %q\n", name, zoekt.Version)
+		os.Exit(0)
+	}
+
+	opts := &build.Options{
+		Parallelism:      *parallelism,
+		SizeMax:          *sizeMax,
+		ShardMax:         *shardLimit,
+		IndexDir:         *indexDir,
+		CTagsMustSucceed: *ctags,
+	}
+	opts.SetDefaults()
+	return opts
+}
diff --git a/cmd/zoekt-archive-index/main.go b/cmd/zoekt-archive-index/main.go
index 776e17b..2efcfe3 100644
--- a/cmd/zoekt-archive-index/main.go
+++ b/cmd/zoekt-archive-index/main.go
@@ -20,6 +20,7 @@
 
 	"github.com/google/zoekt"
 	"github.com/google/zoekt/build"
+	"github.com/google/zoekt/cmd"
 	"github.com/google/zoekt/gitindex"
 )
 
@@ -196,12 +197,7 @@
 
 func main() {
 	var (
-		sizeMax     = flag.Int("file_limit", 128*1024, "maximum file size")
-		shardLimit  = flag.Int("shard_limit", 100<<20, "maximum corpus size for a shard")
-		parallelism = flag.Int("parallelism", 4, "maximum number of parallel indexing processes.")
-		indexDir    = flag.String("index", build.DefaultDir, "index directory for *.zoekt files.")
 		incremental = flag.Bool("incremental", true, "only index changed repositories")
-		ctags       = flag.Bool("require_ctags", false, "If set, ctags calls must succeed.")
 
 		name   = flag.String("name", "", "The repository name for the archive")
 		urlRaw = flag.String("url", "", "The repository URL for the archive")
@@ -217,14 +213,7 @@
 		log.Fatal("expected argument for archive location")
 	}
 	archive := flag.Args()[0]
-
-	bopts := build.Options{
-		Parallelism:      *parallelism,
-		SizeMax:          *sizeMax,
-		ShardMax:         *shardLimit,
-		IndexDir:         *indexDir,
-		CTagsMustSucceed: *ctags,
-	}
+	bopts := cmd.OptionsFromFlags()
 	opts := Options{
 		Incremental: *incremental,
 
@@ -236,7 +225,7 @@
 		Strip:   *strip,
 	}
 
-	if err := do(opts, bopts); err != nil {
+	if err := do(opts, *bopts); err != nil {
 		log.Fatal(err)
 	}
 }
diff --git a/cmd/zoekt-git-index/main.go b/cmd/zoekt-git-index/main.go
index c424107..59f7d6e 100644
--- a/cmd/zoekt-git-index/main.go
+++ b/cmd/zoekt-git-index/main.go
@@ -16,42 +16,27 @@
 
 import (
 	"flag"
-	"fmt"
 	"log"
 	"os"
 	"path/filepath"
 	"strings"
 
-	"github.com/google/zoekt"
-	"github.com/google/zoekt/build"
+	"github.com/google/zoekt/cmd"
 	"github.com/google/zoekt/gitindex"
 )
 
-var _ = log.Println
-
 func main() {
-	var sizeMax = flag.Int("file_limit", 128*1024, "maximum file size")
-	var shardLimit = flag.Int("shard_limit", 100<<20, "maximum corpus size for a shard")
-	var parallelism = flag.Int("parallelism", 4, "maximum number of parallel indexing processes.")
 	allowMissing := flag.Bool("allow_missing_branches", false, "allow missing branches.")
 	submodules := flag.Bool("submodules", true, "if set to false, do not recurse into submodules")
 	branchesStr := flag.String("branches", "HEAD", "git branches to index.")
 	branchPrefix := flag.String("prefix", "refs/heads/", "prefix for branch names")
 
-	indexDir := flag.String("index", build.DefaultDir, "index directory for *.zoekt files.")
 	incremental := flag.Bool("incremental", true, "only index changed repositories")
 	repoCacheDir := flag.String("repo_cache", "", "directory holding bare git repos, named by URL. "+
 		"this is used to find repositories for submodules. "+
 		"It also affects name if the indexed repository is under this directory.")
-	ctags := flag.Bool("require_ctags", false, "If set, ctags calls must succeed.")
-	version := flag.Bool("version", false, "Print version number")
 	flag.Parse()
 
-	if *version {
-		fmt.Printf("zoekt-git-index version %q\n", zoekt.Version)
-		os.Exit(0)
-	}
-
 	if *repoCacheDir != "" {
 		dir, err := filepath.Abs(*repoCacheDir)
 		if err != nil {
@@ -59,14 +44,7 @@
 		}
 		*repoCacheDir = dir
 	}
-	opts := build.Options{
-		Parallelism:      *parallelism,
-		SizeMax:          *sizeMax,
-		ShardMax:         *shardLimit,
-		IndexDir:         *indexDir,
-		CTagsMustSucceed: *ctags,
-	}
-	opts.SetDefaults()
+	opts := cmd.OptionsFromFlags()
 
 	var branches []string
 	if *branchesStr != "" {
@@ -100,7 +78,7 @@
 			Submodules:         *submodules,
 			RepoCacheDir:       *repoCacheDir,
 			AllowMissingBranch: *allowMissing,
-			BuildOptions:       opts,
+			BuildOptions:       *opts,
 			Branches:           branches,
 			RepoDir:            dir,
 		}
diff --git a/cmd/zoekt-index/main.go b/cmd/zoekt-index/main.go
index 223a472..54ff4ff 100644
--- a/cmd/zoekt-index/main.go
+++ b/cmd/zoekt-index/main.go
@@ -26,6 +26,7 @@
 
 	"github.com/google/zoekt"
 	"github.com/google/zoekt/build"
+	"github.com/google/zoekt/cmd"
 )
 
 type fileInfo struct {
@@ -59,21 +60,11 @@
 
 func main() {
 	var cpuProfile = flag.String("cpu_profile", "", "write cpu profile to file")
-	var sizeMax = flag.Int("file_limit", 128*1024, "maximum file size")
-	var shardLimit = flag.Int("shard_limit", 100<<20, "maximum corpus size for a shard")
-	var parallelism = flag.Int("parallelism", 4, "maximum number of parallel indexing processes.")
 
 	ignoreDirs := flag.String("ignore_dirs", ".git,.hg,.svn", "comma separated list of directories to ignore.")
-	indexDir := flag.String("index", build.DefaultDir, "directory for search indices")
 	flag.Parse()
 
-	opts := build.Options{
-		Parallelism: *parallelism,
-		SizeMax:     *sizeMax,
-		ShardMax:    *shardLimit,
-		IndexDir:    *indexDir,
-	}
-	opts.SetDefaults()
+	opts := cmd.OptionsFromFlags()
 	if *cpuProfile != "" {
 		f, err := os.Create(*cpuProfile)
 		if err != nil {
@@ -95,7 +86,7 @@
 	}
 	for _, arg := range flag.Args() {
 		opts.RepositoryDescription.Source = arg
-		if err := indexArg(arg, opts, ignoreDirMap); err != nil {
+		if err := indexArg(arg, *opts, ignoreDirMap); err != nil {
 			log.Fatal(err)
 		}
 	}