forked from gopasspw/gopass
/
config.go
118 lines (97 loc) · 3.39 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package cli
import (
"bytes"
"context"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/fatih/color"
"github.com/justwatchcom/gopass/store"
"github.com/justwatchcom/gopass/utils/out"
"github.com/pkg/errors"
)
const (
fileMode = 0600
)
func (g *Git) fixConfig(ctx context.Context) error {
// set push default, to avoid issues with
// "fatal: The current branch master has multiple upstream branches, refusing to push"
// https://stackoverflow.com/questions/948354/default-behavior-of-git-push-without-a-branch-specified
if err := g.ConfigSet(ctx, "push.default", "matching"); err != nil {
return errors.Wrapf(err, "failed to set git config for push.default")
}
// setup for proper diffs
if err := g.ConfigSet(ctx, "diff.gpg.binary", "true"); err != nil {
out.Yellow(ctx, "Error while initializing git: %s", err)
}
if err := g.ConfigSet(ctx, "diff.gpg.textconv", "gpg --no-tty --decrypt"); err != nil {
out.Yellow(ctx, "Error while initializing git: %s", err)
}
if g.gpg == "" {
return nil
}
if err := g.Cmd(ctx, "gitFixConfig", "config", "--local", "gpg.program", g.gpg); err != nil {
return errors.Wrapf(err, "failed to set git config gpg.program")
}
return nil
}
// InitConfig initialized and preparse the git config
func (g *Git) InitConfig(ctx context.Context, signKey, userName, userEmail string) error {
// set commit identity
if err := g.ConfigSet(ctx, "user.name", userName); err != nil {
return errors.Wrapf(err, "failed to set git config user.name")
}
if err := g.ConfigSet(ctx, "user.email", userEmail); err != nil {
return errors.Wrapf(err, "failed to set git config user.email")
}
// ensure sane git config
if err := g.fixConfig(ctx); err != nil {
return errors.Wrapf(err, "failed to fix git config")
}
if err := ioutil.WriteFile(filepath.Join(g.path, ".gitattributes"), []byte("*.gpg diff=gpg\n"), fileMode); err != nil {
return errors.Errorf("Failed to initialize git: %s", err)
}
if err := g.Add(ctx, g.path+"/.gitattributes"); err != nil {
out.Yellow(ctx, "Warning: Failed to add .gitattributes to git")
}
if err := g.Commit(ctx, "Configure git repository for gpg file diff."); err != nil {
out.Yellow(ctx, "Warning: Failed to commit .gitattributes to git")
}
// set GPG signkey
if err := g.SetSignKey(ctx, signKey); err != nil {
color.Yellow("Failed to configure Git GPG Commit signing: %s\n", err)
}
return nil
}
// SetSignKey configures git to use the given sign key
func (g *Git) SetSignKey(ctx context.Context, sk string) error {
if sk == "" {
return errors.Errorf("SignKey not set")
}
if err := g.ConfigSet(ctx, "user.signingkey", sk); err != nil {
return errors.Wrapf(err, "failed to set git sign key")
}
return g.ConfigSet(ctx, "commit.gpgsign", "true")
}
// ConfigSet sets a local config value
func (g *Git) ConfigSet(ctx context.Context, key, value string) error {
return g.Cmd(ctx, "gitConfigSet", "config", "--local", key, value)
}
// ConfigGet returns a given config value
func (g *Git) ConfigGet(ctx context.Context, key string) (string, error) {
if !g.IsInitialized() {
return "", store.ErrGitNotInit
}
buf := &bytes.Buffer{}
cmd := exec.CommandContext(ctx, "git", "config", "--get", key)
cmd.Dir = g.path
cmd.Stdout = buf
cmd.Stderr = os.Stderr
out.Debug(ctx, "store.gitConfigValue: %s %+v", cmd.Path, cmd.Args)
if err := cmd.Run(); err != nil {
return "", err
}
return strings.TrimSpace(buf.String()), nil
}