diff --git a/README.md b/README.md index 853bf49d..4dfabb44 100644 --- a/README.md +++ b/README.md @@ -141,13 +141,14 @@ using the matched rule and runs it. Rules enabled by default are as follows: * `cpp11` – adds missing `-std=c++11` to `g++` or `clang++`; * `django_south_ghost` – adds `--delete-ghost-migrations` to failed because ghosts django south migration; * `django_south_merge` – adds `--merge` to inconsistent django south migration; -* `dry` – fixes repetitions like "git git push"; +* `dry` – fixes repetitions like `git git push`; * `fix_alt_space` – replaces Alt+Space with Space character; * `git_add` – fixes *"Did you forget to 'git add'?"*; * `git_branch_delete` – changes `git branch -d` to `git branch -D`; * `git_branch_list` – catches `git branch list` in place of `git branch` and removes created branch; * `git_checkout` – fixes branch name or creates new branch; * `git_diff_staged` – adds `--staged` to previous `git diff` with unexpected output; +* `git_fix_stash` – fixes `git stash` commands (misspelled subcommand and missing `save`); * `git_not_command` – fixes wrong git commands like `git brnch`; * `git_pull` – sets upstream before executing previous `git pull`; * `git_pull_clone` – clones instead of pulling when the repo does not exist; @@ -155,14 +156,14 @@ using the matched rule and runs it. Rules enabled by default are as follows: * `git_push_pull` – runs `git pull` when `push` was rejected; * `git_stash` – stashes you local modifications before rebasing or switching branch; * `go_run` – appends `.go` extension when compiling/running Go programs -* `grep_recursive` – adds `-r` when you trying to grep directory; +* `grep_recursive` – adds `-r` when you trying to `grep` directory; * `has_exists_script` – prepends `./` when script/binary exists; -* `heroku_no_command` – fixes wrong heroku commands like `heroku log`; +* `heroku_no_command` – fixes wrong `heroku` commands like `heroku log`; * `history` – tries to replace command with most similar command from history; * `java` – removes `.java` extension when running Java programs; * `javac` – appends missing `.java` when compiling Java files; * `lein_not_task` – fixes wrong `lein` tasks like `lein rpl`; -* `ls_lah` – adds -lah to ls; +* `ls_lah` – adds `-lah` to `ls`; * `man` – changes manual section; * `man_no_space` – fixes man commands without spaces, for example `mandiff`; * `mercurial` – fixes wrong `hg` commands; @@ -170,7 +171,7 @@ using the matched rule and runs it. Rules enabled by default are as follows: * `no_command` – fixes wrong console commands, for example `vom/vim`; * `no_such_file` – creates missing directories with `mv` and `cp` commands; * `open` – prepends `http` to address passed to `open`; -* `pip_unknown_command` – fixes wrong pip commands, for example `pip instatl/pip install`; +* `pip_unknown_command` – fixes wrong `pip` commands, for example `pip instatl/pip install`; * `python_command` – prepends `python` when you trying to run not executable/without `./` python script; * `python_execute` – appends missing `.py` when executing Python files; * `quotation_marks` – fixes uneven usage of `'` and `"` when containing args' @@ -180,9 +181,9 @@ using the matched rule and runs it. Rules enabled by default are as follows: * `ssh_known_hosts` – removes host from `known_hosts` on warning; * `sudo` – prepends `sudo` to previous command if it failed because of permissions; * `switch_layout` – switches command from your local layout to en; -* `systemctl` – correctly orders parameters of confusing systemctl; +* `systemctl` – correctly orders parameters of confusing `systemctl`; * `test.py` – runs `py.test` instead of `test.py`; -* `tmux` – fixes tmux commands; +* `tmux` – fixes `tmux` commands; * `whois` – fixes `whois` command. Enabled by default only on specific platforms: diff --git a/tests/rules/test_git_fix_stash.py b/tests/rules/test_git_fix_stash.py new file mode 100644 index 00000000..c9f65b64 --- /dev/null +++ b/tests/rules/test_git_fix_stash.py @@ -0,0 +1,31 @@ +import pytest +from thefuck.rules.git_fix_stash import match, get_new_command +from tests.utils import Command + + +git_stash_err = ''' +usage: git stash list [] + or: git stash show [] + or: git stash drop [-q|--quiet] [] + or: git stash ( pop | apply ) [--index] [-q|--quiet] [] + or: git stash branch [] + or: git stash [save [--patch] [-k|--[no-]keep-index] [-q|--quiet] + [-u|--include-untracked] [-a|--all] []] + or: git stash clear +''' + + +@pytest.mark.parametrize('wrong', [ + 'git stash opp', + 'git stash Some message', + 'git stash saev Some message']) +def test_match(wrong): + assert match(Command(wrong, stderr=git_stash_err), None) + + +@pytest.mark.parametrize('wrong,fixed', [ + ('git stash opp', 'git stash pop'), + ('git stash Some message', 'git stash save Some message'), + ('git stash saev Some message', 'git stash save Some message')]) +def test_get_new_command(wrong, fixed): + assert get_new_command(Command(wrong, stderr=git_stash_err), None) == fixed diff --git a/thefuck/rules/git_fix_stash.py b/thefuck/rules/git_fix_stash.py new file mode 100644 index 00000000..2ac29a94 --- /dev/null +++ b/thefuck/rules/git_fix_stash.py @@ -0,0 +1,33 @@ +from thefuck import utils + + +@utils.git_support +def match(command, settings): + return (command.script.split()[1] == 'stash' + and 'usage:' in command.stderr) + + +# git's output here is too complicated to be parsed (see the test file) +stash_commands = ( + 'apply', + 'branch', + 'clear', + 'drop', + 'list', + 'pop', + 'save', + 'show', + ) + + +@utils.git_support +def get_new_command(command, settings): + stash_cmd = command.script.split()[2] + fixed = utils.get_closest(stash_cmd, stash_commands, fallback_to_first=False) + + if fixed is not None: + return command.script.replace(stash_cmd, fixed) + else: + cmd = command.script.split() + cmd.insert(2, 'save') + return ' '.join(cmd)