1// Copyright 2015 The Go Authors.  All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package main
6
7import (
8	"fmt"
9	"io/ioutil"
10	"path/filepath"
11	"strings"
12)
13
14var (
15	configPath   string
16	cachedConfig map[string]string
17)
18
19// Config returns the code review config.
20// Configs consist of lines of the form "key: value".
21// Lines beginning with # are comments.
22// If there is no config, it returns an empty map.
23// If the config is malformed, it dies.
24func config() map[string]string {
25	if cachedConfig != nil {
26		return cachedConfig
27	}
28	configPath = filepath.Join(repoRoot(), "codereview.cfg")
29	b, err := ioutil.ReadFile(configPath)
30	raw := string(b)
31	if err != nil {
32		verbosef("%sfailed to load config from %q: %v", raw, configPath, err)
33		cachedConfig = make(map[string]string)
34		return cachedConfig
35	}
36	cachedConfig, err = parseConfig(raw)
37	if err != nil {
38		dief("%v", err)
39	}
40	return cachedConfig
41}
42
43// haveGerrit returns true if gerrit should be used.
44// To enable gerrit, codereview.cfg must be present with "gerrit" property set to
45// the gerrit https URL or the git origin must be to
46// "https://<project>.googlesource.com/<repo>".
47func haveGerrit() bool {
48	gerrit := config()["gerrit"]
49	origin := trim(cmdOutput("git", "config", "remote.origin.url"))
50	return haveGerritInternal(gerrit, origin)
51}
52
53// haveGerritInternal is the same as haveGerrit but factored out
54// for testing.
55func haveGerritInternal(gerrit, origin string) bool {
56	if gerrit == "off" {
57		return false
58	}
59	if gerrit != "" {
60		return true
61	}
62	if strings.Contains(origin, "github.com") {
63		return false
64	}
65	if strings.HasPrefix(origin, "sso://") || strings.HasPrefix(origin, "rpc://") {
66		return true
67	}
68	if !strings.Contains(origin, "https://") {
69		return false
70	}
71	if strings.Count(origin, "/") != 3 {
72		return false
73	}
74	host := origin[:strings.LastIndex(origin, "/")]
75	return strings.HasSuffix(host, ".googlesource.com")
76}
77
78func haveGitHub() bool {
79	origin := trim(cmdOutput("git", "config", "remote.origin.url"))
80	return strings.Contains(origin, "github.com")
81}
82
83func parseConfig(raw string) (map[string]string, error) {
84	cfg := make(map[string]string)
85	for _, line := range nonBlankLines(raw) {
86		line = strings.TrimSpace(line)
87		if strings.HasPrefix(line, "#") {
88			// comment line
89			continue
90		}
91		fields := strings.SplitN(line, ":", 2)
92		if len(fields) != 2 {
93			return nil, fmt.Errorf("bad config line, expected 'key: value': %q", line)
94		}
95		cfg[strings.TrimSpace(fields[0])] = strings.TrimSpace(fields[1])
96	}
97	return cfg, nil
98}
99