Support GitHub Enterprise urls in zoekt-github-mirror.
Closes #72.

Change-Id: I8768b71226a65ce86ed4a668caa0c85047dea866
diff --git a/cmd/zoekt-indexserver/config.go b/cmd/zoekt-indexserver/config.go
index f3ea3b0..07ee329 100644
--- a/cmd/zoekt-indexserver/config.go
+++ b/cmd/zoekt-indexserver/config.go
@@ -33,6 +33,7 @@
 type configEntry struct {
 	GithubUser             string
 	BitBucketServerProject string
+	GitHubURL              string
 	GitilesURL             string
 	CGitURL                string
 	BitBucketServerURL     string
@@ -156,6 +157,9 @@
 		if c.GithubUser != "" {
 			cmd = exec.Command("zoekt-mirror-github",
 				"-dest", repoDir)
+			if c.GitHubURL != "" {
+				cmd.Args = append(cmd.Args, "-url", c.GitHubURL)
+			}
 			if c.GithubUser != "" {
 				cmd.Args = append(cmd.Args, "-user", c.GithubUser)
 			}
diff --git a/cmd/zoekt-mirror-github/main.go b/cmd/zoekt-mirror-github/main.go
index eff1eaa..7973362 100644
--- a/cmd/zoekt-mirror-github/main.go
+++ b/cmd/zoekt-mirror-github/main.go
@@ -38,6 +38,7 @@
 
 func main() {
 	dest := flag.String("dest", "", "destination directory")
+	githubURL := flag.String("url", "", "GitHub Enterprise url. If not set github.com will be used as the host.")
 	org := flag.String("org", "", "organization to mirror")
 	user := flag.String("user", "", "user to mirror")
 	token := flag.String("token",
@@ -56,12 +57,34 @@
 		log.Fatal("must set either --org or --user")
 	}
 
-	destDir := filepath.Join(*dest, "github.com")
+	var host string
+	var apiBaseURL string
+	var client *github.Client
+	if *githubURL != "" {
+		rootURL, err := url.Parse(*githubURL)
+		if err != nil {
+			log.Fatal(err)
+		}
+		host = rootURL.Host
+		apiPath, err := url.Parse("/api/v3/")
+		if err != nil {
+			log.Fatal(err)
+		}
+		apiBaseURL = rootURL.ResolveReference(apiPath).String()
+		client, err = github.NewEnterpriseClient(apiBaseURL, apiBaseURL, nil)
+		if err != nil {
+			log.Fatal(err)
+		}
+	} else {
+		host = "github.com"
+		apiBaseURL = "https://github.com/"
+		client = github.NewClient(nil)
+	}
+	destDir := filepath.Join(*dest, host)
 	if err := os.MkdirAll(destDir, 0755); err != nil {
 		log.Fatal(err)
 	}
 
-	client := github.NewClient(nil)
 	if *token != "" {
 		content, err := ioutil.ReadFile(*token)
 		if err != nil {
@@ -73,7 +96,14 @@
 				AccessToken: strings.TrimSpace(string(content)),
 			})
 		tc := oauth2.NewClient(context.Background(), ts)
-		client = github.NewClient(tc)
+		if *githubURL != "" {
+			client, err = github.NewEnterpriseClient(apiBaseURL, apiBaseURL, tc)
+			if err != nil {
+				log.Fatal(err)
+			}
+		} else {
+			client = github.NewClient(tc)
+		}
 	}
 
 	var repos []*github.Repository
@@ -125,7 +155,13 @@
 }
 
 func deleteStaleRepos(destDir string, filter *gitindex.Filter, repos []*github.Repository, user string) error {
-	u, err := url.Parse("https://github.com/" + user)
+	var baseURL string
+	if len(repos) > 0 {
+		baseURL = *repos[0].HTMLURL
+	} else {
+		return nil
+	}
+	u, err := url.Parse(baseURL + user)
 	if err != nil {
 		return err
 	}
@@ -219,10 +255,14 @@
 
 func cloneRepos(destDir string, repos []*github.Repository) error {
 	for _, r := range repos {
+		host, err := url.Parse(*r.HTMLURL)
+		if err != nil {
+			return err
+		}
 		config := map[string]string{
 			"zoekt.web-url-type": "github",
 			"zoekt.web-url":      *r.HTMLURL,
-			"zoekt.name":         filepath.Join("github.com", *r.FullName),
+			"zoekt.name":         filepath.Join(host.Hostname(), *r.FullName),
 
 			"zoekt.github-stars":       itoa(r.StargazersCount),
 			"zoekt.github-watchers":    itoa(r.WatchersCount),