Skip to content

Commit

Permalink
Make source VCS pull command configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
twpayne committed Jan 28, 2019
1 parent 013e419 commit 792c631
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 47 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -471,13 +471,14 @@ You can encrypt your configuration and then only decrypt it when needed:

`chezmoi` has some helper commands to assist managing your source directory
with version control. The default version control system is `git` but you can
change this by setting `sourceVCSCommand` in your
change this by setting `sourceVCS.command` in your
`~/.config/chezmoi/chezmoi.yaml` file, for example, if you want to use
Mercurial:

sourceVCSCommand: hg
sourceVCS:
command: hg

`chezmoi source` is then a shortcut to running `sourceVCSCommand` in your
`chezmoi source` is then a shortcut to running `sourceVCS.command` in your
`~/.local/share/chezmoi` directory. For example you can push the current branch
with:

Expand Down
14 changes: 8 additions & 6 deletions cmd/add_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,12 +299,14 @@ func TestAddCommand(t *testing.T) {
} {
t.Run(tc.name, func(t *testing.T) {
c := &Config{
SourceDir: "/home/user/.chezmoi",
DestDir: "/home/user",
Umask: 022,
DryRun: false,
Verbose: true,
SourceVCSCommand: "git",
SourceDir: "/home/user/.chezmoi",
DestDir: "/home/user",
Umask: 022,
DryRun: false,
Verbose: true,
SourceVCS: sourceVCSConfig{
Command: "git",
},
Data: map[string]interface{}{
"name": "John Smith",
"email": "john.smith@company.com",
Expand Down
55 changes: 30 additions & 25 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,36 @@ import (
yaml "gopkg.in/yaml.v2"
)

type sourceVCSConfig struct {
Command string
Pull interface{}
}

// A Config represents a configuration.
type Config struct {
configFile string
SourceDir string
DestDir string
Umask permValue
DryRun bool
Verbose bool
SourceVCSCommand string
Bitwarden bitwardenCommandConfig
GenericSecret genericSecretCommandConfig
LastPass lastpassCommandConfig
OnePassword onepasswordCommandConfig
Vault vaultCommandConfig
Pass passCommandConfig
Data map[string]interface{}
templateFuncs template.FuncMap
add addCommandConfig
data dataCommandConfig
dump dumpCommandConfig
edit editCommandConfig
init initCommandConfig
_import importCommandConfig
keyring keyringCommandConfig
update updateCommandConfig
configFile string
SourceDir string
DestDir string
Umask permValue
DryRun bool
Verbose bool
SourceVCS sourceVCSConfig
Bitwarden bitwardenCommandConfig
GenericSecret genericSecretCommandConfig
LastPass lastpassCommandConfig
OnePassword onepasswordCommandConfig
Vault vaultCommandConfig
Pass passCommandConfig
Data map[string]interface{}
templateFuncs template.FuncMap
add addCommandConfig
data dataCommandConfig
dump dumpCommandConfig
edit editCommandConfig
init initCommandConfig
_import importCommandConfig
keyring keyringCommandConfig
update updateCommandConfig
}

var (
Expand Down Expand Up @@ -203,9 +208,9 @@ func (c *Config) getTargetState(fs vfs.FS) (*chezmoi.TargetState, error) {
}

func (c *Config) getVCSInfo() (*vcsInfo, error) {
vcsInfo, ok := vcsInfos[filepath.Base(c.SourceVCSCommand)]
vcsInfo, ok := vcsInfos[filepath.Base(c.SourceVCS.Command)]
if !ok {
return nil, fmt.Errorf("%s: unsupported source VCS command", c.SourceVCSCommand)
return nil, fmt.Errorf("%s: unsupported source VCS command", c.SourceVCS.Command)
}
return vcsInfo, nil
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/doctor.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ func (c *Config) runDoctorCommandE(fs vfs.FS, args []string) error {
if vcsInfo, err := c.getVCSInfo(); err == nil {
vcsCommandCheck = &doctorBinaryCheck{
name: "source VCS command",
binaryName: c.SourceVCSCommand,
binaryName: c.SourceVCS.Command,
versionArgs: vcsInfo.versionArgs,
versionRegexp: vcsInfo.versionRegexp,
}
} else {
// FIXME print a warning that source VCS command is unsupported
vcsCommandCheck = &doctorBinaryCheck{
name: "source VCS command",
binaryName: c.SourceVCSCommand,
binaryName: c.SourceVCS.Command,
}
}

Expand Down
8 changes: 4 additions & 4 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (c *Config) runInitCommand(fs vfs.FS, args []string) error {
return err
}
if vcsInfo.cloneArgsFunc == nil {
return fmt.Errorf("%s: cloning not supported", c.SourceVCSCommand)
return fmt.Errorf("%s: cloning not supported", c.SourceVCS.Command)
}

mutator := c.getDefaultMutator(fs)
Expand All @@ -60,19 +60,19 @@ func (c *Config) runInitCommand(fs vfs.FS, args []string) error {
}

cloneArgs := vcsInfo.cloneArgsFunc(args[0], c.SourceDir)
if err := c.run("", c.SourceVCSCommand, cloneArgs...); err != nil {
if err := c.run("", c.SourceVCS.Command, cloneArgs...); err != nil {
return err
}

// FIXME this should be part of struct vcs
switch filepath.Base(c.SourceVCSCommand) {
switch filepath.Base(c.SourceVCS.Command) {
case "git":
if _, err := fs.Stat(filepath.Join(c.SourceDir, ".gitmodules")); err == nil {
for _, args := range [][]string{
[]string{"submodule", "init"},
[]string{"submodule", "update"},
} {
if err := c.run(c.SourceDir, c.SourceVCSCommand, args...); err != nil {
if err := c.run(c.SourceDir, c.SourceVCS.Command, args...); err != nil {
return err
}
}
Expand Down
6 changes: 4 additions & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ import (

var (
config = Config{
Umask: permValue(getUmask()),
SourceVCSCommand: "git",
Umask: permValue(getUmask()),
SourceVCS: sourceVCSConfig{
Command: "git",
},
}
version = "dev"
commit = "unknown"
Expand Down
2 changes: 1 addition & 1 deletion cmd/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ func (c *Config) runSourceCommand(fs vfs.FS, args []string) error {
return err
}
}
return c.exec(append([]string{c.SourceVCSCommand}, args...))
return c.exec(append([]string{c.SourceVCS.Command}, args...))
}
20 changes: 17 additions & 3 deletions cmd/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cmd

import (
"fmt"
"strings"

"github.com/spf13/cobra"
vfs "github.com/twpayne/go-vfs"
Expand Down Expand Up @@ -30,11 +31,24 @@ func (c *Config) runUpdateCommand(fs vfs.FS, args []string) error {
if err != nil {
return err
}
if vcsInfo.pullArgs == nil {
return fmt.Errorf("%s: pull not supported", c.SourceVCSCommand)
var pullArgs []string
if c.SourceVCS.Pull != nil {
switch v := c.SourceVCS.Pull.(type) {
case string:
pullArgs = strings.Split(v, " ")
case []string:
pullArgs = v
default:
return fmt.Errorf("sourceVCS.pull: cannot parse value")
}
} else {
pullArgs = vcsInfo.pullArgs
}
if pullArgs == nil {
return fmt.Errorf("%s: pull not supported", c.SourceVCS.Command)
}

if err := c.run(c.SourceDir, c.SourceVCSCommand, vcsInfo.pullArgs...); err != nil {
if err := c.run(c.SourceDir, c.SourceVCS.Command, pullArgs...); err != nil {
return err
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/vcs_infos.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var (
cloneArgsFunc: func(repo, dir string) []string {
return []string{"clone", repo, dir}
},
pullArgs: []string{"pull", "--rebase"}, // FIXME this should be configurable
pullArgs: []string{"pull", "--rebase"},
versionArgs: []string{"version"},
versionRegexp: regexp.MustCompile(`^git version (\d+\.\d+\.\d+)`),
},
Expand Down

0 comments on commit 792c631

Please sign in to comment.