cmd/zoekt-indexserver: set timeout on zoekt-git-index calls

Change-Id: I17c84126feb46deec68e5cea08c11c146253cba4
diff --git a/cmd/zoekt-indexserver/main.go b/cmd/zoekt-indexserver/main.go
index a7346a9..eaf322d 100644
--- a/cmd/zoekt-indexserver/main.go
+++ b/cmd/zoekt-indexserver/main.go
@@ -21,6 +21,7 @@
 
 import (
 	"bytes"
+	"context"
 	"flag"
 	"fmt"
 	"log"
@@ -62,6 +63,7 @@
 	indexFlags       []string
 	mirrorConfigFile string
 	maxLogAge        time.Duration
+	indexTimeout     time.Duration
 }
 
 func (o *Options) validate() {
@@ -79,6 +81,7 @@
 }
 
 func (o *Options) defineFlags() {
+	flag.DurationVar(&o.indexTimeout, "index_timeout", time.Hour, "kill index job after this much time")
 	flag.DurationVar(&o.maxLogAge, "max_log_age", 3*day, "recycle index logs after this much time")
 	flag.DurationVar(&o.fetchInterval, "fetch_interval", time.Hour, "run fetches this often")
 	flag.StringVar(&o.mirrorConfigFile, "mirror_config",
@@ -147,20 +150,27 @@
 // indexes them, sequentially.
 func indexPendingRepos(indexDir, repoDir string, opts *Options, repos <-chan string) {
 	for dir := range repos {
-		args := []string{
-			"-require_ctags",
-			fmt.Sprintf("-parallelism=%d", opts.cpuCount),
-			"-repo_cache", repoDir,
-			"-index", indexDir,
-			"-incremental",
-		}
-		args = append(args, opts.indexFlags...)
-		args = append(args, dir)
-		cmd := exec.Command("zoekt-git-index", args...)
-		loggedRun(cmd)
+		indexPendingRepo(dir, indexDir, repoDir, opts)
 	}
 }
 
+func indexPendingRepo(dir, indexDir, repoDir string, opts *Options) {
+	ctx, cancel := context.WithTimeout(context.Background(), opts.indexTimeout)
+	defer cancel()
+	args := []string{
+		"-require_ctags",
+		fmt.Sprintf("-parallelism=%d", opts.cpuCount),
+		"-repo_cache", repoDir,
+		"-index", indexDir,
+		"-incremental",
+	}
+	args = append(args, opts.indexFlags...)
+	args = append(args, dir)
+	cmd := exec.CommandContext(ctx, "zoekt-git-index", args...)
+	loggedRun(cmd)
+
+}
+
 // deleteLogs deletes old logs.
 func deleteLogs(logDir string, maxAge time.Duration) {
 	fs, err := filepath.Glob(filepath.Join(logDir, "*"))