mirror of
				https://github.com/nvbn/thefuck.git
				synced 2025-10-30 22:54:14 +00:00 
			
		
		
		
	Merge branch 'git-aliases' of https://github.com/mcarton/thefuck into mcarton-git-aliases
This commit is contained in:
		| @@ -3,15 +3,13 @@ from thefuck.rules.git_diff_staged import match, get_new_command | |||||||
| from tests.utils import Command | from tests.utils import Command | ||||||
|  |  | ||||||
|  |  | ||||||
| @pytest.mark.parametrize('command', [ | @pytest.mark.parametrize('command', [Command(script='git diff')]) | ||||||
|     Command(script='git diff'), |  | ||||||
|     Command(script='git df'), |  | ||||||
|     Command(script='git ds')]) |  | ||||||
| def test_match(command): | def test_match(command): | ||||||
|     assert match(command, None) |     assert match(command, None) | ||||||
|  |  | ||||||
|  |  | ||||||
| @pytest.mark.parametrize('command', [ | @pytest.mark.parametrize('command', [ | ||||||
|  |     Command(script='git diff --staged'), | ||||||
|     Command(script='git tag'), |     Command(script='git tag'), | ||||||
|     Command(script='git branch'), |     Command(script='git branch'), | ||||||
|     Command(script='git log')]) |     Command(script='git log')]) | ||||||
| @@ -20,8 +18,6 @@ def test_not_match(command): | |||||||
|  |  | ||||||
|  |  | ||||||
| @pytest.mark.parametrize('command, new_command', [ | @pytest.mark.parametrize('command, new_command', [ | ||||||
|     (Command('git diff'), 'git diff --staged'), |     (Command('git diff'), 'git diff --staged')]) | ||||||
|     (Command('git df'), 'git df --staged'), |  | ||||||
|     (Command('git ds'), 'git ds --staged')]) |  | ||||||
| def test_get_new_command(command, new_command): | def test_get_new_command(command, new_command): | ||||||
|     assert get_new_command(command, None) == new_command |     assert get_new_command(command, None) == new_command | ||||||
|   | |||||||
| @@ -3,22 +3,20 @@ from thefuck.rules.git_stash import match, get_new_command | |||||||
| from tests.utils import Command | from tests.utils import Command | ||||||
|  |  | ||||||
|  |  | ||||||
| @pytest.fixture | cherry_pick_error = ( | ||||||
| def cherry_pick_error(): |         'error: Your local changes would be overwritten by cherry-pick.\n' | ||||||
|     return ('error: Your local changes would be overwritten by cherry-pick.\n' |  | ||||||
|         'hint: Commit your changes or stash them to proceed.\n' |         'hint: Commit your changes or stash them to proceed.\n' | ||||||
|         'fatal: cherry-pick failed') |         'fatal: cherry-pick failed') | ||||||
|  |  | ||||||
|  |  | ||||||
| @pytest.fixture | rebase_error = ( | ||||||
| def rebase_error(): |         'Cannot rebase: Your index contains uncommitted changes.\n' | ||||||
|     return ('Cannot rebase: Your index contains uncommitted changes.\n' |  | ||||||
|         'Please commit or stash them.') |         'Please commit or stash them.') | ||||||
|  |  | ||||||
|  |  | ||||||
| @pytest.mark.parametrize('command', [ | @pytest.mark.parametrize('command', [ | ||||||
|     Command(script='git cherry-pick a1b2c3d', stderr=cherry_pick_error()), |     Command(script='git cherry-pick a1b2c3d', stderr=cherry_pick_error), | ||||||
|     Command(script='git rebase -i HEAD~7', stderr=rebase_error())]) |     Command(script='git rebase -i HEAD~7', stderr=rebase_error)]) | ||||||
| def test_match(command): | def test_match(command): | ||||||
|     assert match(command, None) |     assert match(command, None) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -77,23 +77,23 @@ class TestGetCommand(object): | |||||||
|         monkeypatch.setattr('thefuck.shells.to_shell', lambda x: x) |         monkeypatch.setattr('thefuck.shells.to_shell', lambda x: x) | ||||||
|  |  | ||||||
|     def test_get_command_calls(self, Popen): |     def test_get_command_calls(self, Popen): | ||||||
|         assert main.get_command(Mock(), |         assert main.get_command(Mock(env={}), | ||||||
|             ['thefuck', 'apt-get', 'search', 'vim']) \ |             ['thefuck', 'apt-get', 'search', 'vim']) \ | ||||||
|                == Command('apt-get search vim', 'stdout', 'stderr') |                == Command('apt-get search vim', 'stdout', 'stderr') | ||||||
|         Popen.assert_called_once_with('apt-get search vim', |         Popen.assert_called_once_with('apt-get search vim', | ||||||
|                                       shell=True, |                                       shell=True, | ||||||
|                                       stdout=PIPE, |                                       stdout=PIPE, | ||||||
|                                       stderr=PIPE, |                                       stderr=PIPE, | ||||||
|                                       env={'LANG': 'C'}) |                                       env={}) | ||||||
|  |  | ||||||
|     @pytest.mark.parametrize('args, result', [ |     @pytest.mark.parametrize('args, result', [ | ||||||
|         (['thefuck', 'ls', '-la'], 'ls -la'), |         (['thefuck', 'ls', '-la'], 'ls -la'), | ||||||
|         (['thefuck', 'ls'], 'ls')]) |         (['thefuck', 'ls'], 'ls')]) | ||||||
|     def test_get_command_script(self, args, result): |     def test_get_command_script(self, args, result): | ||||||
|         if result: |         if result: | ||||||
|             assert main.get_command(Mock(), args).script == result |             assert main.get_command(Mock(env={}), args).script == result | ||||||
|         else: |         else: | ||||||
|             assert main.get_command(Mock(), args) is None |             assert main.get_command(Mock(env={}), args) is None | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestGetMatchedRule(object): | class TestGetMatchedRule(object): | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| import pytest | import pytest | ||||||
| from mock import Mock | from mock import Mock | ||||||
| from thefuck.utils import sudo_support, wrap_settings, memoize, get_closest | from thefuck.utils import git_support, sudo_support, wrap_settings, memoize, get_closest | ||||||
| from thefuck.types import Settings | from thefuck.types import Settings | ||||||
| from tests.utils import Command | from tests.utils import Command | ||||||
|  |  | ||||||
| @@ -26,6 +26,15 @@ def test_sudo_support(return_value, command, called, result): | |||||||
|     fn.assert_called_once_with(Command(called), None) |     fn.assert_called_once_with(Command(called), None) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @pytest.mark.parametrize('called, command, stderr', [ | ||||||
|  |     ('git co', 'git checkout', "19:22:36.299340 git.c:282   trace: alias expansion: co => 'checkout'"), | ||||||
|  |     ('git com file', 'git commit --verbose file', "19:23:25.470911 git.c:282   trace: alias expansion: com => 'commit' '--verbose'")]) | ||||||
|  | def test_git_support(called, command, stderr): | ||||||
|  |     @git_support | ||||||
|  |     def fn(command, settings): return command.script | ||||||
|  |     assert fn(Command(script=called, stderr=stderr), None) == command | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_memoize(): | def test_memoize(): | ||||||
|     fn = Mock(__name__='fn') |     fn = Mock(__name__='fn') | ||||||
|     memoized = memoize(fn) |     memoized = memoize(fn) | ||||||
|   | |||||||
| @@ -30,7 +30,8 @@ DEFAULT_SETTINGS = {'rules': DEFAULT_RULES, | |||||||
|                     'require_confirmation': False, |                     'require_confirmation': False, | ||||||
|                     'no_colors': False, |                     'no_colors': False, | ||||||
|                     'debug': False, |                     'debug': False, | ||||||
|                     'priority': {}} |                     'priority': {}, | ||||||
|  |                     'env': {'LANG': 'C', 'GIT_TRACE': '1'}} | ||||||
|  |  | ||||||
| ENV_TO_ATTR = {'THEFUCK_RULES': 'rules', | ENV_TO_ATTR = {'THEFUCK_RULES': 'rules', | ||||||
|                'THEFUCK_WAIT_COMMAND': 'wait_command', |                'THEFUCK_WAIT_COMMAND': 'wait_command', | ||||||
|   | |||||||
| @@ -81,8 +81,12 @@ def get_command(settings, args): | |||||||
|  |  | ||||||
|     script = shells.from_shell(script) |     script = shells.from_shell(script) | ||||||
|     logs.debug('Call: {}'.format(script), settings) |     logs.debug('Call: {}'.format(script), settings) | ||||||
|     result = Popen(script, shell=True, stdout=PIPE, stderr=PIPE, |  | ||||||
|                    env=dict(os.environ, LANG='C')) |     env = dict(os.environ) | ||||||
|  |     env.update(settings.env) | ||||||
|  |     logs.debug('Executing with env: {}'.format(env), settings) | ||||||
|  |  | ||||||
|  |     result = Popen(script, shell=True, stdout=PIPE, stderr=PIPE, env=env) | ||||||
|     if wait_output(settings, result): |     if wait_output(settings, result): | ||||||
|         return types.Command(script, result.stdout.read().decode('utf-8'), |         return types.Command(script, result.stdout.read().decode('utf-8'), | ||||||
|                              result.stderr.read().decode('utf-8')) |                              result.stderr.read().decode('utf-8')) | ||||||
|   | |||||||
| @@ -1,13 +1,15 @@ | |||||||
| import re | import re | ||||||
| from thefuck import shells | from thefuck import utils, shells | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @utils.git_support | ||||||
| def match(command, settings): | def match(command, settings): | ||||||
|     return ('git' in command.script |     return ('git' in command.script | ||||||
|             and 'did not match any file(s) known to git.' in command.stderr |             and 'did not match any file(s) known to git.' in command.stderr | ||||||
|             and "Did you forget to 'git add'?" in command.stderr) |             and "Did you forget to 'git add'?" in command.stderr) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @utils.git_support | ||||||
| def get_new_command(command, settings): | def get_new_command(command, settings): | ||||||
|     missing_file = re.findall( |     missing_file = re.findall( | ||||||
|             r"error: pathspec '([^']*)' " |             r"error: pathspec '([^']*)' " | ||||||
|   | |||||||
| @@ -1,10 +1,12 @@ | |||||||
| from thefuck import shells | from thefuck import utils, shells | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @utils.git_support | ||||||
| def match(command, settings): | def match(command, settings): | ||||||
|     # catches "git branch list" in place of "git branch" |     # catches "git branch list" in place of "git branch" | ||||||
|     return command.script.split() == 'git branch list'.split() |     return command.script.split() == 'git branch list'.split() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @utils.git_support | ||||||
| def get_new_command(command, settings): | def get_new_command(command, settings): | ||||||
|     return shells.and_('git branch --delete list', 'git branch') |     return shells.and_('git branch --delete list', 'git branch') | ||||||
|   | |||||||
| @@ -1,13 +1,15 @@ | |||||||
| import re | import re | ||||||
| from thefuck import shells | from thefuck import shells, utils | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @utils.git_support | ||||||
| def match(command, settings): | def match(command, settings): | ||||||
|     return ('git' in command.script |     return ('git' in command.script | ||||||
|             and 'did not match any file(s) known to git.' in command.stderr |             and 'did not match any file(s) known to git.' in command.stderr | ||||||
|             and "Did you forget to 'git add'?" not in command.stderr) |             and "Did you forget to 'git add'?" not in command.stderr) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @utils.git_support | ||||||
| def get_new_command(command, settings): | def get_new_command(command, settings): | ||||||
|     missing_file = re.findall( |     missing_file = re.findall( | ||||||
|             r"error: pathspec '([^']*)' " |             r"error: pathspec '([^']*)' " | ||||||
|   | |||||||
| @@ -1,6 +1,13 @@ | |||||||
|  | from thefuck import utils | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @utils.git_support | ||||||
| def match(command, settings): | def match(command, settings): | ||||||
|     return command.script.startswith('git d') |     return ('git' in command.script and | ||||||
|  |             'diff' in command.script and | ||||||
|  |             '--staged' not in command.script) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @utils.git_support | ||||||
| def get_new_command(command, settings): | def get_new_command(command, settings): | ||||||
|     return '{} --staged'.format(command.script) |     return '{} --staged'.format(command.script) | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| from difflib import get_close_matches |  | ||||||
| import re | import re | ||||||
| from thefuck.utils import get_closest | from thefuck.utils import get_closest, git_support | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @git_support | ||||||
| def match(command, settings): | def match(command, settings): | ||||||
|     return ('git' in command.script |     return ('git' in command.script | ||||||
|             and " is not a git command. See 'git --help'." in command.stderr |             and " is not a git command. See 'git --help'." in command.stderr | ||||||
| @@ -18,6 +18,7 @@ def _get_all_git_matched_commands(stderr): | |||||||
|             yield line.strip() |             yield line.strip() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @git_support | ||||||
| def get_new_command(command, settings): | def get_new_command(command, settings): | ||||||
|     broken_cmd = re.findall(r"git: '([^']*)' is not a git command", |     broken_cmd = re.findall(r"git: '([^']*)' is not a git command", | ||||||
|                             command.stderr)[0] |                             command.stderr)[0] | ||||||
|   | |||||||
| @@ -1,12 +1,14 @@ | |||||||
| from thefuck import shells | from thefuck import shells, utils | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @utils.git_support | ||||||
| def match(command, settings): | def match(command, settings): | ||||||
|     return ('git' in command.script |     return ('git' in command.script | ||||||
|             and 'pull' in command.script |             and 'pull' in command.script | ||||||
|             and 'set-upstream' in command.stderr) |             and 'set-upstream' in command.stderr) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @utils.git_support | ||||||
| def get_new_command(command, settings): | def get_new_command(command, settings): | ||||||
|     line = command.stderr.split('\n')[-3].strip() |     line = command.stderr.split('\n')[-3].strip() | ||||||
|     branch = line.split(' ')[-1] |     branch = line.split(' ')[-1] | ||||||
|   | |||||||
| @@ -1,8 +1,13 @@ | |||||||
|  | from thefuck import utils | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @utils.git_support | ||||||
| def match(command, settings): | def match(command, settings): | ||||||
|     return ('git' in command.script |     return ('git' in command.script | ||||||
|             and 'push' in command.script |             and 'push' in command.script | ||||||
|             and 'set-upstream' in command.stderr) |             and 'set-upstream' in command.stderr) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @utils.git_support | ||||||
| def get_new_command(command, settings): | def get_new_command(command, settings): | ||||||
|     return command.stderr.split('\n')[-3].strip() |     return command.stderr.split('\n')[-3].strip() | ||||||
|   | |||||||
| @@ -1,12 +1,14 @@ | |||||||
| from thefuck import shells | from thefuck import shells, utils | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @utils.git_support | ||||||
| def match(command, settings): | def match(command, settings): | ||||||
|     # catches "Please commit or stash them" and "Please, commit your changes or |     # catches "Please commit or stash them" and "Please, commit your changes or | ||||||
|     # stash them before you can switch branches." |     # stash them before you can switch branches." | ||||||
|     return 'git' in command.script and 'or stash them' in command.stderr |     return 'git' in command.script and 'or stash them' in command.stderr | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @utils.git_support | ||||||
| def get_new_command(command, settings): | def get_new_command(command, settings): | ||||||
|     formatme = shells.and_('git stash', '{}') |     formatme = shells.and_('git stash', '{}') | ||||||
|     return formatme.format(command.script) |     return formatme.format(command.script) | ||||||
|   | |||||||
| @@ -1,7 +1,9 @@ | |||||||
| from difflib import get_close_matches | from difflib import get_close_matches | ||||||
| from functools import wraps | from functools import wraps | ||||||
|  | from shlex import split | ||||||
| import os | import os | ||||||
| import pickle | import pickle | ||||||
|  | import re | ||||||
| import six | import six | ||||||
| from .types import Command | from .types import Command | ||||||
|  |  | ||||||
| @@ -9,11 +11,9 @@ from .types import Command | |||||||
| DEVNULL = open(os.devnull, 'w') | DEVNULL = open(os.devnull, 'w') | ||||||
|  |  | ||||||
| if six.PY2: | if six.PY2: | ||||||
|     import pipes |     from pipes import quote | ||||||
|     quote = pipes.quote |  | ||||||
| else: | else: | ||||||
|     import shlex |     from shlex import quote | ||||||
|     quote = shlex.quote |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def which(program): | def which(program): | ||||||
| @@ -73,6 +73,30 @@ def sudo_support(fn): | |||||||
|     return wrapper |     return wrapper | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def git_support(fn): | ||||||
|  |     """Resolve git aliases.""" | ||||||
|  |     @wraps(fn) | ||||||
|  |     def wrapper(command, settings): | ||||||
|  |         if (command.script.startswith('git') and | ||||||
|  |                 'trace: alias expansion:' in command.stderr): | ||||||
|  |  | ||||||
|  |             search = re.search("trace: alias expansion: ([^ ]*) => ([^\n]*)", | ||||||
|  |                                command.stderr) | ||||||
|  |             alias = search.group(1) | ||||||
|  |  | ||||||
|  |             # by default git quotes everthing, for example: | ||||||
|  |             #     'commit' '--amend' | ||||||
|  |             # which is surprising and does not allow to easily test for | ||||||
|  |             # eg. 'git commit' | ||||||
|  |             expansion = ' '.join(map(quote, split(search.group(2)))) | ||||||
|  |             new_script = command.script.replace(alias, expansion) | ||||||
|  |  | ||||||
|  |             command = Command._replace(command, script=new_script) | ||||||
|  |         return fn(command, settings) | ||||||
|  |  | ||||||
|  |     return wrapper | ||||||
|  |  | ||||||
|  |  | ||||||
| def memoize(fn): | def memoize(fn): | ||||||
|     """Caches previous calls to the function.""" |     """Caches previous calls to the function.""" | ||||||
|     memo = {} |     memo = {} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user