diff --git a/README.md b/README.md index 5498bba8..2ffd8994 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,7 @@ using the matched rule and runs it. Rules enabled by default are as follows: * `git_rebase_no_changes` – runs `git rebase --skip` instead of `git rebase --continue` when there are no changes; * `git_rm_local_modifications` – adds `-f` or `--cached` when you try to `rm` a locally modified file; * `git_rm_recursive` – adds `-r` when you try to `rm` a directory; +* `git_rm_staged` – adds `-f` or `--cached` when you try to `rm` a file with staged changes * `git_rebase_merge_dir` – offers `git rebase (--continue | --abort | --skip)` or removing the `.git/rebase-merge` dir when a rebase is in progress; * `git_remote_seturl_add` – runs `git remote add` when `git remote set_url` on nonexistant remote; * `git_stash` – stashes your local modifications before rebasing or switching branch; diff --git a/tests/rules/test_git_rm_staged.py b/tests/rules/test_git_rm_staged.py new file mode 100644 index 00000000..125ae998 --- /dev/null +++ b/tests/rules/test_git_rm_staged.py @@ -0,0 +1,28 @@ +import pytest +from thefuck.rules.git_rm_staged import match, get_new_command +from tests.utils import Command + + +@pytest.fixture +def stderr(target): + return ('error: the following file has changes staged in the index:\n {}\n(use ' + '--cached to keep the file, or -f to force removal)').format(target) + + +@pytest.mark.parametrize('script, target', [ + ('git rm foo', 'foo'), + ('git rm foo bar', 'bar')]) +def test_match(stderr, script, target): + assert match(Command(script=script, stderr=stderr)) + + +@pytest.mark.parametrize('script', ['git rm foo', 'git rm foo bar', 'git rm']) +def test_not_match(script): + assert not match(Command(script=script, stderr='')) + + +@pytest.mark.parametrize('script, target, new_command', [ + ('git rm foo', 'foo', ['git rm --cached foo', 'git rm -f foo']), + ('git rm foo bar', 'bar', ['git rm --cached foo bar', 'git rm -f foo bar'])]) +def test_get_new_command(stderr, script, target, new_command): + assert get_new_command(Command(script=script, stderr=stderr)) == new_command diff --git a/thefuck/rules/git_rm_staged.py b/thefuck/rules/git_rm_staged.py new file mode 100644 index 00000000..7532a1f6 --- /dev/null +++ b/thefuck/rules/git_rm_staged.py @@ -0,0 +1,19 @@ +from thefuck.specific.git import git_support + + +@git_support +def match(command): + return (' rm ' in command.script and + 'error: the following file has changes staged in the index' in command.stderr and + 'use --cached to keep the file, or -f to force removal' in command.stderr) + + +@git_support +def get_new_command(command): + command_parts = command.script_parts[:] + index = command_parts.index('rm') + 1 + command_parts.insert(index, '--cached') + command_list = [u' '.join(command_parts)] + command_parts[index] = '-f' + command_list.append(u' '.join(command_parts)) + return command_list