From 903abff77e4150ef9e46f0b947b96a3d12fa9e23 Mon Sep 17 00:00:00 2001 From: mcarton Date: Tue, 21 Jul 2015 15:06:04 +0200 Subject: [PATCH 1/2] Support hub as well as git in @git_support --- tests/rules/test_git_push.py | 2 +- tests/test_utils.py | 14 ++++++++++++++ thefuck/utils.py | 14 +++++++++++--- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/tests/rules/test_git_push.py b/tests/rules/test_git_push.py index 7a2b512d..2625c0d9 100644 --- a/tests/rules/test_git_push.py +++ b/tests/rules/test_git_push.py @@ -20,5 +20,5 @@ def test_match(stderr): def test_get_new_command(stderr): - assert get_new_command(Command(stderr=stderr), None)\ + assert get_new_command(Command('git push', stderr=stderr), None)\ == "git push --set-upstream origin master" diff --git a/tests/test_utils.py b/tests/test_utils.py index 39ab00fa..208911d5 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -36,6 +36,20 @@ def test_git_support(called, command, stderr): assert fn(Command(script=called, stderr=stderr), None) == command +@pytest.mark.parametrize('command, is_git', [ + ('git pull', True), + ('hub pull', True), + ('git push --set-upstream origin foo', True), + ('hub push --set-upstream origin foo', True), + ('ls', False), + ('cat git', False), + ('cat hub', False)]) +def test_git_support_match(command, is_git): + @git_support + def fn(command, settings): return True + assert fn(Command(script=command), None) == is_git + + def test_memoize(): fn = Mock(__name__='fn') memoized = memoize(fn) diff --git a/thefuck/utils.py b/thefuck/utils.py index 19d696af..5be2c2bb 100644 --- a/thefuck/utils.py +++ b/thefuck/utils.py @@ -75,12 +75,19 @@ def sudo_support(fn): def git_support(fn): - """Resolve git aliases.""" + """Resolves git aliases and supports testing for both git and hub.""" @wraps(fn) def wrapper(command, settings): - if (command.script.startswith('git') and - 'trace: alias expansion:' in command.stderr): + # supports GitHub's `hub` command + # which is recommended to be used with `alias git=hub` + # but at this point, shell aliases have already been resolved + is_git_cmd = command.script.startswith(('git', 'hub')) + if not is_git_cmd: + return False + + # perform git aliases expansion + if 'trace: alias expansion:' in command.stderr: search = re.search("trace: alias expansion: ([^ ]*) => ([^\n]*)", command.stderr) alias = search.group(1) @@ -93,6 +100,7 @@ def git_support(fn): new_script = command.script.replace(alias, expansion) command = Command._replace(command, script=new_script) + return fn(command, settings) return wrapper From 98a9fb3d7d0a5225ecc73d873d8503e2cad1fbf6 Mon Sep 17 00:00:00 2001 From: mcarton Date: Tue, 21 Jul 2015 15:35:39 +0200 Subject: [PATCH 2/2] Remove now redundant checks in `git_*` rules --- thefuck/rules/git_add.py | 3 +-- thefuck/rules/git_branch_delete.py | 2 +- thefuck/rules/git_branch_list.py | 2 +- thefuck/rules/git_checkout.py | 3 +-- thefuck/rules/git_diff_staged.py | 3 +-- thefuck/rules/git_not_command.py | 3 +-- thefuck/rules/git_pull.py | 3 +-- thefuck/rules/git_pull_clone.py | 6 ++---- thefuck/rules/git_push.py | 3 +-- thefuck/rules/git_push_force.py | 3 +-- thefuck/rules/git_push_pull.py | 3 +-- thefuck/rules/git_stash.py | 2 +- 12 files changed, 13 insertions(+), 23 deletions(-) diff --git a/thefuck/rules/git_add.py b/thefuck/rules/git_add.py index 66f34726..10415d91 100644 --- a/thefuck/rules/git_add.py +++ b/thefuck/rules/git_add.py @@ -4,8 +4,7 @@ from thefuck import utils, shells @utils.git_support def match(command, settings): - return ('git' in command.script - and 'did not match any file(s) known to git.' in command.stderr + return ('did not match any file(s) known to git.' in command.stderr and "Did you forget to 'git add'?" in command.stderr) diff --git a/thefuck/rules/git_branch_delete.py b/thefuck/rules/git_branch_delete.py index f4bf218a..8f20bc4b 100644 --- a/thefuck/rules/git_branch_delete.py +++ b/thefuck/rules/git_branch_delete.py @@ -3,7 +3,7 @@ from thefuck import utils @utils.git_support def match(command, settings): - return ('git branch -d' in command.script + return ('branch -d' in command.script and 'If you are sure you want to delete it' in command.stderr) diff --git a/thefuck/rules/git_branch_list.py b/thefuck/rules/git_branch_list.py index 9f6dd5f6..b3975408 100644 --- a/thefuck/rules/git_branch_list.py +++ b/thefuck/rules/git_branch_list.py @@ -4,7 +4,7 @@ from thefuck import utils, shells @utils.git_support def match(command, settings): # catches "git branch list" in place of "git branch" - return command.script.split() == 'git branch list'.split() + return command.script.split()[1:] == 'branch list'.split() @utils.git_support diff --git a/thefuck/rules/git_checkout.py b/thefuck/rules/git_checkout.py index c3a3fce8..992f615b 100644 --- a/thefuck/rules/git_checkout.py +++ b/thefuck/rules/git_checkout.py @@ -5,8 +5,7 @@ from thefuck import shells, utils @utils.git_support def match(command, settings): - return ('git' in command.script - and 'did not match any file(s) known to git.' in command.stderr + return ('did not match any file(s) known to git.' in command.stderr and "Did you forget to 'git add'?" not in command.stderr) diff --git a/thefuck/rules/git_diff_staged.py b/thefuck/rules/git_diff_staged.py index a35234e4..9e6d202c 100644 --- a/thefuck/rules/git_diff_staged.py +++ b/thefuck/rules/git_diff_staged.py @@ -3,8 +3,7 @@ from thefuck import utils @utils.git_support def match(command, settings): - return ('git' in command.script and - 'diff' in command.script and + return ('diff' in command.script and '--staged' not in command.script) diff --git a/thefuck/rules/git_not_command.py b/thefuck/rules/git_not_command.py index 1fa707ab..81214b85 100644 --- a/thefuck/rules/git_not_command.py +++ b/thefuck/rules/git_not_command.py @@ -4,8 +4,7 @@ from thefuck.utils import get_closest, git_support @git_support def match(command, settings): - return ('git' in command.script - and " is not a git command. See 'git --help'." in command.stderr + return (" is not a git command. See 'git --help'." in command.stderr and 'Did you mean' in command.stderr) diff --git a/thefuck/rules/git_pull.py b/thefuck/rules/git_pull.py index 65f44ea5..773cfa31 100644 --- a/thefuck/rules/git_pull.py +++ b/thefuck/rules/git_pull.py @@ -3,8 +3,7 @@ from thefuck import shells, utils @utils.git_support def match(command, settings): - return ('git' in command.script - and 'pull' in command.script + return ('pull' in command.script and 'set-upstream' in command.stderr) diff --git a/thefuck/rules/git_pull_clone.py b/thefuck/rules/git_pull_clone.py index c5e68a7a..79472ea0 100644 --- a/thefuck/rules/git_pull_clone.py +++ b/thefuck/rules/git_pull_clone.py @@ -1,11 +1,9 @@ -import re -from thefuck import utils, shells +from thefuck import utils @utils.git_support def match(command, settings): - return ('git pull' in command.script - and 'fatal: Not a git repository' in command.stderr + return ('fatal: Not a git repository' in command.stderr and "Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set)." in command.stderr) diff --git a/thefuck/rules/git_push.py b/thefuck/rules/git_push.py index 5b6ea09a..34b16d21 100644 --- a/thefuck/rules/git_push.py +++ b/thefuck/rules/git_push.py @@ -3,8 +3,7 @@ from thefuck import utils @utils.git_support def match(command, settings): - return ('git' in command.script - and 'push' in command.script + return ('push' in command.script and 'set-upstream' in command.stderr) diff --git a/thefuck/rules/git_push_force.py b/thefuck/rules/git_push_force.py index 46238172..5b3f25d5 100644 --- a/thefuck/rules/git_push_force.py +++ b/thefuck/rules/git_push_force.py @@ -3,8 +3,7 @@ from thefuck import utils @utils.git_support def match(command, settings): - return ('git' in command.script - and 'push' in command.script + return ('push' in command.script and '! [rejected]' in command.stderr and 'failed to push some refs to' in command.stderr and 'Updates were rejected because the tip of your current branch is behind' in command.stderr) diff --git a/thefuck/rules/git_push_pull.py b/thefuck/rules/git_push_pull.py index 2958a2c4..7ae7b9a8 100644 --- a/thefuck/rules/git_push_pull.py +++ b/thefuck/rules/git_push_pull.py @@ -4,8 +4,7 @@ from thefuck.shells import and_ @utils.git_support def match(command, settings): - return ('git' in command.script - and 'push' in command.script + return ('push' in command.script and '! [rejected]' in command.stderr and 'failed to push some refs to' in command.stderr and 'Updates were rejected because the tip of your current branch is behind' in command.stderr) diff --git a/thefuck/rules/git_stash.py b/thefuck/rules/git_stash.py index 76cbdf46..1fb0286e 100644 --- a/thefuck/rules/git_stash.py +++ b/thefuck/rules/git_stash.py @@ -5,7 +5,7 @@ from thefuck import shells, utils def match(command, settings): # catches "Please commit or stash them" and "Please, commit your changes or # stash them before you can switch branches." - return 'git' in command.script and 'or stash them' in command.stderr + return 'or stash them' in command.stderr @utils.git_support