1
0
mirror of https://github.com/nvbn/thefuck.git synced 2025-01-19 04:21:14 +00:00

Merge pull request #335 from mcarton/pacman

Add a new rule for pacman/yaourt and fix the apt_get rule
This commit is contained in:
Vladimir Iakovlev 2015-08-16 03:38:50 +03:00
commit 85647794dc
9 changed files with 153 additions and 58 deletions

View File

@ -189,7 +189,7 @@ using the matched rule and runs it. Rules enabled by default are as follows:
* `systemctl` – correctly orders parameters of confusing `systemctl`;
* `test.py` – runs `py.test` instead of `test.py`;
* `tsuru_login` – runs `tsuru login` if not authenticated or session expired;
* `tsuru_not_command` – fixes wrong tsuru commands like `tsuru shell`;
* `tsuru_not_command` – fixes wrong `tsuru` commands like `tsuru shell`;
* `tmux` – fixes `tmux` commands;
* `whois` – fixes `whois` command.
@ -199,7 +199,7 @@ Enabled by default only on specific platforms:
* `brew_install` – fixes formula name for `brew install`;
* `brew_unknown_command` – fixes wrong brew commands, for example `brew docto/brew doctor`;
* `brew_upgrade` – appends `--all` to `brew upgrade` as per Homebrew's new behaviour;
* `pacman` – installs app with `pacman` or `yaourt` if it is not installed.
* `pacman` – installs app with `pacman` if it is not installed (uses `yaourt` if available).
Bundled, but not enabled by default:

View File

@ -16,6 +16,8 @@ def test_match(command):
@pytest.mark.parametrize('command, return_value', [
(Command(script='vim', stderr='vim: command not found'),
[('vim', 'main'), ('vim-tiny', 'main')]),
(Command(script='sudo vim', stderr='vim: command not found'),
[('vim', 'main'), ('vim-tiny', 'main')])])
@patch('thefuck.rules.apt_get.CommandNotFound', create=True)
@patch.multiple(apt_get, create=True, apt_get='apt_get')
@ -38,7 +40,9 @@ def test_not_match(command):
reason='Skip if python-commandnotfound is not available')
@pytest.mark.parametrize('command, new_command', [
(Command('vim'), 'sudo apt-get install vim && vim'),
(Command('convert'), 'sudo apt-get install imagemagick && convert')])
(Command('convert'), 'sudo apt-get install imagemagick && convert'),
(Command('sudo vim'), 'sudo apt-get install vim && sudo vim'),
(Command('sudo convert'), 'sudo apt-get install imagemagick && sudo convert')])
def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command
@ -47,6 +51,11 @@ def test_get_new_command(command, new_command):
(Command('vim'), 'sudo apt-get install vim && vim',
[('vim', 'main'), ('vim-tiny', 'main')]),
(Command('convert'), 'sudo apt-get install imagemagick && convert',
[('imagemagick', 'main'),
('graphicsmagick-imagemagick-compat', 'universe')]),
(Command('sudo vim'), 'sudo apt-get install vim && sudo vim',
[('vim', 'main'), ('vim-tiny', 'main')]),
(Command('sudo convert'), 'sudo apt-get install imagemagick && sudo convert',
[('imagemagick', 'main'),
('graphicsmagick-imagemagick-compat', 'universe')])])
@patch('thefuck.rules.apt_get.CommandNotFound', create=True)
@ -55,5 +64,3 @@ def test_get_new_command_mocked(cmdnf_mock, command, new_command, return_value):
get_packages = Mock(return_value=return_value)
cmdnf_mock.CommandNotFound.return_value = Mock(getPackages=get_packages)
assert get_new_command(command, None) == new_command
assert cmdnf_mock.CommandNotFound.called
assert get_packages.called

View File

@ -7,6 +7,7 @@ from tests.utils import Command
pacman_cmd = getattr(pacman, 'pacman', 'pacman')
PKGFILE_OUTPUT_SUDO = 'core/sudo 1.8.13-13/usr/bin/sudo'
PKGFILE_OUTPUT_CONVERT = 'extra/imagemagick 6.9.1.0-1\t/usr/bin/convert'
PKGFILE_OUTPUT_VIM = '''extra/gvim 7.4.712-1 \t/usr/bin/vim
@ -28,7 +29,7 @@ def test_match(command):
@pytest.mark.parametrize('command, return_value', [
(Command(script='vim', stderr='vim: command not found'), PKGFILE_OUTPUT_VIM),
(Command(script='sudo vim', stderr='sudo: vim: command not found'), PKGFILE_OUTPUT_VIM)])
@patch('thefuck.rules.pacman.subprocess')
@patch('thefuck.archlinux.subprocess')
@patch.multiple(pacman, create=True, pacman=pacman_cmd)
def test_match_mocked(subp_mock, command, return_value):
subp_mock.check_output.return_value = return_value
@ -72,8 +73,9 @@ def test_get_new_command(command, new_command, mocker):
(Command('vim'), vim_possibilities, PKGFILE_OUTPUT_VIM),
(Command('sudo vim'), sudo_vim_possibilities, PKGFILE_OUTPUT_VIM),
(Command('convert'), ['{} -S extra/imagemagick && convert'.format(pacman_cmd)], PKGFILE_OUTPUT_CONVERT),
(Command('sudo'), ['{} -S core/sudo && sudo'.format(pacman_cmd)], PKGFILE_OUTPUT_SUDO),
(Command('sudo convert'), ['{} -S extra/imagemagick && sudo convert'.format(pacman_cmd)], PKGFILE_OUTPUT_CONVERT)])
@patch('thefuck.rules.pacman.subprocess')
@patch('thefuck.archlinux.subprocess')
@patch.multiple(pacman, create=True, pacman=pacman_cmd)
def test_get_new_command_mocked(subp_mock, command, new_command, return_value):
subp_mock.check_output.return_value = return_value

View File

@ -0,0 +1,48 @@
import pytest
from mock import patch
from thefuck.rules import pacman_not_found
from thefuck.rules.pacman_not_found import match, get_new_command
from tests.utils import Command
PKGFILE_OUTPUT_LLC = '''extra/llvm 3.6.0-5 /usr/bin/llc
extra/llvm35 3.5.2-13/usr/bin/llc'''
@pytest.mark.skipif(not getattr(pacman_not_found, 'enabled_by_default', True),
reason='Skip if pacman is not available')
@pytest.mark.parametrize('command', [
Command(script='yaourt -S llc', stderr='error: target not found: llc'),
Command(script='pacman llc', stderr='error: target not found: llc'),
Command(script='sudo pacman llc', stderr='error: target not found: llc')])
def test_match(command):
assert match(command, None)
@pytest.mark.parametrize('command', [
Command(script='yaourt -S llc', stderr='error: target not found: llc'),
Command(script='pacman llc', stderr='error: target not found: llc'),
Command(script='sudo pacman llc', stderr='error: target not found: llc')])
@patch('thefuck.archlinux.subprocess')
def test_match_mocked(subp_mock, command):
subp_mock.check_output.return_value = PKGFILE_OUTPUT_LLC
assert match(command, None)
@pytest.mark.skipif(not getattr(pacman_not_found, 'enabled_by_default', True),
reason='Skip if pacman is not available')
@pytest.mark.parametrize('command, fixed', [
(Command(script='yaourt -S llc', stderr='error: target not found: llc'), ['yaourt -S extra/llvm', 'yaourt -S extra/llvm35']),
(Command(script='pacman -S llc', stderr='error: target not found: llc'), ['pacman -S extra/llvm', 'pacman -S extra/llvm35']),
(Command(script='sudo pacman -S llc', stderr='error: target not found: llc'), ['sudo pacman -S extra/llvm', 'sudo pacman -S extra/llvm35'])])
def test_get_new_command(command, fixed):
assert get_new_command(command, None) == fixed
@pytest.mark.parametrize('command, fixed', [
(Command(script='yaourt -S llc', stderr='error: target not found: llc'), ['yaourt -S extra/llvm', 'yaourt -S extra/llvm35']),
(Command(script='pacman -S llc', stderr='error: target not found: llc'), ['pacman -S extra/llvm', 'pacman -S extra/llvm35']),
(Command(script='sudo pacman -S llc', stderr='error: target not found: llc'), ['sudo pacman -S extra/llvm', 'sudo pacman -S extra/llvm35'])])
@patch('thefuck.archlinux.subprocess')
def test_get_new_command_mocked(subp_mock, command, fixed):
subp_mock.check_output.return_value = PKGFILE_OUTPUT_LLC
assert get_new_command(command, None) == fixed

41
thefuck/archlinux.py Normal file
View File

@ -0,0 +1,41 @@
""" This file provide some utility functions for Arch Linux specific rules."""
import thefuck.utils
import subprocess
@thefuck.utils.memoize
def get_pkgfile(command):
""" Gets the packages that provide the given command using `pkgfile`.
If the command is of the form `sudo foo`, searches for the `foo` command
instead.
"""
try:
command = command.strip()
if command.startswith('sudo '):
command = command[5:]
command = command.split(" ")[0]
packages = subprocess.check_output(
['pkgfile', '-b', '-v', command],
universal_newlines=True, stderr=thefuck.utils.DEVNULL
).splitlines()
return [package.split()[0] for package in packages]
except subprocess.CalledProcessError:
return None
def archlinux_env():
if thefuck.utils.which('yaourt'):
pacman = 'yaourt'
elif thefuck.utils.which('pacman'):
pacman = 'sudo pacman'
else:
return False, None
enabled_by_default = thefuck.utils.which('pkgfile')
return enabled_by_default, pacman

View File

@ -1,27 +1,30 @@
from thefuck import shells
from thefuck.utils import sudo_support
from thefuck.utils import memoize
try:
import CommandNotFound
except ImportError:
enabled_by_default = False
@sudo_support
def match(command, settings):
if 'not found' in command.stderr:
try:
c = CommandNotFound.CommandNotFound()
pkgs = c.getPackages(command.script.split(" ")[0])
name, _ = pkgs[0]
return True
except IndexError:
# IndexError is thrown when no matching package is found
return False
@sudo_support
@memoize
def get_package(command):
try:
c = CommandNotFound.CommandNotFound()
cmd = command.split(' ')
pkgs = c.getPackages(cmd[0] if cmd[0] != 'sudo' else cmd[1])
name, _ = pkgs[0]
return name
except IndexError:
# IndexError is thrown when no matching package is found
return None
def match(command, settings):
return 'not found' in command.stderr and get_package(command.script)
def get_new_command(command, settings):
c = CommandNotFound.CommandNotFound()
pkgs = c.getPackages(command.script.split(" ")[0])
name, _ = pkgs[0]
name = get_package(command.script)
formatme = shells.and_('sudo apt-get install {}', '{}')
return formatme.format(name, command.script)

View File

@ -1,46 +1,16 @@
import subprocess
from thefuck.utils import DEVNULL, which
from thefuck.archlinux import archlinux_env, get_pkgfile
from thefuck import shells
from thefuck.utils import memoize
@memoize
def __get_pkgfile(command):
try:
command = command.script
if command.startswith('sudo'):
command = command[5:]
command = command.split(" ")[0]
packages = subprocess.check_output(
['pkgfile', '-b', '-v', command],
universal_newlines=True, stderr=DEVNULL
).splitlines()
return [package.split()[0] for package in packages]
except subprocess.CalledProcessError:
return None
def match(command, settings):
return 'not found' in command.stderr and __get_pkgfile(command)
return 'not found' in command.stderr and get_pkgfile(command.script)
def get_new_command(command, settings):
packages = __get_pkgfile(command)
packages = get_pkgfile(command.script)
formatme = shells.and_('{} -S {}', '{}')
return [formatme.format(pacman, package, command.script)
for package in packages]
if not which('pkgfile'):
enabled_by_default = False
elif which('yaourt'):
pacman = 'yaourt'
elif which('pacman'):
pacman = 'sudo pacman'
else:
enabled_by_default = False
enabled_by_default, pacman = archlinux_env()

View File

@ -0,0 +1,24 @@
""" Fixes wrong package names with pacman or yaourt.
For example the `llc` program is in package `llvm` so this:
yaourt -S llc
should be:
yaourt -S llvm
"""
from thefuck.utils import replace_command
from thefuck.archlinux import archlinux_env, get_pkgfile
def match(command, settings):
return (command.script.startswith(('pacman', 'sudo pacman', 'yaourt'))
and 'error: target not found:' in command.stderr)
def get_new_command(command, settings):
pgr = command.script.split()[-1]
return replace_command(command, pgr, get_pkgfile(pgr))
enabled_by_default, _ = archlinux_env()

View File

@ -1,3 +1,4 @@
from .types import Command
from difflib import get_close_matches
from functools import wraps
from pathlib import Path
@ -6,7 +7,6 @@ import os
import pickle
import re
import six
from .types import Command
DEVNULL = open(os.devnull, 'w')