fork of https://github.com/sourcegraph/zoekt
1package gitindex
2
3import (
4 "bytes"
5 "errors"
6 "fmt"
7 "maps"
8 "os/exec"
9 "slices"
10 "strings"
11)
12
13func sortedKeys(settings map[string]string) []string {
14 return slices.Sorted(maps.Keys(settings))
15}
16
17func cloneConfigArgs(settings map[string]string) []string {
18 args := make([]string, 0, len(settings)*2)
19 for _, key := range sortedKeys(settings) {
20 if value := settings[key]; value != "" {
21 args = append(args, "--config", key+"="+value)
22 }
23 }
24 return args
25}
26
27// updateZoektGitConfig applies zoekt.* settings to an existing clone.
28// It returns whether the repository config changed.
29func updateZoektGitConfig(repoDest string, settings map[string]string) (bool, error) {
30 changed := false
31 for _, key := range sortedKeys(settings) {
32 updated, err := syncGitConfigOption(repoDest, key, settings[key])
33 if err != nil {
34 return false, err
35 }
36 changed = changed || updated
37 }
38 return changed, nil
39}
40
41func syncGitConfigOption(repoDest, key, value string) (bool, error) {
42 current, ok, err := repoConfigValue(repoDest, key)
43 if err != nil {
44 return false, err
45 }
46
47 if value == "" {
48 if !ok {
49 return false, nil
50 }
51 if err := unsetRepoConfigValue(repoDest, key); err != nil {
52 return false, err
53 }
54 return true, nil
55 }
56
57 if ok && current == value {
58 return false, nil
59 }
60 if err := setRepoConfigValue(repoDest, key, value); err != nil {
61 return false, err
62 }
63 return true, nil
64}
65
66func repoConfigValue(repoDest, key string) (string, bool, error) {
67 cmd := exec.Command("git", "-C", repoDest, "config", "--get", key)
68 var out bytes.Buffer
69 cmd.Stdout = &out
70 if err := cmd.Run(); err == nil {
71 return strings.TrimSuffix(out.String(), "\n"), true, nil
72 } else {
73 var exitErr *exec.ExitError
74 if errors.As(err, &exitErr) && exitErr.ExitCode() == 1 {
75 return "", false, nil
76 }
77 return "", false, fmt.Errorf("git config --get %q: %w", key, err)
78 }
79}
80
81func setRepoConfigValue(repoDest, key, value string) error {
82 if err := exec.Command("git", "-C", repoDest, "config", "--replace-all", key, value).Run(); err != nil {
83 return fmt.Errorf("git config --replace-all %q: %w", key, err)
84 }
85 return nil
86}
87
88func unsetRepoConfigValue(repoDest, key string) error {
89 if err := exec.Command("git", "-C", repoDest, "config", "--unset-all", key).Run(); err != nil {
90 return fmt.Errorf("git config --unset-all %q: %w", key, err)
91 }
92 return nil
93}