From ba71fe9011f2b75c0cc1420196d48472212895a9 Mon Sep 17 00:00:00 2001 From: Andy Walker Date: Tue, 6 Nov 2018 09:37:28 -0500 Subject: [PATCH] Initial commit for 'dotbro init' --- configuration.go | 6 ++++-- docopt.go | 6 +++++- init_commands.go | 34 ++++++++++++++++++++++++++++++++++ linker.go | 13 +++++++++++++ main.go | 24 ++++++++++++++++++++++-- run_commands.go | 34 ++++++++++++++++++++++++++++++++++ 6 files changed, 112 insertions(+), 5 deletions(-) create mode 100644 init_commands.go create mode 100644 run_commands.go diff --git a/configuration.go b/configuration.go index 836d609..ef2e5d5 100644 --- a/configuration.go +++ b/configuration.go @@ -17,6 +17,7 @@ import ( type Configuration struct { Directories Directories Mapping map[string]string + Init map[string][]string Files Files Filepath string } @@ -42,19 +43,20 @@ func NewConfiguration(filename string) (conf *Configuration, err error) { case ".json": conf, err = fromJSON(filename) default: - err = fmt.Errorf("Cannot read config file %s : unknown extension. Supported: conf, toml.", filename) + err = fmt.Errorf("Cannot read config file %s : unknown extension. Supported: json, toml.", filename) } if err != nil { return nil, err } + conf.Filepath = filename + conf, err = processConf(conf) if err != nil { return nil, err } - conf.Filepath = filename return conf, nil } diff --git a/docopt.go b/docopt.go index 1af4a7c..ca2cf83 100644 --- a/docopt.go +++ b/docopt.go @@ -9,15 +9,19 @@ func ParseArguments(argv []string) (map[string]interface{}, error) { usage := `dotbro - simple yet effective dotfiles manager. Usage: - dotbro [options] [--config=] + dotbro [options] + dotbro init [options] dotbro add [options] dotbro -h | --help dotbro --version Common options: -c --config= Dotbro's configuration file in JSON or TOML format. + [default: dotbro.toml] -q --quiet Quiet mode. Do not print any output, except warnings and errors. + -d --dry Dry mode. Do not take any action, instead print what + WOULD happen (suppresses --quiet). -v --verbose Verbose mode. Detailed output. Add options: diff --git a/init_commands.go b/init_commands.go new file mode 100644 index 0000000..daaa9b3 --- /dev/null +++ b/init_commands.go @@ -0,0 +1,34 @@ +package main + +import ( + "strings" + + . "github.com/logrusorgru/aurora" +) + +func runInitCommands(config *Configuration, outputer Outputer) error { + if err := prepInit(outputer); err != nil { + return err + } + for _, section := range []string{"common", currentOS, "after"} { + commands, has := config.Init[section] + if !has { + return nil + } + outputer.OutInfo("--> Running [%s] init commands...", section) + + for _, command := range commands { + // replace any occurrence of %DOTFILEDIR with dotfile directory + command = strings.Replace(command, "%DOTFILEDIR", config.Directories.Dotfiles, -1) + if dry { + outputer.OutInfo(" %s would run: '%s'", Blue("❯"), command) + continue + } + if err := runCommand(command, outputer); err != nil { + //maybe? + return err + } + } + } + return nil +} diff --git a/linker.go b/linker.go index f5ddb82..bb7d8ca 100644 --- a/linker.go +++ b/linker.go @@ -31,6 +31,11 @@ func (l *Linker) Move(oldpath, newpath string) error { return err } + if dry { + l.outputer.OutVerbose(" would %s backup %s to %s", Green("→"), Brown(oldpath), Brown(newpath)) + return nil + } + err = l.os.MkdirAll(path.Dir(newpath), 0700) if err != nil { return err @@ -43,6 +48,9 @@ func (l *Linker) Move(oldpath, newpath string) error { // SetSymlink symlinks scrAbs to destAbs. func (l *Linker) SetSymlink(srcAbs string, destAbs string) error { + if dry { + return nil + } dir := path.Dir(destAbs) if err := l.os.MkdirAll(dir, 0700); err != nil { @@ -78,6 +86,11 @@ func (l *Linker) NeedSymlink(src, dest string) (bool, error) { // here dest is a wrong symlink + if dry { + l.outputer.OutInfo(" %s would delete wrong symlink %s", Green("✓"), Brown(dest)) + return true, nil + } + if err = l.os.Remove(dest); err != nil { return false, err } diff --git a/main.go b/main.go index 5f1b316..d256cb0 100644 --- a/main.go +++ b/main.go @@ -6,6 +6,7 @@ import ( "os" "path" "path/filepath" + "runtime" . "github.com/logrusorgru/aurora" ) @@ -15,7 +16,9 @@ const logFilepath = "${HOME}/.dotbro/dotbro.log" var debugLogger DebugLogger var ( - osfs = new(OSFS) + osfs = new(OSFS) + dry bool + currentOS string ) func main() { @@ -25,6 +28,9 @@ func main() { debugLogger.Write("Start.") + // Get current operating system + currentOS = runtime.GOOS + // Parse arguments args, err := ParseArguments(nil) @@ -33,12 +39,16 @@ func main() { exit(1) } + if args["--dry"].(bool) { + dry = true + } + debugLogger.Write("Arguments passed: %+v", args) switch { case args["--verbose"].(bool): outputer.Mode = OutputerModeVerbose - case args["--quiet"].(bool): + case args["--quiet"].(bool) && !dry: outputer.Mode = OutputerModeQuiet default: outputer.Mode = OutputerModeNormal @@ -87,6 +97,12 @@ func main() { outputer.OutInfo("\nCleaned!") exit(0) + case args["init"]: + if err = runInitCommands(config, outputer); err != nil { + outputer.OutError("%s", err) + exit(1) + } + fallthrough // after init, run installAction default: // Default action: install if err = installAction(config, &outputer); err != nil { @@ -351,6 +367,10 @@ func installDotfile(src, dest string, linker Linker, config *Configuration, srcD exit(1) } + if dry { + outputer.OutInfo(" %s would symlink %s to %s", Green("→"), Brown(src), Brown(dest)) + return + } outputer.OutInfo(" %s set symlink %s -> %s", Green("+"), Brown(src), Brown(dest)) } diff --git a/run_commands.go b/run_commands.go new file mode 100644 index 0000000..649e390 --- /dev/null +++ b/run_commands.go @@ -0,0 +1,34 @@ +// +build !windows + +package main + +import ( + "fmt" + "os" + "os/exec" +) + +var runCmd string + +func prepInit(outputer Outputer) error { + var err error + runCmd, err = exec.LookPath("bash") + if err != nil { + runCmd, err = exec.LookPath("sh") + if err != nil { + return fmt.Errorf("unable to find 'bash' or 'sh', cannot run init commands: %s", err) + } + outputer.OutWarn("'bash' missing, using 'sh'") + } + return nil +} + +func runCommand(command string, outputer Outputer) error { + cmd := exec.Command(runCmd, "-c", command) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stdout + if err := cmd.Run(); err != nil { + return err + } + return nil +}