1
0
mirror of https://github.com/nvbn/thefuck.git synced 2025-11-12 12:55:58 +00:00

Compare commits

..

8 Commits
3.8 ... 3.9

Author SHA1 Message Date
nvbn
f74bbb7a9a Bump to 3.9 2016-04-24 17:56:06 +03:00
nvbn
d6c2c7266d Merge branch 'scorphus-fish-put-to-history' 2016-04-22 03:17:40 +03:00
nvbn
51839e65cd #495: Add comment in put_to_history 2016-04-22 03:16:16 +03:00
nvbn
d5ae3a6b41 Merge branch 'fish-put-to-history' of https://github.com/scorphus/thefuck into scorphus-fish-put-to-history
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
2016-04-22 03:14:31 +03:00
Vladimir Iakovlev
9f421a17e5 Merge pull request #494 from scorphus/brew-update-formula
#N/A Add a new rule `brew_update_formula`
2016-04-21 13:06:11 +03:00
Pablo Santiago Blum de Aguiar
9d9820676a #N/A Add a new rule brew_update_formula 2016-04-20 22:27:39 -03:00
nvbn
5ec4909d2f #N/A: Minor style changes 2016-04-12 00:37:18 +03:00
nvbn
c6d2766553 #N/A: Add chmod +x rule 2016-04-11 16:13:41 +03:00
11 changed files with 139 additions and 3 deletions

View File

@@ -144,6 +144,7 @@ using the matched rule and runs it. Rules enabled by default are as follows:
* `cd_correction` – spellchecks and correct failed cd commands; * `cd_correction` – spellchecks and correct failed cd commands;
* `cd_mkdir` – creates directories before cd'ing into them; * `cd_mkdir` – creates directories before cd'ing into them;
* `cd_parent` – changes `cd..` to `cd ..`; * `cd_parent` – changes `cd..` to `cd ..`;
* `chmod_x` – add execution bit;
* `composer_not_command` – fixes composer command name; * `composer_not_command` – fixes composer command name;
* `cp_omitting_directory` – adds `-a` when you `cp` directory; * `cp_omitting_directory` – adds `-a` when you `cp` directory;
* `cpp11` – adds missing `-std=c++11` to `g++` or `clang++`; * `cpp11` – adds missing `-std=c++11` to `g++` or `clang++`;
@@ -221,6 +222,7 @@ Enabled by default only on specific platforms:
* `apt_invalid_operation` – fixes invalid `apt` and `apt-get` calls, like `apt-get isntall vim`; * `apt_invalid_operation` – fixes invalid `apt` and `apt-get` calls, like `apt-get isntall vim`;
* `brew_install` – fixes formula name for `brew install`; * `brew_install` – fixes formula name for `brew install`;
* `brew_unknown_command` – fixes wrong brew commands, for example `brew docto/brew doctor`; * `brew_unknown_command` – fixes wrong brew commands, for example `brew docto/brew doctor`;
* `brew_update_formula` &ndash; turns `brew update <formula>` into `brew upgrade <formula>`;
* `brew_upgrade` &ndash; appends `--all` to `brew upgrade` as per Homebrew's new behaviour; * `brew_upgrade` &ndash; appends `--all` to `brew upgrade` as per Homebrew's new behaviour;
* `pacman` &ndash; installs app with `pacman` if it is not installed (uses `yaourt` if available); * `pacman` &ndash; installs app with `pacman` if it is not installed (uses `yaourt` if available);
* `pacman_not_found` &ndash; fixes package name with `pacman` or `yaourt`. * `pacman_not_found` &ndash; fixes package name with `pacman` or `yaourt`.

View File

@@ -26,7 +26,7 @@ elif (3, 0) < version < (3, 3):
' ({}.{} detected).'.format(*version)) ' ({}.{} detected).'.format(*version))
sys.exit(-1) sys.exit(-1)
VERSION = '3.8' VERSION = '3.9'
install_requires = ['psutil', 'colorama', 'six', 'decorator'] install_requires = ['psutil', 'colorama', 'six', 'decorator']
extras_require = {':python_version<"3.4"': ['pathlib'], extras_require = {':python_version<"3.4"': ['pathlib'],

View File

@@ -0,0 +1,30 @@
import pytest
from tests.utils import Command
from thefuck.rules.brew_update_formula import get_new_command, match
@pytest.fixture
def stderr():
return ("Error: This command updates brew itself, and does not take formula"
" names.\nUse 'brew upgrade <formula>'.")
@pytest.fixture
def new_command(formula):
return 'brew upgrade {}'.format(formula)
@pytest.mark.parametrize('script', ['brew update foo', 'brew update bar zap'])
def test_match(stderr, script):
assert match(Command(script=script, stderr=stderr))
@pytest.mark.parametrize('script', ['brew upgrade foo', 'brew update'])
def test_not_match(script):
assert not match(Command(script=script, stderr=''))
@pytest.mark.parametrize('script, formula, ', [
('brew update foo', 'foo'), ('brew update bar zap', 'bar zap')])
def test_get_new_command(stderr, new_command, script, formula):
assert get_new_command(Command(script=script, stderr=stderr)) == new_command

View File

@@ -0,0 +1,39 @@
import pytest
from tests.utils import Command
from thefuck.rules.chmod_x import match, get_new_command
@pytest.fixture
def file_exists(mocker):
return mocker.patch('os.path.exists', return_value=True)
@pytest.fixture
def file_access(mocker):
return mocker.patch('os.access', return_value=False)
@pytest.mark.usefixtures('file_exists', 'file_access')
@pytest.mark.parametrize('script, stderr', [
('./gradlew build', 'gradlew: Permission denied'),
('./install.sh --help', 'install.sh: permission denied')])
def test_match(script, stderr):
assert match(Command(script, stderr=stderr))
@pytest.mark.parametrize('script, stderr, exists, callable', [
('./gradlew build', 'gradlew: Permission denied', True, True),
('./gradlew build', 'gradlew: Permission denied', False, False),
('./gradlew build', 'gradlew: error', True, False),
('gradlew build', 'gradlew: Permission denied', True, False)])
def test_not_match(file_exists, file_access, script, stderr, exists, callable):
file_exists.return_value = exists
file_access.return_value = callable
assert not match(Command(script, stderr=stderr))
@pytest.mark.parametrize('script, result', [
('./gradlew build', 'chmod +x gradlew && ./gradlew build'),
('./install.sh --help', 'chmod +x install.sh && ./install.sh --help')])
def test_get_new_command(script, result):
assert get_new_command(Command(script)) == result

View File

@@ -78,3 +78,12 @@ class TestFish(object):
history_lines(['- cmd: ls', ' when: 1432613911', history_lines(['- cmd: ls', ' when: 1432613911',
'- cmd: rm', ' when: 1432613916']) '- cmd: rm', ' when: 1432613916'])
assert list(shell.get_history()) == ['ls', 'rm'] assert list(shell.get_history()) == ['ls', 'rm']
@pytest.mark.parametrize('entry, entry_utf8', [
('ls', '- cmd: ls\n when: 1430707243\n'),
(u'echo café', '- cmd: echo café\n when: 1430707243\n')])
def test_put_to_history(self, entry, entry_utf8, builtins_open, mocker, shell):
mocker.patch('thefuck.shells.fish.time', return_value=1430707243.3517463)
shell.put_to_history(entry)
builtins_open.return_value.__enter__.return_value. \
write.assert_called_once_with(entry_utf8)

View File

@@ -0,0 +1,12 @@
from thefuck.utils import for_app
@for_app('brew', at_least=2)
def match(command):
return ('update' in command.script
and "Error: This command updates brew itself" in command.stderr
and "Use 'brew upgrade <formula>'" in command.stderr)
def get_new_command(command):
return command.script.replace('update', 'upgrade')

15
thefuck/rules/chmod_x.py Normal file
View File

@@ -0,0 +1,15 @@
import os
from thefuck.shells import shell
def match(command):
return (command.script.startswith('./')
and 'permission denied' in command.stderr.lower()
and os.path.exists(command.script_parts[0])
and not os.access(command.script_parts[0], os.X_OK))
def get_new_command(command):
return shell.and_(
'chmod +x {}'.format(command.script_parts[0][2:]),
command.script)

View File

@@ -22,8 +22,7 @@ shells = {'bash': Bash,
def _get_shell(): def _get_shell():
proc = Process(os.getpid()) proc = Process(os.getpid())
while (proc is not None): while proc is not None:
name = None
try: try:
name = proc.name() name = proc.name()
except TypeError: except TypeError:

View File

@@ -1,6 +1,9 @@
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
from time import time from time import time
import os import os
import sys
import six
from .. import logs
from ..utils import DEVNULL, memoize, cache from ..utils import DEVNULL, memoize, cache
from .generic import Generic from .generic import Generic
@@ -65,3 +68,20 @@ class Fish(Generic):
def how_to_configure(self): def how_to_configure(self):
return (r"eval (thefuck --alias | tr '\n' ';')", return (r"eval (thefuck --alias | tr '\n' ';')",
'~/.config/fish/config.fish') '~/.config/fish/config.fish')
def put_to_history(self, command):
try:
return self._put_to_history(command)
except IOError:
logs.exception("Can't update history", sys.exc_info())
def _put_to_history(self, command_script):
"""Puts command script to shell history."""
history_file_name = self._get_history_file_name()
if os.path.isfile(history_file_name):
with open(history_file_name, 'a') as history:
entry = self._get_history_line(command_script)
if six.PY2:
history.write(entry.encode('utf-8'))
else:
history.write(entry)

View File

@@ -81,3 +81,11 @@ class Generic(object):
def _script_from_history(self, line): def _script_from_history(self, line):
return line return line
def put_to_history(self, command):
"""Adds fixed command to shell history.
In most of shells we change history on shell-level, but not
all shells support it (Fish).
"""

View File

@@ -280,6 +280,8 @@ class CorrectedCommand(object):
""" """
if self.side_effect: if self.side_effect:
compatibility_call(self.side_effect, old_cmd, self.script) compatibility_call(self.side_effect, old_cmd, self.script)
if settings.alter_history:
shell.put_to_history(self.script)
# This depends on correct setting of PYTHONIOENCODING by the alias: # This depends on correct setting of PYTHONIOENCODING by the alias:
logs.debug(u'PYTHONIOENCODING: {}'.format( logs.debug(u'PYTHONIOENCODING: {}'.format(
os.environ.get('PYTHONIOENCODING', '!!not-set!!'))) os.environ.get('PYTHONIOENCODING', '!!not-set!!')))