1
0
mirror of https://github.com/nvbn/thefuck.git synced 2025-03-20 09:39:01 +00:00

Merge branch 'master' into git-hook-bypass

This commit is contained in:
Divya Jain 2020-06-15 22:15:54 +05:30 committed by GitHub
commit b5f48be95d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 83 additions and 57 deletions

View File

@ -215,6 +215,7 @@ following rules are enabled by default:
* `git_flag_after_filename` – fixes `fatal: bad flag '...' after filename` * `git_flag_after_filename` – fixes `fatal: bad flag '...' after filename`
* `git_help_aliased` &ndash; fixes `git help <alias>` commands replacing <alias> with the aliased command; * `git_help_aliased` &ndash; fixes `git help <alias>` commands replacing <alias> with the aliased command;
* `git_hook_bypass` &ndash; adds `--no-verify` flag previous to `git am`, `git commit`, or `git push` command; * `git_hook_bypass` &ndash; adds `--no-verify` flag previous to `git am`, `git commit`, or `git push` command;
* `git_lfs_mistype` &ndash; fixes mistyped `git lfs <command>` commands;
* `git_merge` &ndash; adds remote to branch names; * `git_merge` &ndash; adds remote to branch names;
* `git_merge_unrelated` &ndash; adds `--allow-unrelated-histories` when required * `git_merge_unrelated` &ndash; adds `--allow-unrelated-histories` when required
* `git_not_command` &ndash; fixes wrong git commands like `git brnch`; * `git_not_command` &ndash; fixes wrong git commands like `git brnch`;

View File

@ -2,62 +2,54 @@
import pytest import pytest
import os import os
from collections import namedtuple
from thefuck.rules.fix_file import match, get_new_command from thefuck.rules.fix_file import match, get_new_command
from thefuck.types import Command from thefuck.types import Command
FixFileTest = namedtuple('FixFileTest', ['script', 'file', 'line', 'col', 'output'])
# (script, file, line, col (or None), output)
tests = ( tests = (
('gcc a.c', 'a.c', 3, 1, FixFileTest('gcc a.c', 'a.c', 3, 1, """
"""
a.c: In function 'main': a.c: In function 'main':
a.c:3:1: error: expected expression before '}' token a.c:3:1: error: expected expression before '}' token
} }
^ ^
"""), """),
('clang a.c', 'a.c', 3, 1, FixFileTest('clang a.c', 'a.c', 3, 1, """
"""
a.c:3:1: error: expected expression a.c:3:1: error: expected expression
} }
^ ^
"""), """),
('perl a.pl', 'a.pl', 3, None, FixFileTest('perl a.pl', 'a.pl', 3, None, """
"""
syntax error at a.pl line 3, at EOF syntax error at a.pl line 3, at EOF
Execution of a.pl aborted due to compilation errors. Execution of a.pl aborted due to compilation errors.
"""), """),
('perl a.pl', 'a.pl', 2, None, FixFileTest('perl a.pl', 'a.pl', 2, None, """
"""
Search pattern not terminated at a.pl line 2. Search pattern not terminated at a.pl line 2.
"""), """),
('sh a.sh', 'a.sh', 2, None, FixFileTest('sh a.sh', 'a.sh', 2, None, """
"""
a.sh: line 2: foo: command not found a.sh: line 2: foo: command not found
"""), """),
('zsh a.sh', 'a.sh', 2, None, FixFileTest('zsh a.sh', 'a.sh', 2, None, """
"""
a.sh:2: command not found: foo a.sh:2: command not found: foo
"""), """),
('bash a.sh', 'a.sh', 2, None, FixFileTest('bash a.sh', 'a.sh', 2, None, """
"""
a.sh: line 2: foo: command not found a.sh: line 2: foo: command not found
"""), """),
('rustc a.rs', 'a.rs', 2, 5, FixFileTest('rustc a.rs', 'a.rs', 2, 5, """
"""
a.rs:2:5: 2:6 error: unexpected token: `+` a.rs:2:5: 2:6 error: unexpected token: `+`
a.rs:2 + a.rs:2 +
^ ^
"""), """),
('cargo build', 'src/lib.rs', 3, 5, FixFileTest('cargo build', 'src/lib.rs', 3, 5, """
"""
Compiling test v0.1.0 (file:///tmp/fix-error/test) Compiling test v0.1.0 (file:///tmp/fix-error/test)
src/lib.rs:3:5: 3:6 error: unexpected token: `+` src/lib.rs:3:5: 3:6 error: unexpected token: `+`
src/lib.rs:3 + src/lib.rs:3 +
@ -67,16 +59,14 @@ Could not compile `test`.
To learn more, run the command again with --verbose. To learn more, run the command again with --verbose.
"""), """),
('python a.py', 'a.py', 2, None, FixFileTest('python a.py', 'a.py', 2, None, """
"""
File "a.py", line 2 File "a.py", line 2
+ +
^ ^
SyntaxError: invalid syntax SyntaxError: invalid syntax
"""), """),
('python a.py', 'a.py', 8, None, FixFileTest('python a.py', 'a.py', 8, None, """
"""
Traceback (most recent call last): Traceback (most recent call last):
File "a.py", line 8, in <module> File "a.py", line 8, in <module>
match("foo") match("foo")
@ -89,8 +79,7 @@ Traceback (most recent call last):
TypeError: first argument must be string or compiled pattern TypeError: first argument must be string or compiled pattern
"""), """),
(u'python café.py', u'café.py', 8, None, FixFileTest(u'python café.py', u'café.py', 8, None, u"""
u"""
Traceback (most recent call last): Traceback (most recent call last):
File "café.py", line 8, in <module> File "café.py", line 8, in <module>
match("foo") match("foo")
@ -103,57 +92,48 @@ Traceback (most recent call last):
TypeError: first argument must be string or compiled pattern TypeError: first argument must be string or compiled pattern
"""), """),
('ruby a.rb', 'a.rb', 3, None, FixFileTest('ruby a.rb', 'a.rb', 3, None, """
"""
a.rb:3: syntax error, unexpected keyword_end a.rb:3: syntax error, unexpected keyword_end
"""), """),
('lua a.lua', 'a.lua', 2, None, FixFileTest('lua a.lua', 'a.lua', 2, None, """
"""
lua: a.lua:2: unexpected symbol near '+' lua: a.lua:2: unexpected symbol near '+'
"""), """),
('fish a.sh', '/tmp/fix-error/a.sh', 2, None, FixFileTest('fish a.sh', '/tmp/fix-error/a.sh', 2, None, """
"""
fish: Unknown command 'foo' fish: Unknown command 'foo'
/tmp/fix-error/a.sh (line 2): foo /tmp/fix-error/a.sh (line 2): foo
^ ^
"""), """),
('./a', './a', 2, None, FixFileTest('./a', './a', 2, None, """
"""
awk: ./a:2: BEGIN { print "Hello, world!" + } awk: ./a:2: BEGIN { print "Hello, world!" + }
awk: ./a:2: ^ syntax error awk: ./a:2: ^ syntax error
"""), """),
('llc a.ll', 'a.ll', 1, 2, FixFileTest('llc a.ll', 'a.ll', 1, 2, """
"""
llc: a.ll:1:2: error: expected top-level entity llc: a.ll:1:2: error: expected top-level entity
+ +
^ ^
"""), """),
('go build a.go', 'a.go', 1, 2, FixFileTest('go build a.go', 'a.go', 1, 2, """
"""
can't load package: can't load package:
a.go:1:2: expected 'package', found '+' a.go:1:2: expected 'package', found '+'
"""), """),
('make', 'Makefile', 2, None, FixFileTest('make', 'Makefile', 2, None, """
"""
bidule bidule
make: bidule: Command not found make: bidule: Command not found
Makefile:2: recipe for target 'target' failed Makefile:2: recipe for target 'target' failed
make: *** [target] Error 127 make: *** [target] Error 127
"""), """),
('git st', '/home/martin/.config/git/config', 1, None, FixFileTest('git st', '/home/martin/.config/git/config', 1, None, """
"""
fatal: bad config file line 1 in /home/martin/.config/git/config fatal: bad config file line 1 in /home/martin/.config/git/config
"""), """),
('node fuck.js asdf qwer', '/Users/pablo/Workspace/barebones/fuck.js', '2', 5, FixFileTest('node fuck.js asdf qwer', '/Users/pablo/Workspace/barebones/fuck.js', '2', 5, """
"""
/Users/pablo/Workspace/barebones/fuck.js:2 /Users/pablo/Workspace/barebones/fuck.js:2
conole.log(arg); // this should read console.log(arg); conole.log(arg); // this should read console.log(arg);
^ ^
@ -170,16 +150,14 @@ ReferenceError: conole is not defined
at node.js:814:3 at node.js:814:3
"""), """),
('pep8', './tests/rules/test_systemctl.py', 17, 80, FixFileTest('pep8', './tests/rules/test_systemctl.py', 17, 80, """
"""
./tests/rules/test_systemctl.py:17:80: E501 line too long (93 > 79 characters) ./tests/rules/test_systemctl.py:17:80: E501 line too long (93 > 79 characters)
./tests/rules/test_systemctl.py:18:80: E501 line too long (103 > 79 characters) ./tests/rules/test_systemctl.py:18:80: E501 line too long (103 > 79 characters)
./tests/rules/test_whois.py:20:80: E501 line too long (89 > 79 characters) ./tests/rules/test_whois.py:20:80: E501 line too long (89 > 79 characters)
./tests/rules/test_whois.py:22:80: E501 line too long (83 > 79 characters) ./tests/rules/test_whois.py:22:80: E501 line too long (83 > 79 characters)
"""), """),
('py.test', '/home/thefuck/tests/rules/test_fix_file.py', 218, None, FixFileTest('py.test', '/home/thefuck/tests/rules/test_fix_file.py', 218, None, """
"""
monkeypatch = <_pytest.monkeypatch.monkeypatch object at 0x7fdb76a25b38> monkeypatch = <_pytest.monkeypatch.monkeypatch object at 0x7fdb76a25b38>
test = ('fish a.sh', '/tmp/fix-error/a.sh', 2, None, '', "\\nfish: Unknown command 'foo'\\n/tmp/fix-error/a.sh (line 2): foo\\n ^\\n") test = ('fish a.sh', '/tmp/fix-error/a.sh', 2, None, '', "\\nfish: Unknown command 'foo'\\n/tmp/fix-error/a.sh (line 2): foo\\n ^\\n")
@ -191,7 +169,7 @@ E NameError: name 'mocker' is not defined
/home/thefuck/tests/rules/test_fix_file.py:218: NameError /home/thefuck/tests/rules/test_fix_file.py:218: NameError
"""), """),
) # noqa )
@pytest.mark.parametrize('test', tests) @pytest.mark.parametrize('test', tests)
@ -199,7 +177,7 @@ E NameError: name 'mocker' is not defined
def test_match(mocker, monkeypatch, test): def test_match(mocker, monkeypatch, test):
mocker.patch('os.path.isfile', return_value=True) mocker.patch('os.path.isfile', return_value=True)
monkeypatch.setenv('EDITOR', 'dummy_editor') monkeypatch.setenv('EDITOR', 'dummy_editor')
assert match(Command('', test[4])) assert match(Command('', test.output))
@pytest.mark.parametrize('test', tests) @pytest.mark.parametrize('test', tests)
@ -209,7 +187,7 @@ def test_no_editor(mocker, monkeypatch, test):
if 'EDITOR' in os.environ: if 'EDITOR' in os.environ:
monkeypatch.delenv('EDITOR') monkeypatch.delenv('EDITOR')
assert not match(Command('', test[4])) assert not match(Command('', test.output))
@pytest.mark.parametrize('test', tests) @pytest.mark.parametrize('test', tests)
@ -218,7 +196,7 @@ def test_not_file(mocker, monkeypatch, test):
mocker.patch('os.path.isfile', return_value=False) mocker.patch('os.path.isfile', return_value=False)
monkeypatch.setenv('EDITOR', 'dummy_editor') monkeypatch.setenv('EDITOR', 'dummy_editor')
assert not match(Command('', test[4])) assert not match(Command('', test.output))
@pytest.mark.parametrize('test', tests) @pytest.mark.parametrize('test', tests)
@ -234,12 +212,12 @@ def test_get_new_command_with_settings(mocker, monkeypatch, test, settings):
mocker.patch('os.path.isfile', return_value=True) mocker.patch('os.path.isfile', return_value=True)
monkeypatch.setenv('EDITOR', 'dummy_editor') monkeypatch.setenv('EDITOR', 'dummy_editor')
cmd = Command(test[0], test[4]) cmd = Command(test.script, test.output)
settings.fixcolcmd = '{editor} {file} +{line}:{col}' settings.fixcolcmd = '{editor} {file} +{line}:{col}'
if test[3]: if test.col:
assert (get_new_command(cmd) == assert (get_new_command(cmd) ==
u'dummy_editor {} +{}:{} && {}'.format(test[1], test[2], test[3], test[0])) u'dummy_editor {} +{}:{} && {}'.format(test.file, test.line, test.col, test.script))
else: else:
assert (get_new_command(cmd) == assert (get_new_command(cmd) ==
u'dummy_editor {} +{} && {}'.format(test[1], test[2], test[0])) u'dummy_editor {} +{} && {}'.format(test.file, test.line, test.script))

View File

@ -0,0 +1,29 @@
import pytest
from thefuck.rules.git_lfs_mistype import match, get_new_command
from thefuck.types import Command
@pytest.fixture
def mistype_response():
return """
Error: unknown command "evn" for "git-lfs"
Did you mean this?
env
ext
Run 'git-lfs --help' for usage.
"""
def test_match(mistype_response):
assert match(Command('git lfs evn', mistype_response))
err_response = 'bash: git: command not found'
assert not match(Command('git lfs env', err_response))
assert not match(Command('docker lfs env', mistype_response))
def test_get_new_command(mistype_response):
assert (get_new_command(Command('git lfs evn', mistype_response))
== ['git lfs env', 'git lfs ext'])

View File

@ -71,7 +71,7 @@ def organize_commands(corrected_commands):
without_duplicates, without_duplicates,
key=lambda corrected_command: corrected_command.priority) key=lambda corrected_command: corrected_command.priority)
logs.debug('Corrected commands: '.format( logs.debug(u'Corrected commands: {}'.format(
', '.join(u'{}'.format(cmd) for cmd in [first_command] + sorted_commands))) ', '.join(u'{}'.format(cmd) for cmd in [first_command] + sorted_commands)))
for command in sorted_commands: for command in sorted_commands:

View File

@ -0,0 +1,18 @@
import re
from thefuck.utils import get_all_matched_commands, replace_command
from thefuck.specific.git import git_support
@git_support
def match(command):
'''
Match a mistyped command
'''
return 'lfs' in command.script and 'Did you mean this?' in command.output
@git_support
def get_new_command(command):
broken_cmd = re.findall(r'Error: unknown command "([^"]*)" for "git-lfs"', command.output)[0]
matched = get_all_matched_commands(command.output, ['Did you mean', ' for usage.'])
return replace_command(command, broken_cmd, matched)

View File

@ -122,7 +122,7 @@ class Rule(object):
def __repr__(self): def __repr__(self):
return 'Rule(name={}, match={}, get_new_command={}, ' \ return 'Rule(name={}, match={}, get_new_command={}, ' \
'enabled_by_default={}, side_effect={}, ' \ 'enabled_by_default={}, side_effect={}, ' \
'priority={}, requires_output)'.format( 'priority={}, requires_output={})'.format(
self.name, self.match, self.get_new_command, self.name, self.match, self.get_new_command,
self.enabled_by_default, self.side_effect, self.enabled_by_default, self.side_effect,
self.priority, self.requires_output) self.priority, self.requires_output)