diff --git a/CMDREF.md b/CMDREF.md index e228c044..508f2dea 100644 --- a/CMDREF.md +++ b/CMDREF.md @@ -1,3 +1,76 @@ +``` + .----------------. .----------------. .----------------. .----------------. +| .--------------. || .--------------. || .--------------. || .--------------. | +| | ____ ____ | || | ____ | || | _____ | || | _________ | | +| ||_ _| |_ _| | || | .' `. | || | |_ _| | || | | _ _ | | | +| | \ \ / / | || | / .--. \ | || | | | | || | |_/ | | \_| | | +| | \ \ / / | || | | | | | | || | | | _ | || | | | | | +| | \ ' / | || | \ `--' / | || | _| |__/ | | || | _| |_ | | +| | \_/ | || | `.____.' | || | |________| | || | |_____| | | +| | | || | | || | | || | | | +| '--------------' || '--------------' || '--------------' || '--------------' | + '----------------' '----------------' '----------------' '----------------' + +Usage + volt COMMAND ARGS + +Command + get [-l] [-u] [{repository} ...] + Install or upgrade given {repository} list, or add local {repository} list as plugins + + rm [-r] [-p] {repository} [{repository2} ...] + Remove vim plugin from ~/.vim/pack/volt/opt/ directory + + list [-f {text/template string}] + Vim plugin information extractor. + Unless -f flag was given, this command shows vim plugins of **current profile** (not all installed plugins) by default. + + enable {repository} [{repository2} ...] + This is shortcut of: + volt profile add -current {repository} [{repository2} ...] + + disable {repository} [{repository2} ...] + This is shortcut of: + volt profile rm -current {repository} [{repository2} ...] + + profile set {name} + Set profile name + + profile show {name} + Show profile info + + profile list + List all profiles + + profile new {name} + Create new profile + + profile destroy {name} + Delete profile + + profile rename {old} {new} + Rename profile {old} to {new} + + profile add {name} {repository} [{repository2} ...] + Add one or more repositories to profile + + profile rm {name} {repository} [{repository2} ...] + Remove one or more repositories to profile + + build [-full] + Build ~/.vim/pack/volt/ directory + + migrate {migration operation} + Perform miscellaneous migration operations. + See 'volt migrate -help' for all available operations + + self-upgrade [-check] + Upgrade to the latest volt command, or if -check was given, it only checks the newer version is available + + version + Show volt command version +``` + # volt build ``` @@ -137,7 +210,7 @@ Quick example Show repositories used by current profile: - $ volt list -f '{{ range .Profiles }}{{ if eq $.CurrentProfileName .Name }}{{ range .ReposPath }}{{ . }}{{ end }}{{ end }}{{ end }}' + $ volt list -f '{{ range .Profiles }}{{ if eq $.CurrentProfileName .Name }}{{ range .ReposPath }}{{ println . }}{{ end }}{{ end }}{{ end }}' Or (see "Additional property"): diff --git a/Makefile b/Makefile index 0cd1811e..0788d9de 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ NAME := volt SRC := $(shell find . -type d -name 'vendor' -prune -o -type f -name '*.go' -print) -VERSION := $(shell sed -n -E 's/var voltVersion = "([^"]+)"/\1/p' cmd/version.go) +VERSION := $(shell sed -n -E 's/var voltVersion = "([^"]+)"/\1/p' subcmd/version.go) RELEASE_LDFLAGS := -s -w -extldflags '-static' RELEASE_OS := linux windows darwin RELEASE_ARCH := amd64 386 @@ -43,7 +43,6 @@ release: $(BIN_DIR)/$(NAME) done update-doc: all - go run _scripts/update-readme.go README.md - go run _scripts/update-cmdref.go CMDREF.md + go run _scripts/update-cmdref.go >CMDREF.md .PHONY: all precompile install-dep dep-ensure test release update-doc diff --git a/README.md b/README.md index de7ea24f..e43552c3 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ ---- ``` -$ volt .----------------. .----------------. .----------------. .----------------. | .--------------. || .--------------. || .--------------. || .--------------. | | | ____ ____ | || | ____ | || | _____ | || | _________ | | @@ -16,65 +15,6 @@ $ volt | | | || | | || | | || | | | | '--------------' || '--------------' || '--------------' || '--------------' | '----------------' '----------------' '----------------' '----------------' - -Usage - volt COMMAND ARGS - -Command - get [-l] [-u] [{repository} ...] - Install or upgrade given {repository} list, or add local {repository} list as plugins - - rm [-r] [-p] {repository} [{repository2} ...] - Remove vim plugin from ~/.vim/pack/volt/opt/ directory - - list [-f {text/template string}] - Vim plugin information extractor. - Unless -f flag was given, this command shows vim plugins of **current profile** (not all installed plugins) by default. - - enable {repository} [{repository2} ...] - This is shortcut of: - volt profile add -current {repository} [{repository2} ...] - - disable {repository} [{repository2} ...] - This is shortcut of: - volt profile rm -current {repository} [{repository2} ...] - - profile set {name} - Set profile name - - profile show {name} - Show profile info - - profile list - List all profiles - - profile new {name} - Create new profile - - profile destroy {name} - Delete profile - - profile rename {old} {new} - Rename profile {old} to {new} - - profile add {name} {repository} [{repository2} ...] - Add one or more repositories to profile - - profile rm {name} {repository} [{repository2} ...] - Remove one or more repositories to profile - - build [-full] - Build ~/.vim/pack/volt/ directory - - migrate {migration operation} - Perform miscellaneous migration operations. - See 'volt migrate -help' for all available operations - - self-upgrade [-check] - Upgrade to the latest volt command, or if -check was given, it only checks the newer version is available - - version - Show volt command version ``` See [the command reference](https://github.com/vim-volt/volt/blob/master/CMDREF.md) for more details. @@ -82,8 +22,6 @@ See [the command reference](https://github.com/vim-volt/volt/blob/master/CMDREF. * [What is Volt](#what-is-volt) * [Install](#install) -* [Build Environment](#build-environment) -* [Config](#config) * [Self upgrade](#self-upgrade) * [Introduction](#introduction) * [VOLTPATH](#voltpath) @@ -92,6 +30,7 @@ See [the command reference](https://github.com/vim-volt/volt/blob/master/CMDREF. * [Uninstall plugins](#uninstall-plugins) * [How it works](#how-it-works) * [Syncing ~/.vim/pack/volt directory with $VOLTPATH](#syncing-vimpackvolt-directory-with-voltpath) +* [Config](#config) * [Features](#features) * [Easy setup](#easy-setup) * [Configuration per plugin ("Plugconf" feature)](#configuration-per-plugin-plugconf-feature) @@ -104,6 +43,7 @@ See [the command reference](https://github.com/vim-volt/volt/blob/master/CMDREF. ## What is Volt * Multi-platform CLI tool managing Vim plugin life +* Parallel vim plugin update * Based on Vim 8 [packages feature](http://vimhelp.appspot.com/repeat.txt.html#packages) * All plugins are installed under `~/.vim/pack/volt` directory * Zero overhead & optimizations @@ -114,56 +54,29 @@ See [the command reference](https://github.com/vim-volt/volt/blob/master/CMDREF. * This separates plugin configuration from vimrc, so you can easily disable/remove plugins in a second * [Profile feature](#switch-set-of-plugins-profile-feature) saves set of plugins, vimrc, and gvimrc * You can switch those combinations with one command + * For example, you can switch various Vim such as Web development mode, Essential plugins + vimrc only, or Vanilla Vim. ## Install -``` -$ go get github.com/vim-volt/volt -``` - -Or download binaries from [GitHub releases](https://github.com/vim-volt/volt/releases). - -## Build environment - -* Go 1.9 or higher - * If you are on WSL (Windows Subsystem Linux), note that you need **[the patch for os.RemoveAll()](https://go-review.googlesource.com/c/go/+/62970) ([#1](https://github.com/vim-volt/go-volt/issues/1))** +* **RECOMMENDED**: Download binaries from [GitHub releases](https://github.com/vim-volt/volt/releases) +* Or `go get github.com/vim-volt/volt` + * You need Go 1.9 or higher + * And if you are using Windows Subsystem Linux, you need to apply **[the patch for os.RemoveAll()](https://go-review.googlesource.com/c/go/+/62970) ! ([#1](https://github.com/vim-volt/go-volt/issues/1))** * But it's a hassle, you can just download linux-386/amd64 binaries from [GitHub releases](https://github.com/vim-volt/volt/releases) :) -## Config - -Config file: `$VOLTPATH/config.toml` - -```toml -[build] -# * "symlink" (default): "volt build" creates symlinks "~/.vim/pack/volt/opt/" referring to "$VOLTPATH/repos/" -# * "copy": "volt build" copies "$VOLTPATH/repos/" files to "~/.vim/pack/volt/opt/" -strategy = "symlink" - -[get] -# * true (default): "volt get" creates skeleton plugconf file at "$VOLTPATH/plugconf/.vim" -# * false: It does not creates skeleton plugconf file -create_skeleton_plugconf = true - -# * true (default): When "volt get" or "volt get -u" fail and "git" command is -# installed, it tries to execute "git clone" or "git pull" as a fallback -# * false: "volt get" or "volt get -u" won't try to execute fallback commands -fallback_git_cmd = true -``` +And there is bash completion script in [\_contrib](https://github.com/vim-volt/volt/blob/master/_contrib/completion/bash) directory (thanks @AvianY). ## Self upgrade +If you already have older version's `volt` command, you can use `volt self-upgrade` command. + ``` $ volt self-upgrade ``` will upgrade current running volt binary to the latest version if the [newer releases](https://github.com/vim-volt/volt/releases) published. -``` -$ volt self-upgrade -check -``` - -just checks if the newer releases published. -It also shows the release note of the latest version. +Or also you can just checks if the newer releases published by running `volt self-upgrade -check`. ## Introduction @@ -245,6 +158,31 @@ But if you edit `$VOLTPATH/rc//vimrc.vim` or `$VOLTPATH/rc//gv `volt build` uses cache for the next running. Normally `volt build` synchronizes correctly, but if you met the bug, try `volt build -full` (or please [file an issue](https://github.com/vim-volt/volt/issues/new) as possible :) to ignore the previous cache. +## Config + +Config file: `$VOLTPATH/config.toml` + +```toml +[alias] +# You can use `volt update` in addition to `volt get -u` +update = ["get", "-u"] + +[build] +# * "symlink" (default): "volt build" creates symlinks "~/.vim/pack/volt/opt/" referring to "$VOLTPATH/repos/" +# * "copy": "volt build" copies "$VOLTPATH/repos/" files to "~/.vim/pack/volt/opt/" +strategy = "symlink" + +[get] +# * true (default): "volt get" creates skeleton plugconf file at "$VOLTPATH/plugconf/.vim" +# * false: It does not creates skeleton plugconf file +create_skeleton_plugconf = true + +# * true (default): When "volt get" or "volt get -u" fail and "git" command is +# installed, it tries to execute "git clone" or "git pull" as a fallback +# * false: "volt get" or "volt get -u" won't try to execute fallback commands +fallback_git_cmd = true +``` + ## Features ### Easy setup @@ -323,7 +261,7 @@ endfunction " " This function must contain 'return ""' code. " (the argument of :return must be string literal) -function! s:depends() +function! s:loaded_on() " this is the default value, you don't have to write this return 'start' endfunction @@ -454,7 +392,7 @@ Because if you run `volt get localhost/{user}/{name}` accidentally you only get So it is guaranteed that you won't install a unwanted plugin :) In other words, this means you can also manage your `~/.vim/*` files as a vim plugin. -Off cource you can disable/enable it by `volt disable ` and `volt enable `. +Off cource you can disable/enable it by `volt disable ` and `volt enable `. ``` Move files/directories to vimdir diff --git a/_contrib/completion/bash b/_contrib/completion/bash new file mode 100644 index 00000000..e8d60763 --- /dev/null +++ b/_contrib/completion/bash @@ -0,0 +1,90 @@ +get_profile() { + volt list -f '{{ .CurrentProfileName }}' +} + +get_profiles() { + volt profile list | sed 's/[* ] //' +} + +get_plugs() { + local profile=$1 + if [ -z $(comm -13 <(get_profiles | sort) <(echo $profile)) ] ; then + case "$2" in + all) all_plugs ;; + this) this_plug "$profile" ;; + not) comm -23 <(all_plugs) <(this_plug "$profile") ;; + *) echo ;; + esac + fi +} + +all_plugs() { + volt list -f "{{ range .Repos }}{{ println .Path }}{{ end }}" | sed -E 's@^(www\.)?github\.com/@@' | sort -u +} + +this_plug() { + volt list -f "{{ range .Profiles }}{{ if eq \"$1\" .Name }}{{ range .ReposPath }}{{ println . }}{{ end }}{{ end }}{{ end }}" | sed -E 's@^(www\.)?github\.com/@@' | sort -u +} + +CMDS="get rm list enable disable profile build migrate self-upgrade version" +PROFILE_CMDS="set show list new destroy rename add rm" +MIGRATE_CMDS="lockjson plugconf/config-func" + +_volt() { + COMPREPLY=() + local cur="${COMP_WORDS[COMP_CWORD]}" + local last="${COMP_WORDS[COMP_CWORD - 1]}" + local first="${COMP_WORDS[1]}" + local second="${COMP_WORDS[2]}" + local third="${COMP_WORDS[3]}" + + if [[ "${first}" == "profile" && "${second}" =~ ^(set|show|destroy|rename|add|rm)$ && "${last}" =~ ^(set|show|destroy|rename|add|rm)$ ]] ; then + local profiles=$(get_profiles) + COMPREPLY=( $(compgen -W "${profiles}" -- ${cur}) ) + + elif [[ "${first}" == "profile" && "${second}" =~ ^(add|rm)$ && "${third}" ]] ; then + local profile=$third + case "$second" in + add) plugs=$(get_plugs "${profile}" "not") ;; + rm) plugs=$(get_plugs "${profile}" "this") ;; + esac + COMPREPLY=( $(compgen -W "${plugs}" -- ${cur}) ) + + elif [[ "${first}" == "profile" && "${last}" == "profile" ]] ; then + COMPREPLY=( $(compgen -W "${PROFILE_CMDS}" -- ${cur}) ) + + elif [[ "${first}" =~ ^(rm|disable)$ ]] ; then + local profile=$(get_profile) + plugs=$(get_plugs "$profile" "this") + COMPREPLY=( $(compgen -W "${plugs}" -- ${cur}) ) + + elif [[ "${first}" == "get" ]] ; then + if [[ "${second}" == "-l" || "${third}" == "-l" ]] ; then : + + elif [[ "${second}" == "-u" ]] ; then + local profile=$(get_profile) + plugs=$(get_plugs "$profile" "all") + COMPREPLY=( $(compgen -W "${plugs}" -- ${cur}) ) + else + local profile=$(get_profile) + plugs=$(get_plugs "$profile" "not") + COMPREPLY=( $(compgen -W "${plugs}" -- ${cur}) ) + fi + + elif [[ "${first}" == "enable" ]] ; then + local profile=$(get_profile) + plugs=$(get_plugs "$profile" "not") + COMPREPLY=( $(compgen -W "${plugs}" -- ${cur}) ) + + elif [[ "${first}" == "migrate" && "${last}" == "migrate" ]] ; then + COMPREPLY=( $(compgen -W "${MIGRATE_CMDS}" -- ${cur}) ) + + elif [[ "${first}" == "build" && "${last}" == "build" ]] ; then + COMPREPLY=( $(compgen -W "-full" -- ${cur}) ) + + elif [[ "${second}" == "" && "${first}" != "${last}" ]] ; then + COMPREPLY=( $(compgen -W "${CMDS}" -- ${cur}) ) + fi + return 0 +} +complete -F _volt volt diff --git a/_scripts/update-cmdref.go b/_scripts/update-cmdref.go index a4651fc8..d6aa1a8a 100644 --- a/_scripts/update-cmdref.go +++ b/_scripts/update-cmdref.go @@ -1,7 +1,6 @@ package main import ( - "bufio" "errors" "fmt" "os" @@ -16,32 +15,32 @@ func main() { // Update CMDREF.md "volt help" output in the first code block (lines surrounded by ```) func doMain() int { - if len(os.Args) <= 1 { - fmt.Fprintln(os.Stderr, "[WARN] Specify CMDREF.md path") - return 1 - } - file, err := os.Create(os.Args[1]) + header, err := getVoltHelpOutput() if err != nil { fmt.Fprintf(os.Stderr, "[WARN] %s\n", err.Error()) - return 2 + return 1 } - defer file.Close() - bw := bufio.NewWriter(file) - out, err := getCmdRefContent() + cmdref, err := getCmdRefContent() if err != nil { fmt.Fprintf(os.Stderr, "[WARN] %s\n", err.Error()) - return 3 + return 2 } - bw.WriteString(out) - if err := bw.Flush(); err != nil { - fmt.Fprintf(os.Stderr, "[WARN] %s\n", err.Error()) - return 4 - } + fmt.Printf("%s\n\n%s", header, cmdref) + return 0 } +func getVoltHelpOutput() (string, error) { + out, err := testutil.RunVolt("help") + if err != nil { + return "", err + } + content := strings.TrimRight(string(out), " \t\r\n") + return fmt.Sprintf("```\n%s\n```", content), nil +} + func getCmdRefContent() (string, error) { cmdList, err := testutil.GetCmdList() if err != nil { diff --git a/_scripts/update-readme.go b/_scripts/update-readme.go deleted file mode 100644 index 93f2050e..00000000 --- a/_scripts/update-readme.go +++ /dev/null @@ -1,111 +0,0 @@ -package main - -import ( - "bufio" - "bytes" - "fmt" - "io" - "os" - "strings" - - "github.com/vim-volt/volt/internal/testutil" -) - -func main() { - os.Exit(doMain()) -} - -// Embeds "volt help" output in the first code block (lines surrounded by ```) -// of README.md -func doMain() int { - if len(os.Args) <= 1 { - fmt.Fprintln(os.Stderr, "[WARN] Specify README.md path") - return 1 - } - readme := os.Args[1] - fileinfo, err := os.Stat(readme) - if err != nil { - fmt.Fprintf(os.Stderr, "[WARN] %s\n", err.Error()) - return 2 - } - file, err := os.OpenFile(os.Args[1], os.O_RDWR, fileinfo.Mode()) - if err != nil { - fmt.Fprintf(os.Stderr, "[WARN] %s\n", err.Error()) - return 3 - } - defer file.Close() - - // Read content from file - var content bytes.Buffer - if _, err := io.Copy(&content, file); err != nil { - fmt.Fprintf(os.Stderr, "[WARN] %s\n", err.Error()) - return 4 - } - // Find the first code block ("volt help" output) - lines := strings.Split(content.String(), "\n") - start, end := findTopCodeBlockRange(lines) - if start < 0 { - fmt.Fprintln(os.Stderr, "[WARN] Cannot find code block") - return 5 - } - - // seek for writing to file - if _, err := file.Seek(0, 0); err != nil { - fmt.Fprintf(os.Stderr, "[WARN] %s\n", err.Error()) - return 6 - } - bw := bufio.NewWriter(file) - for _, line := range lines[:start] { - bw.WriteString(line + "\n") - } - out, err := getVoltHelpOutput() - if err != nil { - fmt.Fprintf(os.Stderr, "[WARN] %s\n", err.Error()) - return 7 - } - bw.WriteString(out + "\n") - for _, line := range lines[end:] { - bw.WriteString(line + "\n") - } - - if err := bw.Flush(); err != nil { - fmt.Fprintln(os.Stderr, "[WARN] Cannot find code block") - return 8 - } - curpos, err := file.Seek(0, 1) - if err != nil { - fmt.Fprintf(os.Stderr, "[WARN] %s\n", err.Error()) - return 9 - } - // Specify curpos-1 to delete the last newline - if err := file.Truncate(curpos - 1); err != nil { - fmt.Fprintf(os.Stderr, "[WARN] %s\n", err.Error()) - return 10 - } - return 0 -} - -// start = The first line number **inside** code block -// end = The end of code block line (```) line number -func findTopCodeBlockRange(lines []string) (int, int) { - start, end := -1, -1 - for i := range lines { - if lines[i] == "```" { - if start == -1 { - start = i + 1 - } else { - end = i - break - } - } - } - return start, end -} - -func getVoltHelpOutput() (string, error) { - out, err := testutil.RunVolt("help") - if err != nil { - return "", err - } - return "$ volt\n" + strings.TrimRight(string(out), " \t\r\n"), nil -} diff --git a/cmd/cmd.go b/cmd/cmd.go deleted file mode 100644 index 049928e5..00000000 --- a/cmd/cmd.go +++ /dev/null @@ -1,57 +0,0 @@ -package cmd - -import ( - "errors" - "flag" - "os/user" - "runtime" - - "github.com/vim-volt/volt/logger" -) - -var cmdMap = make(map[string]Cmd) - -// Cmd represents volt's subcommand interface. -// All subcommands must implement this. -type Cmd interface { - ProhibitRootExecution(args []string) bool - Run(args []string) int - FlagSet() *flag.FlagSet -} - -// Run is invoked by main(), each argument means 'volt {subcmd} {args}'. -func Run(subCmd string, args []string) int { - self, exists := cmdMap[subCmd] - if !exists { - logger.Error("Unknown command '" + subCmd + "'") - return 3 - } - if self.ProhibitRootExecution(args) { - err := detectPriviledgedUser() - if err != nil { - logger.Error(err.Error()) - return 4 - } - } - return self.Run(args) -} - -// On Windows, this function always returns nil. -// Because if even administrator user creates a file, the file can be -// overwritten by normal user. -// On Linux, if current user's uid == 0, returns non-nil error. -func detectPriviledgedUser() error { - if runtime.GOOS == "windows" { - return nil - } - u, err := user.Current() - if err != nil { - return errors.New("Cannot get current user: " + err.Error()) - } - if u.Uid == "0" { - return errors.New( - "Cannot run this sub command with root priviledge. " + - "Please run as normal user") - } - return nil -} diff --git a/config/config.go b/config/config.go index 20cec5b8..fc8feedf 100644 --- a/config/config.go +++ b/config/config.go @@ -9,16 +9,17 @@ import ( // Config is marshallable content of config.toml type Config struct { - Build configBuild `toml:"build"` - Get configGet `toml:"get"` + Alias map[string][]string `toml:"alias"` + Build configBuild `toml:"build"` + Get configGet `toml:"get"` } -// configBuild is a config of 'volt build'. +// configBuild is a config for 'volt build'. type configBuild struct { Strategy string `toml:"strategy"` } -// configGet is a config of 'volt get'. +// configGet is a config for 'volt get'. type configGet struct { CreateSkeletonPlugconf *bool `toml:"create_skeleton_plugconf"` FallbackGitCmd *bool `toml:"fallback_git_cmd"` @@ -33,13 +34,14 @@ const ( func initialConfigTOML() *Config { trueValue := true + falseValue := false return &Config{ Build: configBuild{ Strategy: SymlinkBuilder, }, Get: configGet{ CreateSkeletonPlugconf: &trueValue, - FallbackGitCmd: &trueValue, + FallbackGitCmd: &falseValue, }, } } diff --git a/main.go b/main.go index 1678758f..70334e02 100644 --- a/main.go +++ b/main.go @@ -5,20 +5,14 @@ package main import ( "os" - "github.com/vim-volt/volt/cmd" "github.com/vim-volt/volt/logger" + "github.com/vim-volt/volt/subcmd" ) func main() { - os.Exit(doMain()) -} - -func doMain() int { - if os.Getenv("VOLT_DEBUG") != "" { - logger.SetLevel(logger.DebugLevel) - } - if len(os.Args) <= 1 { - os.Args = append(os.Args, "help") + err := subcmd.Run(os.Args, subcmd.DefaultRunner) + if err != nil { + logger.Error(err.Msg) + os.Exit(err.Code) } - return cmd.Run(os.Args[1], os.Args[2:]) } diff --git a/plugconf/plugconf.go b/plugconf/plugconf.go index 03cd026a..5966474d 100644 --- a/plugconf/plugconf.go +++ b/plugconf/plugconf.go @@ -76,6 +76,9 @@ func (pi *ParsedInfo) GeneratePlugconf() ([]byte, error) { // Merge result and return it var buf bytes.Buffer + // modeline + buf.WriteString("\" vim:et:sw=2:ts=2\n\n") + // s:on_load_pre() if pi.onLoadPreFunc != "" { buf.WriteString(pi.onLoadPreFunc) diff --git a/cmd/build.go b/subcmd/build.go similarity index 86% rename from cmd/build.go rename to subcmd/build.go index e4ae71b5..0b871d60 100644 --- a/cmd/build.go +++ b/subcmd/build.go @@ -1,12 +1,12 @@ -package cmd +package subcmd import ( "flag" "fmt" "os" - "github.com/vim-volt/volt/cmd/builder" "github.com/vim-volt/volt/logger" + "github.com/vim-volt/volt/subcmd/builder" "github.com/vim-volt/volt/transaction" ) @@ -53,27 +53,27 @@ Description return fs } -func (cmd *buildCmd) Run(args []string) int { +func (cmd *buildCmd) Run(args []string) *Error { // Parse args fs := cmd.FlagSet() fs.Parse(args) if cmd.helped { - return 0 + return nil } // Begin transaction err := transaction.Create() if err != nil { - logger.Error("Failed to begin transaction:", err.Error()) - return 11 + logger.Error() + return &Error{Code: 11, Msg: "Failed to begin transaction: " + err.Error()} } defer transaction.Remove() err = builder.Build(cmd.full) if err != nil { - logger.Error("Failed to build:", err.Error()) - return 12 + logger.Error() + return &Error{Code: 12, Msg: "Failed to build: " + err.Error()} } - return 0 + return nil } diff --git a/cmd/build_test.go b/subcmd/build_test.go similarity index 99% rename from cmd/build_test.go rename to subcmd/build_test.go index e09bd6b7..77b95172 100644 --- a/cmd/build_test.go +++ b/subcmd/build_test.go @@ -1,4 +1,4 @@ -package cmd +package subcmd import ( "bytes" @@ -11,12 +11,12 @@ import ( "time" "github.com/haya14busa/go-vimlparser" - "github.com/vim-volt/volt/cmd/builder" "github.com/vim-volt/volt/config" "github.com/vim-volt/volt/fileutil" "github.com/vim-volt/volt/internal/testutil" "github.com/vim-volt/volt/lockjson" "github.com/vim-volt/volt/pathutil" + "github.com/vim-volt/volt/subcmd/builder" ) // Checks: diff --git a/cmd/builder/base.go b/subcmd/builder/base.go similarity index 92% rename from cmd/builder/base.go rename to subcmd/builder/base.go index 64d0686a..d0d2b87b 100644 --- a/cmd/builder/base.go +++ b/subcmd/builder/base.go @@ -10,13 +10,14 @@ import ( "strings" "github.com/hashicorp/go-multierror" - "github.com/vim-volt/volt/cmd/buildinfo" "github.com/vim-volt/volt/fileutil" "github.com/vim-volt/volt/lockjson" "github.com/vim-volt/volt/logger" "github.com/vim-volt/volt/pathutil" + "github.com/vim-volt/volt/subcmd/buildinfo" ) +// BaseBuilder is a base struct which all builders must implement type BaseBuilder struct{} func (builder *BaseBuilder) installVimrcAndGvimrc(profileName, vimrcPath, gvimrcPath string) error { @@ -78,7 +79,7 @@ func (builder *BaseBuilder) installRCFile(profileName, srcRCFileName, dst string if !pathutil.Exists(src) { return nil } - return errors.New("'" + dst + "' does not have magic comment") + return fmt.Errorf("'%s' is not an auto-generated file. please move to '%s' and re-run 'volt build'", dst, pathutil.RCDir(profileName)) } } @@ -99,7 +100,7 @@ func (builder *BaseBuilder) installRCFile(profileName, srcRCFileName, dst string const magicComment = "\" NOTE: this file was generated by volt. please modify original file.\n" const magicCommentNext = "\" Original file: %s\n\n" -// Return error if the magic comment does not exist +// HasMagicComment returns true if the magic comment exists func (*BaseBuilder) HasMagicComment(dst string) bool { r, err := os.Open(dst) if err != nil { diff --git a/cmd/builder/builder.go b/subcmd/builder/builder.go similarity index 98% rename from cmd/builder/builder.go rename to subcmd/builder/builder.go index 562fad27..3730b783 100644 --- a/cmd/builder/builder.go +++ b/subcmd/builder/builder.go @@ -4,10 +4,10 @@ import ( "errors" "os" - "github.com/vim-volt/volt/cmd/buildinfo" "github.com/vim-volt/volt/config" "github.com/vim-volt/volt/logger" "github.com/vim-volt/volt/pathutil" + "github.com/vim-volt/volt/subcmd/buildinfo" ) // Builder creates/updates ~/.vim/pack/volt directory diff --git a/cmd/builder/copy.go b/subcmd/builder/copy.go similarity index 99% rename from cmd/builder/copy.go rename to subcmd/builder/copy.go index 07c49d1c..b579f62e 100644 --- a/cmd/builder/copy.go +++ b/subcmd/builder/copy.go @@ -9,13 +9,13 @@ import ( "time" "github.com/hashicorp/go-multierror" - "github.com/vim-volt/volt/cmd/buildinfo" "github.com/vim-volt/volt/fileutil" "github.com/vim-volt/volt/gitutil" "github.com/vim-volt/volt/lockjson" "github.com/vim-volt/volt/logger" "github.com/vim-volt/volt/pathutil" "github.com/vim-volt/volt/plugconf" + "github.com/vim-volt/volt/subcmd/buildinfo" "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/plumbing/object" diff --git a/cmd/builder/symlink.go b/subcmd/builder/symlink.go similarity index 99% rename from cmd/builder/symlink.go rename to subcmd/builder/symlink.go index 83285bd2..eb94e5e5 100644 --- a/cmd/builder/symlink.go +++ b/subcmd/builder/symlink.go @@ -11,12 +11,12 @@ import ( "gopkg.in/src-d/go-git.v4" - "github.com/vim-volt/volt/cmd/buildinfo" "github.com/vim-volt/volt/gitutil" "github.com/vim-volt/volt/lockjson" "github.com/vim-volt/volt/logger" "github.com/vim-volt/volt/pathutil" "github.com/vim-volt/volt/plugconf" + "github.com/vim-volt/volt/subcmd/buildinfo" ) type symlinkBuilder struct { diff --git a/cmd/buildinfo/buildinfo.go b/subcmd/buildinfo/buildinfo.go similarity index 100% rename from cmd/buildinfo/buildinfo.go rename to subcmd/buildinfo/buildinfo.go diff --git a/subcmd/cmd.go b/subcmd/cmd.go new file mode 100644 index 00000000..9e1a7983 --- /dev/null +++ b/subcmd/cmd.go @@ -0,0 +1,108 @@ +package subcmd + +import ( + "errors" + "flag" + "os" + "os/user" + "runtime" + + "github.com/vim-volt/volt/config" + "github.com/vim-volt/volt/logger" +) + +var cmdMap = make(map[string]Cmd) + +// Cmd represents volt's subcommand interface. +// All subcommands must implement this. +type Cmd interface { + ProhibitRootExecution(args []string) bool + Run(args []string) *Error + FlagSet() *flag.FlagSet +} + +// RunnerFunc invokes c with args. +// On unit testing, a mock function was given. +type RunnerFunc func(c Cmd, args []string) *Error + +// Error is a command error. +// It also has a exit code. +type Error struct { + Code int + Msg string +} + +func (e *Error) Error() string { + return e.Msg +} + +// DefaultRunner simply runs command with args +func DefaultRunner(c Cmd, args []string) *Error { + return c.Run(args) +} + +// Run is invoked by main(), each argument means 'volt {subcmd} {args}'. +func Run(args []string, cont RunnerFunc) *Error { + if os.Getenv("VOLT_DEBUG") != "" { + logger.SetLevel(logger.DebugLevel) + } + + if len(args) <= 1 { + args = append(args, "help") + } + subCmd := args[1] + args = args[2:] + + // Expand subcommand alias + subCmd, args, err := expandAlias(subCmd, args) + if err != nil { + return &Error{Code: 1, Msg: err.Error()} + } + + c, exists := cmdMap[subCmd] + if !exists { + return &Error{Code: 3, Msg: "Unknown command '" + subCmd + "'"} + } + + // Disallow executing the commands which may modify files in root priviledge + if c.ProhibitRootExecution(args) { + err := detectPriviledgedUser() + if err != nil { + return &Error{Code: 4, Msg: err.Error()} + } + } + + return cont(c, args) +} + +func expandAlias(subCmd string, args []string) (string, []string, error) { + cfg, err := config.Read() + if err != nil { + return "", nil, errors.New("could not read config.toml: " + err.Error()) + } + if newArgs, exists := cfg.Alias[subCmd]; exists && len(newArgs) > 0 { + subCmd = newArgs[0] + args = append(newArgs[1:], args...) + } + return subCmd, args, nil +} + +// On Windows, this function always returns nil. +// Because if even administrator user creates a file, the file can be +// overwritten by normal user. +// On Linux, if current user's uid == 0, returns non-nil error. +func detectPriviledgedUser() error { + if runtime.GOOS == "windows" { + return nil + } + u, err := user.Current() + if err != nil { + return errors.New("Cannot get current user: " + err.Error()) + } + if u.Uid == "0" { + return errors.New( + "Cannot run this sub command with root priviledge. " + + "Please run as normal user") + } + return nil +} diff --git a/cmd/disable.go b/subcmd/disable.go similarity index 87% rename from cmd/disable.go rename to subcmd/disable.go index 3b6eaa27..c3177243 100644 --- a/cmd/disable.go +++ b/subcmd/disable.go @@ -1,4 +1,4 @@ -package cmd +package subcmd import ( "errors" @@ -6,7 +6,6 @@ import ( "fmt" "os" - "github.com/vim-volt/volt/logger" "github.com/vim-volt/volt/pathutil" ) @@ -42,14 +41,13 @@ Description return fs } -func (cmd *disableCmd) Run(args []string) int { +func (cmd *disableCmd) Run(args []string) *Error { reposPathList, err := cmd.parseArgs(args) if err == ErrShowedHelp { - return 0 + return nil } if err != nil { - logger.Error("Failed to parse args: " + err.Error()) - return 10 + return &Error{Code: 10, Msg: "Failed to parse args: " + err.Error()} } profCmd := profileCmd{} @@ -58,11 +56,10 @@ func (cmd *disableCmd) Run(args []string) int { reposPathList.Strings()..., )) if err != nil { - logger.Error(err.Error()) - return 11 + return &Error{Code: 11, Msg: err.Error()} } - return 0 + return nil } func (cmd *disableCmd) parseArgs(args []string) (pathutil.ReposPathList, error) { diff --git a/cmd/enable.go b/subcmd/enable.go similarity index 87% rename from cmd/enable.go rename to subcmd/enable.go index 3ae8b2b9..e51c8186 100644 --- a/cmd/enable.go +++ b/subcmd/enable.go @@ -1,4 +1,4 @@ -package cmd +package subcmd import ( "errors" @@ -6,7 +6,6 @@ import ( "fmt" "os" - "github.com/vim-volt/volt/logger" "github.com/vim-volt/volt/pathutil" ) @@ -42,14 +41,13 @@ Description return fs } -func (cmd *enableCmd) Run(args []string) int { +func (cmd *enableCmd) Run(args []string) *Error { reposPathList, err := cmd.parseArgs(args) if err == ErrShowedHelp { - return 0 + return nil } if err != nil { - logger.Error("Failed to parse args: " + err.Error()) - return 10 + return &Error{Code: 10, Msg: "Failed to parse args: " + err.Error()} } profCmd := profileCmd{} @@ -58,11 +56,10 @@ func (cmd *enableCmd) Run(args []string) int { reposPathList.Strings()..., )) if err != nil { - logger.Error(err.Error()) - return 11 + return &Error{Code: 11, Msg: err.Error()} } - return 0 + return nil } func (cmd *enableCmd) parseArgs(args []string) (pathutil.ReposPathList, error) { diff --git a/cmd/get.go b/subcmd/get.go similarity index 96% rename from cmd/get.go rename to subcmd/get.go index c02609d6..b20796f7 100644 --- a/cmd/get.go +++ b/subcmd/get.go @@ -1,4 +1,4 @@ -package cmd +package subcmd import ( "errors" @@ -14,7 +14,6 @@ import ( "gopkg.in/src-d/go-git.v4" - "github.com/vim-volt/volt/cmd/builder" "github.com/vim-volt/volt/config" "github.com/vim-volt/volt/fileutil" "github.com/vim-volt/volt/gitutil" @@ -22,6 +21,7 @@ import ( "github.com/vim-volt/volt/logger" "github.com/vim-volt/volt/pathutil" "github.com/vim-volt/volt/plugconf" + "github.com/vim-volt/volt/subcmd/builder" "github.com/vim-volt/volt/transaction" multierror "github.com/hashicorp/go-multierror" @@ -115,41 +115,36 @@ Options`) return fs } -func (cmd *getCmd) Run(args []string) int { +func (cmd *getCmd) Run(args []string) *Error { // Parse args args, err := cmd.parseArgs(args) if err == ErrShowedHelp { - return 0 + return nil } if err != nil { - logger.Error("Failed to parse args: " + err.Error()) - return 10 + return &Error{Code: 10, Msg: "Failed to parse args: " + err.Error()} } // Read lock.json lockJSON, err := lockjson.Read() if err != nil { - logger.Error("Could not read lock.json: " + err.Error()) - return 11 + return &Error{Code: 11, Msg: "Could not read lock.json: " + err.Error()} } reposPathList, err := cmd.getReposPathList(args, lockJSON) if err != nil { - logger.Error("Could not get repos list: " + err.Error()) - return 12 + return &Error{Code: 12, Msg: "Could not get repos list: " + err.Error()} } if len(reposPathList) == 0 { - logger.Error("No repositories are specified") - return 13 + return &Error{Code: 13, Msg: "No repositories are specified"} } err = cmd.doGet(reposPathList, lockJSON) if err != nil { - logger.Error(err.Error()) - return 20 + return &Error{Code: 20, Msg: err.Error()} } - return 0 + return nil } func (cmd *getCmd) parseArgs(args []string) ([]string, error) { @@ -638,8 +633,11 @@ func (cmd *getCmd) gitPull(r *git.Repository, workDir string, remote string, cfg return err } err = wt.Pull(&git.PullOptions{ - RemoteName: remote, - RecurseSubmodules: 10, + RemoteName: remote, + // TODO: Temporarily recursive clone is disabled, because go-git does + // not support relative submodule url in .gitmodules and it causes an + // error + RecurseSubmodules: 0, }) if err == nil || err == git.NoErrAlreadyUpToDate { return err diff --git a/cmd/get_test.go b/subcmd/get_test.go similarity index 99% rename from cmd/get_test.go rename to subcmd/get_test.go index 9b605bc9..a2ee3224 100644 --- a/cmd/get_test.go +++ b/subcmd/get_test.go @@ -1,4 +1,4 @@ -package cmd +package subcmd import ( "bytes" diff --git a/cmd/help.go b/subcmd/help.go similarity index 93% rename from cmd/help.go rename to subcmd/help.go index 90ad5e35..49bf679a 100644 --- a/cmd/help.go +++ b/subcmd/help.go @@ -1,12 +1,10 @@ -package cmd +package subcmd import ( "errors" "flag" "fmt" "os" - - "github.com/vim-volt/volt/logger" ) // ErrShowedHelp is used in parsing argument function of subcommand when the @@ -101,22 +99,20 @@ Command return fs } -func (cmd *helpCmd) Run(args []string) int { +func (cmd *helpCmd) Run(args []string) *Error { if len(args) == 0 { cmd.FlagSet().Usage() - return 0 + return nil } if args[0] == "help" { // "volt help help" - fmt.Println("E478: Don't panic!") - return 0 + return &Error{Code: 47, Msg: "E478: Don't panic!"} } fs, exists := cmdMap[args[0]] if !exists { - logger.Errorf("Unknown command '%s'", args[0]) - return 1 + return &Error{Code: 1, Msg: fmt.Sprintf("Unknown command '%s'", args[0])} } args = append([]string{"-help"}, args[1:]...) fs.Run(args) - return 0 + return nil } diff --git a/cmd/help_test.go b/subcmd/help_test.go similarity index 92% rename from cmd/help_test.go rename to subcmd/help_test.go index 0b52e131..86a5b9af 100644 --- a/cmd/help_test.go +++ b/subcmd/help_test.go @@ -1,6 +1,7 @@ -package cmd +package subcmd import ( + "strings" "testing" "github.com/vim-volt/volt/internal/testutil" @@ -53,8 +54,8 @@ func TestVoltHelpE478(t *testing.T) { // =============== run =============== // out, err := testutil.RunVolt("help", "help") - testutil.SuccessExit(t, out, err) - if string(out) != "E478: Don't panic!\n" { + testutil.FailExit(t, out, err) + if !strings.Contains(string(out), "E478: Don't panic!") { t.Error("'volt help help' did not show E478 error: " + string(out)) } } diff --git a/cmd/list.go b/subcmd/list.go similarity index 94% rename from cmd/list.go rename to subcmd/list.go index e8aa4146..f3578547 100644 --- a/cmd/list.go +++ b/subcmd/list.go @@ -1,4 +1,4 @@ -package cmd +package subcmd import ( "encoding/json" @@ -9,7 +9,6 @@ import ( "text/template" "github.com/vim-volt/volt/lockjson" - "github.com/vim-volt/volt/logger" ) func init() { @@ -40,7 +39,7 @@ Quick example Show repositories used by current profile: - $ volt list -f '{{ range .Profiles }}{{ if eq $.CurrentProfileName .Name }}{{ range .ReposPath }}{{ . }}{{ end }}{{ end }}{{ end }}' + $ volt list -f '{{ range .Profiles }}{{ if eq $.CurrentProfileName .Name }}{{ range .ReposPath }}{{ println . }}{{ end }}{{ end }}{{ end }}' Or (see "Additional property"): @@ -126,17 +125,16 @@ repos path: ` } -func (cmd *listCmd) Run(args []string) int { +func (cmd *listCmd) Run(args []string) *Error { fs := cmd.FlagSet() fs.Parse(args) if cmd.helped { - return 0 + return nil } if err := cmd.list(cmd.format); err != nil { - logger.Error("Failed to render template:", err.Error()) - return 10 + return &Error{Code: 10, Msg: "Failed to render template: " + err.Error()} } - return 0 + return nil } func (cmd *listCmd) list(format string) error { diff --git a/cmd/list_test.go b/subcmd/list_test.go similarity index 99% rename from cmd/list_test.go rename to subcmd/list_test.go index 9e9a4b37..0f2d0f03 100644 --- a/cmd/list_test.go +++ b/subcmd/list_test.go @@ -1,4 +1,4 @@ -package cmd +package subcmd import ( "strconv" diff --git a/cmd/migrate.go b/subcmd/migrate.go similarity index 86% rename from cmd/migrate.go rename to subcmd/migrate.go index cec816d9..0fe90a2c 100644 --- a/cmd/migrate.go +++ b/subcmd/migrate.go @@ -1,4 +1,4 @@ -package cmd +package subcmd import ( "errors" @@ -6,8 +6,8 @@ import ( "fmt" "os" - "github.com/vim-volt/volt/cmd/migrate" "github.com/vim-volt/volt/logger" + "github.com/vim-volt/volt/subcmd/migrate" ) func init() { @@ -55,23 +55,21 @@ Available operations`) return fs } -func (cmd *migrateCmd) Run(args []string) int { +func (cmd *migrateCmd) Run(args []string) *Error { op, err := cmd.parseArgs(args) if err == ErrShowedHelp { - return 0 + return nil } if err != nil { - logger.Error("Failed to parse args: " + err.Error()) - return 10 + return &Error{Code: 10, Msg: "Failed to parse args: " + err.Error()} } if err := op.Migrate(); err != nil { - logger.Error("Failed to migrate: " + err.Error()) - return 11 + return &Error{Code: 11, Msg: "Failed to migrate: " + err.Error()} } logger.Infof("'%s' was successfully migrated!", op.Name()) - return 0 + return nil } func (cmd *migrateCmd) parseArgs(args []string) (migrate.Migrater, error) { diff --git a/cmd/migrate/lockjson.go b/subcmd/migrate/lockjson.go similarity index 100% rename from cmd/migrate/lockjson.go rename to subcmd/migrate/lockjson.go diff --git a/cmd/migrate/migrater.go b/subcmd/migrate/migrater.go similarity index 100% rename from cmd/migrate/migrater.go rename to subcmd/migrate/migrater.go diff --git a/cmd/migrate/plugconf-config-func.go b/subcmd/migrate/plugconf-config-func.go similarity index 98% rename from cmd/migrate/plugconf-config-func.go rename to subcmd/migrate/plugconf-config-func.go index ddf27b99..6033c783 100644 --- a/cmd/migrate/plugconf-config-func.go +++ b/subcmd/migrate/plugconf-config-func.go @@ -7,11 +7,11 @@ import ( "path/filepath" "strings" - "github.com/vim-volt/volt/cmd/builder" "github.com/vim-volt/volt/lockjson" "github.com/vim-volt/volt/logger" "github.com/vim-volt/volt/pathutil" "github.com/vim-volt/volt/plugconf" + "github.com/vim-volt/volt/subcmd/builder" "github.com/vim-volt/volt/transaction" ) diff --git a/cmd/profile.go b/subcmd/profile.go similarity index 97% rename from cmd/profile.go rename to subcmd/profile.go index 8020406e..6fb4a6c5 100644 --- a/cmd/profile.go +++ b/subcmd/profile.go @@ -1,4 +1,4 @@ -package cmd +package subcmd import ( "errors" @@ -7,10 +7,10 @@ import ( "os" "github.com/hashicorp/go-multierror" - "github.com/vim-volt/volt/cmd/builder" "github.com/vim-volt/volt/lockjson" "github.com/vim-volt/volt/logger" "github.com/vim-volt/volt/pathutil" + "github.com/vim-volt/volt/subcmd/builder" "github.com/vim-volt/volt/transaction" ) @@ -99,15 +99,14 @@ Quick example return fs } -func (cmd *profileCmd) Run(args []string) int { +func (cmd *profileCmd) Run(args []string) *Error { // Parse args args, err := cmd.parseArgs(args) if err == ErrShowedHelp { - return 0 + return nil } if err != nil { - logger.Error(err.Error()) - return 10 + return &Error{Code: 10, Msg: err.Error()} } subCmd := args[0] @@ -129,16 +128,14 @@ func (cmd *profileCmd) Run(args []string) int { case "rm": err = cmd.doRm(args[1:]) default: - logger.Error("unknown subcommand: " + subCmd) - return 11 + return &Error{Code: 11, Msg: "Unknown subcommand: " + subCmd} } if err != nil { - logger.Error(err.Error()) - return 20 + return &Error{Code: 20, Msg: err.Error()} } - return 0 + return nil } func (cmd *profileCmd) parseArgs(args []string) ([]string, error) { diff --git a/cmd/profile_test.go b/subcmd/profile_test.go similarity index 99% rename from cmd/profile_test.go rename to subcmd/profile_test.go index 354d2a5f..feea4621 100644 --- a/cmd/profile_test.go +++ b/subcmd/profile_test.go @@ -1,4 +1,4 @@ -package cmd +package subcmd import ( "encoding/json" diff --git a/cmd/rm.go b/subcmd/rm.go similarity index 93% rename from cmd/rm.go rename to subcmd/rm.go index 60b020a2..f805b2fd 100644 --- a/cmd/rm.go +++ b/subcmd/rm.go @@ -1,4 +1,4 @@ -package cmd +package subcmd import ( "errors" @@ -8,12 +8,12 @@ import ( "path/filepath" "strings" - "github.com/vim-volt/volt/cmd/builder" "github.com/vim-volt/volt/fileutil" "github.com/vim-volt/volt/lockjson" "github.com/vim-volt/volt/logger" "github.com/vim-volt/volt/pathutil" "github.com/vim-volt/volt/plugconf" + "github.com/vim-volt/volt/subcmd/builder" "github.com/vim-volt/volt/transaction" ) @@ -62,30 +62,27 @@ Description return fs } -func (cmd *rmCmd) Run(args []string) int { +func (cmd *rmCmd) Run(args []string) *Error { reposPathList, err := cmd.parseArgs(args) if err == ErrShowedHelp { - return 0 + return nil } if err != nil { - logger.Error(err.Error()) - return 10 + return &Error{Code: 10, Msg: err.Error()} } err = cmd.doRemove(reposPathList) if err != nil { - logger.Error("Failed to remove repository: " + err.Error()) - return 11 + return &Error{Code: 11, Msg: "Failed to remove repository: " + err.Error()} } // Build opt dir err = builder.Build(false) if err != nil { - logger.Error("could not build " + pathutil.VimVoltDir() + ": " + err.Error()) - return 12 + return &Error{Code: 12, Msg: "Could not build " + pathutil.VimVoltDir() + ": " + err.Error()} } - return 0 + return nil } func (cmd *rmCmd) parseArgs(args []string) ([]pathutil.ReposPath, error) { diff --git a/cmd/rm_test.go b/subcmd/rm_test.go similarity index 99% rename from cmd/rm_test.go rename to subcmd/rm_test.go index dc2405c2..46616974 100644 --- a/cmd/rm_test.go +++ b/subcmd/rm_test.go @@ -1,4 +1,4 @@ -package cmd +package subcmd import ( "fmt" diff --git a/cmd/self_upgrade.go b/subcmd/self_upgrade.go similarity index 94% rename from cmd/self_upgrade.go rename to subcmd/self_upgrade.go index d39403b9..be65a8fd 100644 --- a/cmd/self_upgrade.go +++ b/subcmd/self_upgrade.go @@ -1,4 +1,4 @@ -package cmd +package subcmd import ( "encoding/json" @@ -49,30 +49,27 @@ Description return fs } -func (cmd *selfUpgradeCmd) Run(args []string) int { +func (cmd *selfUpgradeCmd) Run(args []string) *Error { err := cmd.parseArgs(args) if err == ErrShowedHelp { - return 0 + return nil } if err != nil { - logger.Error("Failed to parse args: " + err.Error()) - return 10 + return &Error{Code: 10, Msg: "Failed to parse args: " + err.Error()} } if ppidStr := os.Getenv("VOLT_SELF_UPGRADE_PPID"); ppidStr != "" { if err = cmd.doCleanUp(ppidStr); err != nil { - logger.Error("Failed to clean up old binary: " + err.Error()) - return 11 + return &Error{Code: 11, Msg: "Failed to clean up old binary: " + err.Error()} } } else { latestURL := "https://api.github.com/repos/vim-volt/volt/releases/latest" if err = cmd.doSelfUpgrade(latestURL); err != nil { - logger.Error("Failed to self-upgrade: " + err.Error()) - return 12 + return &Error{Code: 12, Msg: "Failed to self-upgrade: " + err.Error()} } } - return 0 + return nil } func (cmd *selfUpgradeCmd) parseArgs(args []string) error { diff --git a/cmd/self_upgrade_test.go b/subcmd/self_upgrade_test.go similarity index 82% rename from cmd/self_upgrade_test.go rename to subcmd/self_upgrade_test.go index 4d28e5f9..858dd344 100644 --- a/cmd/self_upgrade_test.go +++ b/subcmd/self_upgrade_test.go @@ -1,9 +1,8 @@ -package cmd +package subcmd import ( "io/ioutil" "os" - "strconv" "strings" "testing" ) @@ -29,13 +28,14 @@ func testVoltSelfUpgradeCheckFromOldVer(t *testing.T) { // =============== run =============== // - var code int + var err *Error out := captureOutput(t, func() { - code = Run("self-upgrade", []string{"-check"}) + args := []string{"volt", "self-upgrade", "-check"} + err = Run(args, DefaultRunner) }) - if code != 0 { - t.Error("Expected exitcode=0, but got: " + strconv.Itoa(code)) + if err != nil { + t.Error("Expected nil error, but got: " + err.Error()) } if !strings.Contains(out, "---") { t.Error("Expected release notes, but got: " + out) @@ -44,13 +44,14 @@ func testVoltSelfUpgradeCheckFromOldVer(t *testing.T) { // 'volt self-upgrade -check' from current version should show the latest release func testVoltSelfUpgradeCheckFromCurrentVer(t *testing.T) { - var code int + var err *Error out := captureOutput(t, func() { - code = Run("self-upgrade", []string{"-check"}) + args := []string{"volt", "self-upgrade", "-check"} + err = Run(args, DefaultRunner) }) - if code != 0 { - t.Error("Expected exitcode=0, but got: " + strconv.Itoa(code)) + if err != nil { + t.Error("Expected nil error, but got: " + err.Error()) } if out != "[INFO] No updates were found.\n" { t.Error("Expected no updates found, but got: " + out) diff --git a/cmd/version.go b/subcmd/version.go similarity index 94% rename from cmd/version.go rename to subcmd/version.go index c7614514..65f94623 100644 --- a/cmd/version.go +++ b/subcmd/version.go @@ -1,4 +1,4 @@ -package cmd +package subcmd import ( "errors" @@ -10,7 +10,7 @@ import ( ) // This variable is not constant for testing (to change it temporarily) -var voltVersion = "v0.3.4" +var voltVersion = "v0.3.5" func init() { cmdMap["version"] = &versionCmd{} @@ -40,15 +40,15 @@ Description return fs } -func (cmd *versionCmd) Run(args []string) int { +func (cmd *versionCmd) Run(args []string) *Error { fs := cmd.FlagSet() fs.Parse(args) if cmd.helped { - return 0 + return nil } fmt.Printf("volt version: %s\n", voltVersion) - return 0 + return nil } // [major, minor, patch, alphaBeta] diff --git a/cmd/version_test.go b/subcmd/version_test.go similarity index 98% rename from cmd/version_test.go rename to subcmd/version_test.go index e1e8dc6f..13c51de9 100644 --- a/cmd/version_test.go +++ b/subcmd/version_test.go @@ -1,4 +1,4 @@ -package cmd +package subcmd import "testing"