mirror of
				https://github.com/nvbn/thefuck.git
				synced 2025-11-04 09:02:08 +00:00 
			
		
		
		
	Compare commits
	
		
			58 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					d3a05426de | ||
| 
						 | 
					88db57b4b1 | ||
| 
						 | 
					444908ce1c | ||
| 
						 | 
					2ced7a7f33 | ||
| 
						 | 
					b28ece0f34 | ||
| 
						 | 
					eb60900330 | ||
| 
						 | 
					ed8aaa7f26 | ||
| 
						 | 
					77992029b6 | ||
| 
						 | 
					25c858c13e | ||
| 
						 | 
					60073bea78 | ||
| 
						 | 
					d10fc80fa5 | ||
| 
						 | 
					fdea32b47d | ||
| 
						 | 
					9381cfefa5 | ||
| 
						 | 
					793510ad48 | ||
| 
						 | 
					d85099b8da | ||
| 
						 | 
					ecee70f774 | ||
| 
						 | 
					70b414aca2 | ||
| 
						 | 
					80cfd6991d | ||
| 
						 | 
					0ccb34bde8 | ||
| 
						 | 
					581a292797 | ||
| 
						 | 
					7a9d87f502 | ||
| 
						 | 
					4f165bf6df | ||
| 
						 | 
					6789701e23 | ||
| 
						 | 
					64dd018c1a | ||
| 
						 | 
					3bbd0e9463 | ||
| 
						 | 
					c53676e42f | ||
| 
						 | 
					84c16fb69a | ||
| 
						 | 
					1683f45e94 | ||
| 
						 | 
					d88454a638 | ||
| 
						 | 
					8ef9634492 | ||
| 
						 | 
					335ae40675 | ||
| 
						 | 
					3bbe391391 | ||
| 
						 | 
					01a5ba99d0 | ||
| 
						 | 
					4c3a559124 | ||
| 
						 | 
					e047c1eb40 | ||
| 
						 | 
					48e1e4217f | ||
| 
						 | 
					59dc6cbf90 | ||
| 
						 | 
					59e1f7b122 | ||
| 
						 | 
					ff2944086d | ||
| 
						 | 
					ba949f7fd9 | ||
| 
						 | 
					5efcf1019f | ||
| 
						 | 
					70a13406f0 | ||
| 
						 | 
					201c01fc74 | ||
| 
						 | 
					78ef9eec88 | ||
| 
						 | 
					40ab4eb62d | ||
| 
						 | 
					55cb3546df | ||
| 
						 | 
					82902fb50d | ||
| 
						 | 
					828ae537da | ||
| 
						 | 
					1208faaabb | ||
| 
						 | 
					2d81166213 | ||
| 
						 | 
					8093f7cab8 | ||
| 
						 | 
					b946b7d319 | ||
| 
						 | 
					9354a977dd | ||
| 
						 | 
					1eb4ccbcc9 | ||
| 
						 | 
					ce5feaebf7 | ||
| 
						 | 
					ac343fb1bd | ||
| 
						 | 
					7bc619385b | ||
| 
						 | 
					d86dd5f179 | 
							
								
								
									
										11
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
root = true
 | 
			
		||||
 | 
			
		||||
[*]
 | 
			
		||||
charset = utf-8
 | 
			
		||||
end_of_line = lf
 | 
			
		||||
insert_final_newline = true
 | 
			
		||||
indent_style = space
 | 
			
		||||
indent_size = 4
 | 
			
		||||
 | 
			
		||||
[*.py]
 | 
			
		||||
max_line_length = 119
 | 
			
		||||
							
								
								
									
										45
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								.travis.yml
									
									
									
									
									
								
							@@ -1,34 +1,18 @@
 | 
			
		||||
language: python
 | 
			
		||||
sudo: false
 | 
			
		||||
os: linux
 | 
			
		||||
dist: xenial
 | 
			
		||||
matrix:
 | 
			
		||||
  include:
 | 
			
		||||
    - os: linux
 | 
			
		||||
      dist: xenial
 | 
			
		||||
      python: "nightly"
 | 
			
		||||
    - os: linux
 | 
			
		||||
      dist: xenial
 | 
			
		||||
      python: "3.8-dev"
 | 
			
		||||
    - os: linux
 | 
			
		||||
      dist: xenial
 | 
			
		||||
      python: "3.7-dev"
 | 
			
		||||
    - os: linux
 | 
			
		||||
      dist: xenial
 | 
			
		||||
      python: "3.7"
 | 
			
		||||
    - os: linux
 | 
			
		||||
      dist: trusty
 | 
			
		||||
      python: "3.6-dev"
 | 
			
		||||
    - os: linux
 | 
			
		||||
      dist: trusty
 | 
			
		||||
      python: "3.6"
 | 
			
		||||
    - os: linux
 | 
			
		||||
      dist: trusty
 | 
			
		||||
      python: "3.5"
 | 
			
		||||
    - os: linux
 | 
			
		||||
      dist: trusty
 | 
			
		||||
      python: "3.4"
 | 
			
		||||
    - os: linux
 | 
			
		||||
      dist: trusty
 | 
			
		||||
      python: "2.7"
 | 
			
		||||
    - python: "nightly"
 | 
			
		||||
    - python: "3.8-dev"
 | 
			
		||||
    - python: "3.8"
 | 
			
		||||
    - python: "3.7-dev"
 | 
			
		||||
    - python: "3.7"
 | 
			
		||||
    - python: "3.6-dev"
 | 
			
		||||
    - python: "3.6"
 | 
			
		||||
    - python: "3.5"
 | 
			
		||||
    - python: "2.7"
 | 
			
		||||
    - os: osx
 | 
			
		||||
      language: generic
 | 
			
		||||
  allow_failures:
 | 
			
		||||
@@ -46,6 +30,7 @@ addons:
 | 
			
		||||
before_install:
 | 
			
		||||
  - if [[ $TRAVIS_OS_NAME == "osx" ]]; then rm -rf /usr/local/include/c++; fi
 | 
			
		||||
  - if [[ $TRAVIS_OS_NAME == "osx" ]]; then brew update; fi
 | 
			
		||||
  - if [[ $TRAVIS_OS_NAME == "osx" ]]; then brew unlink python@2; fi
 | 
			
		||||
  - if [[ $TRAVIS_OS_NAME == "osx" ]]; then brew upgrade python; fi
 | 
			
		||||
  - if [[ $TRAVIS_OS_NAME == "osx" ]]; then pip3 install virtualenv; fi
 | 
			
		||||
  - if [[ $TRAVIS_OS_NAME == "osx" ]]; then virtualenv venv -p python3; fi
 | 
			
		||||
@@ -60,7 +45,7 @@ script:
 | 
			
		||||
  - flake8
 | 
			
		||||
  - export COVERAGE_PYTHON_VERSION=python-${TRAVIS_PYTHON_VERSION:0:1}
 | 
			
		||||
  - export RUN_TESTS="coverage run --source=thefuck,tests -m py.test -v --capture=sys tests"
 | 
			
		||||
  - if [[ $TRAVIS_PYTHON_VERSION == 3.7 && $TRAVIS_OS_NAME != "osx" ]]; then $RUN_TESTS --enable-functional; fi
 | 
			
		||||
  - if [[ $TRAVIS_PYTHON_VERSION != 3.7 || $TRAVIS_OS_NAME == "osx" ]]; then $RUN_TESTS; fi
 | 
			
		||||
  - if [[ $TRAVIS_PYTHON_VERSION == 3.8 && $TRAVIS_OS_NAME != "osx" ]]; then $RUN_TESTS --enable-functional; fi
 | 
			
		||||
  - if [[ $TRAVIS_PYTHON_VERSION != 3.8 || $TRAVIS_OS_NAME == "osx" ]]; then $RUN_TESTS; fi
 | 
			
		||||
after_success:
 | 
			
		||||
  - if [[ $TRAVIS_PYTHON_VERSION == 3.7 && $TRAVIS_OS_NAME != "osx" ]]; then coveralls; fi
 | 
			
		||||
  - if [[ $TRAVIS_PYTHON_VERSION == 3.8 && $TRAVIS_OS_NAME != "osx" ]]; then coveralls; fi
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,8 @@ fixes, etc.
 | 
			
		||||
 | 
			
		||||
# Developing
 | 
			
		||||
 | 
			
		||||
[Create and activate a Python 3 virtual environment.](https://docs.python.org/3/tutorial/venv.html)
 | 
			
		||||
 | 
			
		||||
Install `The Fuck` for development:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										35
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								README.md
									
									
									
									
									
								
							@@ -99,7 +99,7 @@ Reading package lists... Done
 | 
			
		||||
 | 
			
		||||
## Installation
 | 
			
		||||
 | 
			
		||||
On OS X, you can install *The Fuck* via [Homebrew][homebrew]:
 | 
			
		||||
On OS X, you can install *The Fuck* via [Homebrew][homebrew] (or via [Linuxbrew][linuxbrew] on Linux):
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
brew install thefuck
 | 
			
		||||
@@ -114,8 +114,7 @@ sudo pip3 install thefuck
 | 
			
		||||
 | 
			
		||||
On FreeBSD, install *The Fuck* with the following commands:
 | 
			
		||||
```bash
 | 
			
		||||
sudo portsnap fetch update
 | 
			
		||||
cd /usr/ports/misc/thefuck && sudo make install clean
 | 
			
		||||
pkg install thefuck
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
On ChromeOS, install *The Fuck* using [chromebrew](https://github.com/skycocker/chromebrew) with the following command:
 | 
			
		||||
@@ -146,7 +145,7 @@ eval $(thefuck --alias FUCK)
 | 
			
		||||
Changes are only available in a new shell session. To make changes immediately
 | 
			
		||||
available, run `source ~/.bashrc` (or your shell config file like `.zshrc`).
 | 
			
		||||
 | 
			
		||||
To run fixed commands without confirmation, use the `--yeah` option (or just `-y` for short):
 | 
			
		||||
To run fixed commands without confirmation, use the `--yeah` option (or just `-y` for short, or `--hard` if you're especially frustrated):
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
fuck --yeah
 | 
			
		||||
@@ -183,14 +182,18 @@ following rules are enabled by default:
 | 
			
		||||
* `cd_mkdir` – creates directories before cd'ing into them;
 | 
			
		||||
* `cd_parent` – changes `cd..` to `cd ..`;
 | 
			
		||||
* `chmod_x` – add execution bit;
 | 
			
		||||
* `choco_install` – append common suffixes for chocolatey packages;
 | 
			
		||||
* `composer_not_command` – fixes composer command name;
 | 
			
		||||
* `cp_create_destination` – creates a new directory when you attempt to `cp` or `mv` to a non existent one
 | 
			
		||||
* `cp_omitting_directory` – adds `-a` when you `cp` directory;
 | 
			
		||||
* `cpp11` – adds missing `-std=c++11` to `g++` or `clang++`;
 | 
			
		||||
* `dirty_untar` – fixes `tar x` command that untarred in the current directory;
 | 
			
		||||
* `dirty_unzip` – fixes `unzip` command that unzipped in the current directory;
 | 
			
		||||
* `django_south_ghost` – adds `--delete-ghost-migrations` to failed because ghosts django south migration;
 | 
			
		||||
* `django_south_merge` – adds `--merge` to inconsistent django south migration;
 | 
			
		||||
* `docker_login` – executes a `docker login` and repeats the previous command;
 | 
			
		||||
* `docker_not_command` – fixes wrong docker commands like `docker tags`;
 | 
			
		||||
* `docker_image_being_used_by_container` ‐ removes the container that is using the image before removing the image;
 | 
			
		||||
* `dry` – fixes repetitions like `git git push`;
 | 
			
		||||
* `fab_command_not_found` – fix misspelled fabric commands;
 | 
			
		||||
* `fix_alt_space` – replaces Alt+Space with Space character;
 | 
			
		||||
@@ -200,10 +203,12 @@ following rules are enabled by default:
 | 
			
		||||
* `git_add_force` – adds `--force` to `git add <pathspec>...` when paths are .gitignore'd;
 | 
			
		||||
* `git_bisect_usage` – fixes `git bisect strt`, `git bisect goood`, `git bisect rset`, etc. when bisecting;
 | 
			
		||||
* `git_branch_delete` – changes `git branch -d` to `git branch -D`;
 | 
			
		||||
* `git_branch_delete_checked_out` – changes `git branch -d` to `git checkout master && git branch -D` when trying to delete a checked out branch;
 | 
			
		||||
* `git_branch_exists` – offers `git branch -d foo`, `git branch -D foo` or `git checkout foo` when creating a branch that already exists;
 | 
			
		||||
* `git_branch_list` – catches `git branch list` in place of `git branch` and removes created branch;
 | 
			
		||||
* `git_checkout` – fixes branch name or creates new branch;
 | 
			
		||||
* `git_commit_amend` – offers `git commit --amend` after previous commit;
 | 
			
		||||
* `git_commit_reset` – offers `git reset HEAD~` after previous commit;
 | 
			
		||||
* `git_diff_no_index` – adds `--no-index` to previous `git diff` on untracked files;
 | 
			
		||||
* `git_diff_staged` – adds `--staged` to previous `git diff` with unexpected output;
 | 
			
		||||
* `git_fix_stash` – fixes `git stash` commands (misspelled subcommand and missing `save`);
 | 
			
		||||
@@ -225,12 +230,13 @@ following rules are enabled by default:
 | 
			
		||||
* `git_rm_recursive` – adds `-r` when you try to `rm` a directory;
 | 
			
		||||
* `git_rm_staged` –  adds `-f` or `--cached` when you try to `rm` a file with staged changes
 | 
			
		||||
* `git_rebase_merge_dir` – offers `git rebase (--continue | --abort | --skip)` or removing the `.git/rebase-merge` dir when a rebase is in progress;
 | 
			
		||||
* `git_remote_seturl_add` – runs `git remote add` when `git remote set_url` on nonexistant remote;
 | 
			
		||||
* `git_remote_seturl_add` – runs `git remote add` when `git remote set_url` on nonexistent remote;
 | 
			
		||||
* `git_stash` – stashes your local modifications before rebasing or switching branch;
 | 
			
		||||
* `git_stash_pop` – adds your local modifications before popping stash, then resets;
 | 
			
		||||
* `git_tag_force` – adds `--force` to `git tag <tagname>` when the tag already exists;
 | 
			
		||||
* `git_two_dashes` – adds a missing dash to commands like `git commit -amend` or `git rebase -continue`;
 | 
			
		||||
* `go_run` – appends `.go` extension when compiling/running Go programs;
 | 
			
		||||
* `go_unknown_command` – fixes wrong `go` commands, for example `go bulid`;
 | 
			
		||||
* `gradle_no_task` – fixes not found or ambiguous `gradle` task;
 | 
			
		||||
* `gradle_wrapper` – replaces `gradle` with `./gradlew`;
 | 
			
		||||
* `grep_arguments_order` – fixes `grep` arguments order for situations like `grep -lir . test`;
 | 
			
		||||
@@ -257,23 +263,26 @@ following rules are enabled by default:
 | 
			
		||||
* `missing_space_before_subcommand` – fixes command with missing space like `npminstall`;
 | 
			
		||||
* `mkdir_p` – adds `-p` when you try to create a directory without parent;
 | 
			
		||||
* `mvn_no_command` – adds `clean package` to `mvn`;
 | 
			
		||||
* `mvn_unknown_lifecycle_phase` – fixes misspelled lifecycle phases with `mvn`;
 | 
			
		||||
* `mvn_unknown_lifecycle_phase` – fixes misspelled life cycle phases with `mvn`;
 | 
			
		||||
* `npm_missing_script` – fixes `npm` custom script name in `npm run-script <script>`;
 | 
			
		||||
* `npm_run_script` – adds missing `run-script` for custom `npm` scripts;
 | 
			
		||||
* `npm_wrong_command` – fixes wrong npm commands like `npm urgrade`;
 | 
			
		||||
* `no_command` – fixes wrong console commands, for example `vom/vim`;
 | 
			
		||||
* `no_such_file` – creates missing directories with `mv` and `cp` commands;
 | 
			
		||||
* `open` – either prepends `http://` to address passed to `open` or create a new file or directory and passes it to `open`;
 | 
			
		||||
* `pip_install` – fixes permission issues with `pip install` commands by adding `--user` or prepending `sudo` if necessary;
 | 
			
		||||
* `pip_unknown_command` – fixes wrong `pip` commands, for example `pip instatl/pip install`;
 | 
			
		||||
* `php_s` – replaces `-s` by `-S` when trying to run a local php server;
 | 
			
		||||
* `port_already_in_use` – kills process that bound port;
 | 
			
		||||
* `prove_recursively` – adds `-r` when called with directory;
 | 
			
		||||
* `pyenv_no_such_command` – fixes wrong pyenv commands like `pyenv isntall` or `pyenv list`;
 | 
			
		||||
* `python_command` – prepends `python` when you try to run non-executable/without `./` python script;
 | 
			
		||||
* `python_execute` – appends missing `.py` when executing Python files;
 | 
			
		||||
* `quotation_marks` – fixes uneven usage of `'` and `"` when containing args';
 | 
			
		||||
* `path_from_history` – replaces not found path with similar absolute path from history;
 | 
			
		||||
* `react_native_command_unrecognized` – fixes unrecognized `react-native` commands;
 | 
			
		||||
* `remove_trailing_cedilla` – remove trailling cedillas `ç`, a common typo for european keyboard layouts;
 | 
			
		||||
* `remove_shell_prompt_literal` – remove leading shell prompt symbol `$`, common when copying commands from documentations;
 | 
			
		||||
* `remove_trailing_cedilla` – remove trailing cedillas `ç`, a common typo for european keyboard layouts;
 | 
			
		||||
* `rm_dir` – adds `-rf` when you try to remove a directory;
 | 
			
		||||
* `scm_correction` – corrects wrong scm like `hg log` to `git log`;
 | 
			
		||||
* `sed_unterminated_s` – adds missing '/' to `sed`'s `s` commands;
 | 
			
		||||
@@ -283,6 +292,7 @@ following rules are enabled by default:
 | 
			
		||||
* `sudo_command_from_user_path` – runs commands from users `$PATH` with `sudo`;
 | 
			
		||||
* `switch_lang` – switches command from your local layout to en;
 | 
			
		||||
* `systemctl` – correctly orders parameters of confusing `systemctl`;
 | 
			
		||||
* `terraform_init.py` – run `terraform init` before plan or apply;
 | 
			
		||||
* `test.py` – runs `py.test` instead of `test.py`;
 | 
			
		||||
* `touch` – creates missing directories before "touching";
 | 
			
		||||
* `tsuru_login` – runs `tsuru login` if not authenticated or session expired;
 | 
			
		||||
@@ -313,8 +323,10 @@ The following rules are enabled by default on specific platforms only:
 | 
			
		||||
* `brew_unknown_command` – fixes wrong brew commands, for example `brew docto/brew doctor`;
 | 
			
		||||
* `brew_update_formula` – turns `brew update <formula>` into `brew upgrade <formula>`;
 | 
			
		||||
* `dnf_no_such_command` – fixes mistyped DNF commands;
 | 
			
		||||
* `pacman` – installs app with `pacman` if it is not installed (uses `yaourt` if available);
 | 
			
		||||
* `pacman_not_found` – fixes package name with `pacman` or `yaourt`.
 | 
			
		||||
* `nixos_cmd_not_found` – installs apps on NixOS;
 | 
			
		||||
* `pacman` – installs app with `pacman` if it is not installed (uses `yay` or `yaourt` if available);
 | 
			
		||||
* `pacman_not_found` – fixes package name with `pacman`, `yay` or `yaourt`.
 | 
			
		||||
* `yum_invalid_operation` – fixes invalid `yum` calls, like `yum isntall vim`;
 | 
			
		||||
 | 
			
		||||
The following commands are bundled with *The Fuck*, but are not enabled by
 | 
			
		||||
default:
 | 
			
		||||
@@ -380,7 +392,7 @@ requires_output = True
 | 
			
		||||
Several *The Fuck* parameters can be changed in the file `$XDG_CONFIG_HOME/thefuck/settings.py`
 | 
			
		||||
(`$XDG_CONFIG_HOME` defaults to `~/.config`):
 | 
			
		||||
 | 
			
		||||
* `rules` – list of enabled rules, by default `thefuck.conf.DEFAULT_RULES`;
 | 
			
		||||
* `rules` – list of enabled rules, by default `thefuck.const.DEFAULT_RULES`;
 | 
			
		||||
* `exclude_rules` – list of disabled rules, by default `[]`;
 | 
			
		||||
* `require_confirmation` – requires confirmation before running new command, by default `True`;
 | 
			
		||||
* `wait_command` – max amount of time in seconds for getting previous command output;
 | 
			
		||||
@@ -495,4 +507,5 @@ Project License can be found [here](LICENSE.md).
 | 
			
		||||
[license-badge]:   https://img.shields.io/badge/license-MIT-007EC7.svg
 | 
			
		||||
[examples-link]:   https://raw.githubusercontent.com/nvbn/thefuck/master/example.gif
 | 
			
		||||
[instant-mode-gif-link]:   https://raw.githubusercontent.com/nvbn/thefuck/master/example_instant_mode.gif
 | 
			
		||||
[homebrew]:        http://brew.sh/
 | 
			
		||||
[homebrew]:        https://brew.sh/
 | 
			
		||||
[linuxbrew]:       https://linuxbrew.sh/
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,6 @@ build: false
 | 
			
		||||
environment:
 | 
			
		||||
  matrix:
 | 
			
		||||
    - PYTHON: "C:/Python27"
 | 
			
		||||
    - PYTHON: "C:/Python34"
 | 
			
		||||
    - PYTHON: "C:/Python35"
 | 
			
		||||
    - PYTHON: "C:/Python36"
 | 
			
		||||
    - PYTHON: "C:/Python37"
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,7 @@ http://github.com/ninjaaron/fast-entry_points
 | 
			
		||||
'''
 | 
			
		||||
from setuptools.command import easy_install
 | 
			
		||||
import re
 | 
			
		||||
TEMPLATE = '''\
 | 
			
		||||
TEMPLATE = r'''\
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
# EASY-INSTALL-ENTRY-SCRIPT: '{3}','{4}','{5}'
 | 
			
		||||
__requires__ = '{3}'
 | 
			
		||||
@@ -83,7 +83,7 @@ def main():
 | 
			
		||||
    import shutil
 | 
			
		||||
    import sys
 | 
			
		||||
    dests = sys.argv[1:] or ['.']
 | 
			
		||||
    filename = re.sub('\.pyc$', '.py', __file__)
 | 
			
		||||
    filename = re.sub(r'\.pyc$', '.py', __file__)
 | 
			
		||||
 | 
			
		||||
    for dst in dests:
 | 
			
		||||
        shutil.copy(filename, dst)
 | 
			
		||||
 
 | 
			
		||||
@@ -32,5 +32,6 @@ call('git push --tags', shell=True)
 | 
			
		||||
 | 
			
		||||
env = os.environ
 | 
			
		||||
env['CONVERT_README'] = 'true'
 | 
			
		||||
call('rm -rf dist/*', shell=True, env=env)
 | 
			
		||||
call('python setup.py sdist bdist_wheel', shell=True, env=env)
 | 
			
		||||
call('twine upload dist/*', shell=True, env=env)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								setup.py
									
									
									
									
									
								
							@@ -26,12 +26,12 @@ if version < (2, 7):
 | 
			
		||||
    print('thefuck requires Python version 2.7 or later' +
 | 
			
		||||
          ' ({}.{} detected).'.format(*version))
 | 
			
		||||
    sys.exit(-1)
 | 
			
		||||
elif (3, 0) < version < (3, 4):
 | 
			
		||||
    print('thefuck requires Python version 3.4 or later' +
 | 
			
		||||
elif (3, 0) < version < (3, 5):
 | 
			
		||||
    print('thefuck requires Python version 3.5 or later' +
 | 
			
		||||
          ' ({}.{} detected).'.format(*version))
 | 
			
		||||
    sys.exit(-1)
 | 
			
		||||
 | 
			
		||||
VERSION = '3.28'
 | 
			
		||||
VERSION = '3.30'
 | 
			
		||||
 | 
			
		||||
install_requires = ['psutil', 'colorama', 'six', 'decorator', 'pyte']
 | 
			
		||||
extras_require = {':python_version<"3.4"': ['pathlib2'],
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,7 @@ def no_cache(monkeypatch):
 | 
			
		||||
 | 
			
		||||
@pytest.fixture(autouse=True)
 | 
			
		||||
def functional(request):
 | 
			
		||||
    if request.node.get_marker('functional') \
 | 
			
		||||
    if request.node.get_closest_marker('functional') \
 | 
			
		||||
            and not request.config.getoption('enable_functional'):
 | 
			
		||||
        pytest.skip('functional tests are disabled')
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -76,6 +76,45 @@ apt_get_operations = ['update', 'upgrade', 'install', 'remove', 'autoremove',
 | 
			
		||||
                      'dselect-upgrade', 'clean', 'autoclean', 'check',
 | 
			
		||||
                      'changelog', 'download']
 | 
			
		||||
 | 
			
		||||
new_apt_get_help = b'''apt 1.6.12 (amd64)
 | 
			
		||||
Usage: apt-get [options] command
 | 
			
		||||
       apt-get [options] install|remove pkg1 [pkg2 ...]
 | 
			
		||||
       apt-get [options] source pkg1 [pkg2 ...]
 | 
			
		||||
 | 
			
		||||
apt-get is a command line interface for retrieval of packages
 | 
			
		||||
and information about them from authenticated sources and
 | 
			
		||||
for installation, upgrade and removal of packages together
 | 
			
		||||
with their dependencies.
 | 
			
		||||
 | 
			
		||||
Most used commands:
 | 
			
		||||
  update - Retrieve new lists of packages
 | 
			
		||||
  upgrade - Perform an upgrade
 | 
			
		||||
  install - Install new packages (pkg is libc6 not libc6.deb)
 | 
			
		||||
  remove - Remove packages
 | 
			
		||||
  purge - Remove packages and config files
 | 
			
		||||
  autoremove - Remove automatically all unused packages
 | 
			
		||||
  dist-upgrade - Distribution upgrade, see apt-get(8)
 | 
			
		||||
  dselect-upgrade - Follow dselect selections
 | 
			
		||||
  build-dep - Configure build-dependencies for source packages
 | 
			
		||||
  clean - Erase downloaded archive files
 | 
			
		||||
  autoclean - Erase old downloaded archive files
 | 
			
		||||
  check - Verify that there are no broken dependencies
 | 
			
		||||
  source - Download source archives
 | 
			
		||||
  download - Download the binary package into the current directory
 | 
			
		||||
  changelog - Download and display the changelog for the given package
 | 
			
		||||
 | 
			
		||||
See apt-get(8) for more information about the available commands.
 | 
			
		||||
Configuration options and syntax is detailed in apt.conf(5).
 | 
			
		||||
Information about how to configure sources can be found in sources.list(5).
 | 
			
		||||
Package and version choices can be expressed via apt_preferences(5).
 | 
			
		||||
Security details are available in apt-secure(8).
 | 
			
		||||
                                        This APT has Super Cow Powers.
 | 
			
		||||
'''
 | 
			
		||||
new_apt_get_operations = ['update', 'upgrade', 'install', 'remove', 'purge',
 | 
			
		||||
                          'autoremove', 'dist-upgrade', 'dselect-upgrade',
 | 
			
		||||
                          'build-dep', 'clean', 'autoclean', 'check',
 | 
			
		||||
                          'source', 'download', 'changelog']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('script, output', [
 | 
			
		||||
    ('apt', invalid_operation('saerch')),
 | 
			
		||||
@@ -104,7 +143,8 @@ def set_help(mocker):
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('app, help_text, operations', [
 | 
			
		||||
    ('apt', apt_help, apt_operations),
 | 
			
		||||
    ('apt-get', apt_get_help, apt_get_operations)
 | 
			
		||||
    ('apt-get', apt_get_help, apt_get_operations),
 | 
			
		||||
    ('apt-get', new_apt_get_help, new_apt_get_operations)
 | 
			
		||||
])
 | 
			
		||||
def test_get_operations(set_help, app, help_text, operations):
 | 
			
		||||
    set_help(help_text)
 | 
			
		||||
@@ -116,6 +156,8 @@ def test_get_operations(set_help, app, help_text, operations):
 | 
			
		||||
     apt_get_help, 'apt-get install vim'),
 | 
			
		||||
    ('apt saerch vim', invalid_operation('saerch'),
 | 
			
		||||
     apt_help, 'apt search vim'),
 | 
			
		||||
    ('apt uninstall vim', invalid_operation('uninstall'),
 | 
			
		||||
     apt_help, 'apt remove vim'),
 | 
			
		||||
])
 | 
			
		||||
def test_get_new_command(set_help, output, script, help_text, result):
 | 
			
		||||
    set_help(help_text)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,10 @@
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
import pytest
 | 
			
		||||
from thefuck.rules.apt_list_upgradable import get_new_command, match
 | 
			
		||||
from thefuck.types import Command
 | 
			
		||||
 | 
			
		||||
match_output = '''
 | 
			
		||||
full_english_output = '''
 | 
			
		||||
Hit:1 http://us.archive.ubuntu.com/ubuntu zesty InRelease
 | 
			
		||||
Hit:2 http://us.archive.ubuntu.com/ubuntu zesty-updates InRelease
 | 
			
		||||
Get:3 http://us.archive.ubuntu.com/ubuntu zesty-backports InRelease [89.2 kB]
 | 
			
		||||
@@ -17,6 +19,11 @@ Reading state information... Done
 | 
			
		||||
8 packages can be upgraded. Run 'apt list --upgradable' to see them.
 | 
			
		||||
'''
 | 
			
		||||
 | 
			
		||||
match_output = [
 | 
			
		||||
    full_english_output,
 | 
			
		||||
    'Führen Sie »apt list --upgradable« aus, um sie anzuzeigen.'  # German
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
no_match_output = '''
 | 
			
		||||
Hit:1 http://us.archive.ubuntu.com/ubuntu zesty InRelease
 | 
			
		||||
Get:2 http://us.archive.ubuntu.com/ubuntu zesty-updates InRelease [89.2 kB]
 | 
			
		||||
@@ -48,8 +55,9 @@ All packages are up to date.
 | 
			
		||||
'''
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_match():
 | 
			
		||||
    assert match(Command('sudo apt update', match_output))
 | 
			
		||||
@pytest.mark.parametrize('output', match_output)
 | 
			
		||||
def test_match(output):
 | 
			
		||||
    assert match(Command('sudo apt update', output))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('command', [
 | 
			
		||||
@@ -67,9 +75,10 @@ def test_not_match(command):
 | 
			
		||||
    assert not match(command)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_get_new_command():
 | 
			
		||||
    new_command = get_new_command(Command('sudo apt update', match_output))
 | 
			
		||||
@pytest.mark.parametrize('output', match_output)
 | 
			
		||||
def test_get_new_command(output):
 | 
			
		||||
    new_command = get_new_command(Command('sudo apt update', output))
 | 
			
		||||
    assert new_command == 'sudo apt list --upgradable'
 | 
			
		||||
 | 
			
		||||
    new_command = get_new_command(Command('apt update', match_output))
 | 
			
		||||
    new_command = get_new_command(Command('apt update', output))
 | 
			
		||||
    assert new_command == 'apt list --upgradable'
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										86
									
								
								tests/rules/test_choco_install.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								tests/rules/test_choco_install.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
			
		||||
import pytest
 | 
			
		||||
from thefuck.rules.choco_install import match, get_new_command
 | 
			
		||||
from thefuck.types import Command
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
package_not_found_error = (
 | 
			
		||||
    'Chocolatey v0.10.15\n'
 | 
			
		||||
    'Installing the following packages:\n'
 | 
			
		||||
    'logstitcher\n'
 | 
			
		||||
    'By installing you accept licenses for the packages.\n'
 | 
			
		||||
    'logstitcher not installed. The package was not found with the source(s) listed.\n'
 | 
			
		||||
    ' Source(s): \'https://chocolatey.org/api/v2/\'\n'
 | 
			
		||||
    ' NOTE: When you specify explicit sources, it overrides default sources.\n'
 | 
			
		||||
    'If the package version is a prerelease and you didn\'t specify `--pre`,\n'
 | 
			
		||||
    ' the package may not be found.\n'
 | 
			
		||||
    'Please see https://chocolatey.org/docs/troubleshooting for more\n'
 | 
			
		||||
    ' assistance.\n'
 | 
			
		||||
    '\n'
 | 
			
		||||
    'Chocolatey installed 0/1 packages. 1 packages failed.\n'
 | 
			
		||||
    ' See the log for details (C:\\ProgramData\\chocolatey\\logs\\chocolatey.log).\n'
 | 
			
		||||
    '\n'
 | 
			
		||||
    'Failures\n'
 | 
			
		||||
    ' - logstitcher - logstitcher not installed. The package was not found with the source(s) listed.\n'
 | 
			
		||||
    ' Source(s): \'https://chocolatey.org/api/v2/\'\n'
 | 
			
		||||
    ' NOTE: When you specify explicit sources, it overrides default sources.\n'
 | 
			
		||||
    'If the package version is a prerelease and you didn\'t specify `--pre`,\n'
 | 
			
		||||
    ' the package may not be found.\n'
 | 
			
		||||
    'Please see https://chocolatey.org/docs/troubleshooting for more\n'
 | 
			
		||||
    ' assistance.\n'
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('command', [
 | 
			
		||||
    Command('choco install logstitcher', package_not_found_error),
 | 
			
		||||
    Command('cinst logstitcher', package_not_found_error),
 | 
			
		||||
    Command('choco install logstitcher -y', package_not_found_error),
 | 
			
		||||
    Command('cinst logstitcher -y', package_not_found_error),
 | 
			
		||||
    Command('choco install logstitcher -y -n=test', package_not_found_error),
 | 
			
		||||
    Command('cinst logstitcher -y -n=test', package_not_found_error),
 | 
			
		||||
    Command('choco install logstitcher -y -n=test /env', package_not_found_error),
 | 
			
		||||
    Command('cinst logstitcher -y -n=test /env', package_not_found_error),
 | 
			
		||||
    Command('choco install chocolatey -y', package_not_found_error),
 | 
			
		||||
    Command('cinst chocolatey -y', package_not_found_error)])
 | 
			
		||||
def test_match(command):
 | 
			
		||||
    assert match(command)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('command', [
 | 
			
		||||
    Command('choco /?', ''),
 | 
			
		||||
    Command('choco upgrade logstitcher', ''),
 | 
			
		||||
    Command('cup logstitcher', ''),
 | 
			
		||||
    Command('choco upgrade logstitcher -y', ''),
 | 
			
		||||
    Command('cup logstitcher -y', ''),
 | 
			
		||||
    Command('choco upgrade logstitcher -y -n=test', ''),
 | 
			
		||||
    Command('cup logstitcher -y -n=test', ''),
 | 
			
		||||
    Command('choco upgrade logstitcher -y -n=test /env', ''),
 | 
			
		||||
    Command('cup logstitcher -y -n=test /env', ''),
 | 
			
		||||
    Command('choco upgrade chocolatey -y', ''),
 | 
			
		||||
    Command('cup chocolatey -y', ''),
 | 
			
		||||
    Command('choco uninstall logstitcher', ''),
 | 
			
		||||
    Command('cuninst logstitcher', ''),
 | 
			
		||||
    Command('choco uninstall logstitcher -y', ''),
 | 
			
		||||
    Command('cuninst logstitcher -y', ''),
 | 
			
		||||
    Command('choco uninstall logstitcher -y -n=test', ''),
 | 
			
		||||
    Command('cuninst logstitcher -y -n=test', ''),
 | 
			
		||||
    Command('choco uninstall logstitcher -y -n=test /env', ''),
 | 
			
		||||
    Command('cuninst logstitcher -y -n=test /env', ''),
 | 
			
		||||
    Command('choco uninstall chocolatey -y', ''),
 | 
			
		||||
    Command('cuninst chocolatey -y', '')])
 | 
			
		||||
def not_test_match(command):
 | 
			
		||||
    assert not match(command)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('before, after', [
 | 
			
		||||
    ('choco install logstitcher', 'choco install logstitcher.install'),
 | 
			
		||||
    ('cinst logstitcher', 'cinst logstitcher.install'),
 | 
			
		||||
    ('choco install logstitcher -y', 'choco install logstitcher.install -y'),
 | 
			
		||||
    ('cinst logstitcher -y', 'cinst logstitcher.install -y'),
 | 
			
		||||
    ('choco install logstitcher -y -n=test', 'choco install logstitcher.install -y -n=test'),
 | 
			
		||||
    ('cinst logstitcher -y -n=test', 'cinst logstitcher.install -y -n=test'),
 | 
			
		||||
    ('choco install logstitcher -y -n=test /env', 'choco install logstitcher.install -y -n=test /env'),
 | 
			
		||||
    ('cinst logstitcher -y -n=test /env', 'cinst logstitcher.install -y -n=test /env'),
 | 
			
		||||
    ('choco install chocolatey -y', 'choco install chocolatey.install -y'),
 | 
			
		||||
    ('cinst chocolatey -y', 'cinst chocolatey.install -y'), ])
 | 
			
		||||
def test_get_new_command(before, after):
 | 
			
		||||
    assert (get_new_command(Command(before, '')) == after)
 | 
			
		||||
							
								
								
									
										30
									
								
								tests/rules/test_cp_create_destination.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								tests/rules/test_cp_create_destination.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
import pytest
 | 
			
		||||
from thefuck.rules.cp_create_destination import match, get_new_command
 | 
			
		||||
from thefuck.types import Command
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize(
 | 
			
		||||
    "script, output",
 | 
			
		||||
    [("cp", "cp: directory foo does not exist\n"), ("mv", "No such file or directory")],
 | 
			
		||||
)
 | 
			
		||||
def test_match(script, output):
 | 
			
		||||
    assert match(Command(script, output))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize(
 | 
			
		||||
    "script, output", [("cp", ""), ("mv", ""), ("ls", "No such file or directory")]
 | 
			
		||||
)
 | 
			
		||||
def test_not_match(script, output):
 | 
			
		||||
    assert not match(Command(script, output))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize(
 | 
			
		||||
    "script, output, new_command",
 | 
			
		||||
    [
 | 
			
		||||
        ("cp foo bar/", "cp: directory foo does not exist\n", "mkdir -p bar/ && cp foo bar/"),
 | 
			
		||||
        ("mv foo bar/", "No such file or directory", "mkdir -p bar/ && mv foo bar/"),
 | 
			
		||||
        ("cp foo bar/baz/", "cp: directory foo does not exist\n", "mkdir -p bar/baz/ && cp foo bar/baz/"),
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
def test_get_new_command(script, output, new_command):
 | 
			
		||||
    assert get_new_command(Command(script, output)) == new_command
 | 
			
		||||
							
								
								
									
										27
									
								
								tests/rules/test_docker_image_being_used_by_container.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								tests/rules/test_docker_image_being_used_by_container.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
from thefuck.rules.docker_image_being_used_by_container import match, get_new_command
 | 
			
		||||
from thefuck.types import Command
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_match():
 | 
			
		||||
    err_response = """Error response from daemon: conflict: unable to delete cd809b04b6ff (cannot be forced) - image is being used by running container e5e2591040d1"""
 | 
			
		||||
    assert match(Command('docker image rm -f cd809b04b6ff', err_response))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_not_match():
 | 
			
		||||
    err_response = 'bash: docker: command not found'
 | 
			
		||||
    assert not match(Command('docker image rm -f cd809b04b6ff', err_response))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_not_docker_command():
 | 
			
		||||
    err_response = """Error response from daemon: conflict: unable to delete cd809b04b6ff (cannot be forced) - image is being used by running container e5e2591040d1"""
 | 
			
		||||
    assert not match(Command('git image rm -f cd809b04b6ff', err_response))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_get_new_command():
 | 
			
		||||
    err_response = """
 | 
			
		||||
        Error response from daemon: conflict: unable to delete cd809b04b6ff (cannot be forced) - image
 | 
			
		||||
        is being used by running container e5e2591040d1
 | 
			
		||||
        """
 | 
			
		||||
    result = get_new_command(Command('docker image rm -f cd809b04b6ff', err_response))
 | 
			
		||||
    expected = 'docker container rm -f e5e2591040d1 && docker image rm -f cd809b04b6ff'
 | 
			
		||||
    assert result == expected
 | 
			
		||||
							
								
								
									
										37
									
								
								tests/rules/test_docker_login.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								tests/rules/test_docker_login.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
from thefuck.rules.docker_login import match, get_new_command
 | 
			
		||||
from thefuck.types import Command
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_match():
 | 
			
		||||
    err_response1 = """
 | 
			
		||||
    Sending build context to Docker daemon  118.8kB
 | 
			
		||||
Step 1/6 : FROM foo/bar:fdb7c6d
 | 
			
		||||
pull access denied for foo/bar, repository does not exist or may require 'docker login'
 | 
			
		||||
"""
 | 
			
		||||
    assert match(Command('docker build -t artifactory:9090/foo/bar:fdb7c6d .', err_response1))
 | 
			
		||||
 | 
			
		||||
    err_response2 = """
 | 
			
		||||
    The push refers to repository [artifactory:9090/foo/bar]
 | 
			
		||||
push access denied for foo/bar, repository does not exist or may require 'docker login'
 | 
			
		||||
"""
 | 
			
		||||
    assert match(Command('docker push artifactory:9090/foo/bar:fdb7c6d', err_response2))
 | 
			
		||||
 | 
			
		||||
    err_response3 = """
 | 
			
		||||
    docker push artifactory:9090/foo/bar:fdb7c6d
 | 
			
		||||
The push refers to repository [artifactory:9090/foo/bar]
 | 
			
		||||
9c29c7ad209d: Preparing
 | 
			
		||||
71f3ad53dfe0: Preparing
 | 
			
		||||
f58ee068224c: Preparing
 | 
			
		||||
aeddc924d0f7: Preparing
 | 
			
		||||
c2040e5d6363: Preparing
 | 
			
		||||
4d42df4f350f: Preparing
 | 
			
		||||
35723dab26f9: Preparing
 | 
			
		||||
71f3ad53dfe0: Pushed
 | 
			
		||||
cb95fa0faeb1: Layer already exists
 | 
			
		||||
"""
 | 
			
		||||
    assert not match(Command('docker push artifactory:9090/foo/bar:fdb7c6d', err_response3))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_get_new_command():
 | 
			
		||||
    assert get_new_command(Command('docker build -t artifactory:9090/foo/bar:fdb7c6d .', '')) == 'docker login && docker build -t artifactory:9090/foo/bar:fdb7c6d .'
 | 
			
		||||
    assert get_new_command(Command('docker push artifactory:9090/foo/bar:fdb7c6d', '')) == 'docker login && docker push artifactory:9090/foo/bar:fdb7c6d'
 | 
			
		||||
@@ -4,6 +4,46 @@ from thefuck.types import Command
 | 
			
		||||
from thefuck.rules.docker_not_command import get_new_command, match
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
_DOCKER_SWARM_OUTPUT = '''
 | 
			
		||||
Usage:	docker swarm COMMAND
 | 
			
		||||
 | 
			
		||||
Manage Swarm
 | 
			
		||||
 | 
			
		||||
Commands:
 | 
			
		||||
  ca          Display and rotate the root CA
 | 
			
		||||
  init        Initialize a swarm
 | 
			
		||||
  join        Join a swarm as a node and/or manager
 | 
			
		||||
  join-token  Manage join tokens
 | 
			
		||||
  leave       Leave the swarm
 | 
			
		||||
  unlock      Unlock swarm
 | 
			
		||||
  unlock-key  Manage the unlock key
 | 
			
		||||
  update      Update the swarm
 | 
			
		||||
 | 
			
		||||
Run 'docker swarm COMMAND --help' for more information on a command.
 | 
			
		||||
'''
 | 
			
		||||
_DOCKER_IMAGE_OUTPUT = '''
 | 
			
		||||
Usage:	docker image COMMAND
 | 
			
		||||
 | 
			
		||||
Manage images
 | 
			
		||||
 | 
			
		||||
Commands:
 | 
			
		||||
  build       Build an image from a Dockerfile
 | 
			
		||||
  history     Show the history of an image
 | 
			
		||||
  import      Import the contents from a tarball to create a filesystem image
 | 
			
		||||
  inspect     Display detailed information on one or more images
 | 
			
		||||
  load        Load an image from a tar archive or STDIN
 | 
			
		||||
  ls          List images
 | 
			
		||||
  prune       Remove unused images
 | 
			
		||||
  pull        Pull an image or a repository from a registry
 | 
			
		||||
  push        Push an image or a repository to a registry
 | 
			
		||||
  rm          Remove one or more images
 | 
			
		||||
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
 | 
			
		||||
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
 | 
			
		||||
 | 
			
		||||
Run 'docker image COMMAND --help' for more information on a command.
 | 
			
		||||
'''
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def docker_help(mocker):
 | 
			
		||||
    help = b'''Usage: docker [OPTIONS] COMMAND [arg...]
 | 
			
		||||
@@ -104,6 +144,94 @@ Run 'docker COMMAND --help' for more information on a command.
 | 
			
		||||
    return mock
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def docker_help_new(mocker):
 | 
			
		||||
    helptext_new = b'''
 | 
			
		||||
Usage:	docker [OPTIONS] COMMAND
 | 
			
		||||
 | 
			
		||||
A self-sufficient runtime for containers
 | 
			
		||||
 | 
			
		||||
Options:
 | 
			
		||||
      --config string      Location of client config files (default "/Users/ik1ne/.docker")
 | 
			
		||||
  -c, --context string     Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var
 | 
			
		||||
                           and default context set with "docker context use")
 | 
			
		||||
  -D, --debug              Enable debug mode
 | 
			
		||||
  -H, --host list          Daemon socket(s) to connect to
 | 
			
		||||
  -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
 | 
			
		||||
      --tls                Use TLS; implied by --tlsverify
 | 
			
		||||
      --tlscacert string   Trust certs signed only by this CA (default "/Users/ik1ne/.docker/ca.pem")
 | 
			
		||||
      --tlscert string     Path to TLS certificate file (default "/Users/ik1ne/.docker/cert.pem")
 | 
			
		||||
      --tlskey string      Path to TLS key file (default "/Users/ik1ne/.docker/key.pem")
 | 
			
		||||
      --tlsverify          Use TLS and verify the remote
 | 
			
		||||
  -v, --version            Print version information and quit
 | 
			
		||||
 | 
			
		||||
Management Commands:
 | 
			
		||||
  builder     Manage builds
 | 
			
		||||
  config      Manage Docker configs
 | 
			
		||||
  container   Manage containers
 | 
			
		||||
  context     Manage contexts
 | 
			
		||||
  image       Manage images
 | 
			
		||||
  network     Manage networks
 | 
			
		||||
  node        Manage Swarm nodes
 | 
			
		||||
  plugin      Manage plugins
 | 
			
		||||
  secret      Manage Docker secrets
 | 
			
		||||
  service     Manage services
 | 
			
		||||
  stack       Manage Docker stacks
 | 
			
		||||
  swarm       Manage Swarm
 | 
			
		||||
  system      Manage Docker
 | 
			
		||||
  trust       Manage trust on Docker images
 | 
			
		||||
  volume      Manage volumes
 | 
			
		||||
 | 
			
		||||
Commands:
 | 
			
		||||
  attach      Attach local standard input, output, and error streams to a running container
 | 
			
		||||
  build       Build an image from a Dockerfile
 | 
			
		||||
  commit      Create a new image from a container's changes
 | 
			
		||||
  cp          Copy files/folders between a container and the local filesystem
 | 
			
		||||
  create      Create a new container
 | 
			
		||||
  diff        Inspect changes to files or directories on a container's filesystem
 | 
			
		||||
  events      Get real time events from the server
 | 
			
		||||
  exec        Run a command in a running container
 | 
			
		||||
  export      Export a container's filesystem as a tar archive
 | 
			
		||||
  history     Show the history of an image
 | 
			
		||||
  images      List images
 | 
			
		||||
  import      Import the contents from a tarball to create a filesystem image
 | 
			
		||||
  info        Display system-wide information
 | 
			
		||||
  inspect     Return low-level information on Docker objects
 | 
			
		||||
  kill        Kill one or more running containers
 | 
			
		||||
  load        Load an image from a tar archive or STDIN
 | 
			
		||||
  login       Log in to a Docker registry
 | 
			
		||||
  logout      Log out from a Docker registry
 | 
			
		||||
  logs        Fetch the logs of a container
 | 
			
		||||
  pause       Pause all processes within one or more containers
 | 
			
		||||
  port        List port mappings or a specific mapping for the container
 | 
			
		||||
  ps          List containers
 | 
			
		||||
  pull        Pull an image or a repository from a registry
 | 
			
		||||
  push        Push an image or a repository to a registry
 | 
			
		||||
  rename      Rename a container
 | 
			
		||||
  restart     Restart one or more containers
 | 
			
		||||
  rm          Remove one or more containers
 | 
			
		||||
  rmi         Remove one or more images
 | 
			
		||||
  run         Run a command in a new container
 | 
			
		||||
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
 | 
			
		||||
  search      Search the Docker Hub for images
 | 
			
		||||
  start       Start one or more stopped containers
 | 
			
		||||
  stats       Display a live stream of container(s) resource usage statistics
 | 
			
		||||
  stop        Stop one or more running containers
 | 
			
		||||
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
 | 
			
		||||
  top         Display the running processes of a container
 | 
			
		||||
  unpause     Unpause all processes within one or more containers
 | 
			
		||||
  update      Update configuration of one or more containers
 | 
			
		||||
  version     Show the Docker version information
 | 
			
		||||
  wait        Block until one or more containers stop, then print their exit codes
 | 
			
		||||
 | 
			
		||||
Run 'docker COMMAND --help' for more information on a command.
 | 
			
		||||
'''
 | 
			
		||||
    mock = mocker.patch('subprocess.Popen')
 | 
			
		||||
    mock.return_value.stdout = BytesIO(b'')
 | 
			
		||||
    mock.return_value.stderr = BytesIO(helptext_new)
 | 
			
		||||
    return mock
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def output(cmd):
 | 
			
		||||
    return "docker: '{}' is not a docker command.\n" \
 | 
			
		||||
           "See 'docker --help'.".format(cmd)
 | 
			
		||||
@@ -113,6 +241,24 @@ def test_match():
 | 
			
		||||
    assert match(Command('docker pes', output('pes')))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# tests docker (management command)
 | 
			
		||||
@pytest.mark.usefixtures('no_memoize')
 | 
			
		||||
@pytest.mark.parametrize('script, output', [
 | 
			
		||||
    ('docker swarn', output('swarn')),
 | 
			
		||||
    ('docker imge', output('imge'))])
 | 
			
		||||
def test_match_management_cmd(script, output):
 | 
			
		||||
    assert match(Command(script, output))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# tests docker (management cmd) (management subcmd)
 | 
			
		||||
@pytest.mark.usefixtures('no_memoize')
 | 
			
		||||
@pytest.mark.parametrize('script, output', [
 | 
			
		||||
    ('docker swarm int', _DOCKER_SWARM_OUTPUT),
 | 
			
		||||
    ('docker image la', _DOCKER_IMAGE_OUTPUT)])
 | 
			
		||||
def test_match_management_subcmd(script, output):
 | 
			
		||||
    assert match(Command(script, output))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('script, output', [
 | 
			
		||||
    ('docker ps', ''),
 | 
			
		||||
    ('cat pes', output('pes'))])
 | 
			
		||||
@@ -120,10 +266,28 @@ def test_not_match(script, output):
 | 
			
		||||
    assert not match(Command(script, output))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.usefixtures('docker_help')
 | 
			
		||||
@pytest.mark.usefixtures('no_memoize', 'docker_help')
 | 
			
		||||
@pytest.mark.parametrize('wrong, fixed', [
 | 
			
		||||
    ('pes', ['ps', 'push', 'pause']),
 | 
			
		||||
    ('tags', ['tag', 'stats', 'images'])])
 | 
			
		||||
def test_get_new_command(wrong, fixed):
 | 
			
		||||
    command = Command('docker {}'.format(wrong), output(wrong))
 | 
			
		||||
    assert get_new_command(command) == ['docker {}'.format(x) for x in fixed]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.usefixtures('no_memoize', 'docker_help_new')
 | 
			
		||||
@pytest.mark.parametrize('wrong, fixed', [
 | 
			
		||||
    ('swarn', ['swarm', 'start', 'search']),
 | 
			
		||||
    ('inage', ['image', 'images', 'rename'])])
 | 
			
		||||
def test_get_new_management_command(wrong, fixed):
 | 
			
		||||
    command = Command('docker {}'.format(wrong), output(wrong))
 | 
			
		||||
    assert get_new_command(command) == ['docker {}'.format(x) for x in fixed]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.usefixtures('no_memoize', 'docker_help_new')
 | 
			
		||||
@pytest.mark.parametrize('wrong, fixed, output', [
 | 
			
		||||
    ('swarm int', ['swarm init', 'swarm join', 'swarm join-token'], _DOCKER_SWARM_OUTPUT),
 | 
			
		||||
    ('image la', ['image load', 'image ls', 'image tag'], _DOCKER_IMAGE_OUTPUT)])
 | 
			
		||||
def test_get_new_management_command_subcommand(wrong, fixed, output):
 | 
			
		||||
    command = Command('docker {}'.format(wrong), output)
 | 
			
		||||
    assert get_new_command(command) == ['docker {}'.format(x) for x in fixed]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										29
									
								
								tests/rules/test_git_branch_delete_checked_out.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								tests/rules/test_git_branch_delete_checked_out.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
import pytest
 | 
			
		||||
from thefuck.rules.git_branch_delete_checked_out import match, get_new_command
 | 
			
		||||
from thefuck.types import Command
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def output():
 | 
			
		||||
    return "error: Cannot delete branch 'foo' checked out at '/bar/foo'"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize("script", ["git branch -d foo", "git branch -D foo"])
 | 
			
		||||
def test_match(script, output):
 | 
			
		||||
    assert match(Command(script, output))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize("script", ["git branch -d foo", "git branch -D foo"])
 | 
			
		||||
def test_not_match(script):
 | 
			
		||||
    assert not match(Command(script, "Deleted branch foo (was a1b2c3d)."))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize(
 | 
			
		||||
    "script, new_command",
 | 
			
		||||
    [
 | 
			
		||||
        ("git branch -d foo", "git checkout master && git branch -D foo"),
 | 
			
		||||
        ("git branch -D foo", "git checkout master && git branch -D foo"),
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
def test_get_new_command(script, new_command, output):
 | 
			
		||||
    assert get_new_command(Command(script, output)) == new_command
 | 
			
		||||
@@ -39,6 +39,11 @@ def test_not_match(command):
 | 
			
		||||
    (b'', []),
 | 
			
		||||
    (b'* master', ['master']),
 | 
			
		||||
    (b'  remotes/origin/master', ['master']),
 | 
			
		||||
    (b'  remotes/origin/test/1', ['test/1']),
 | 
			
		||||
    (b'  remotes/origin/test/1/2/3', ['test/1/2/3']),
 | 
			
		||||
    (b'  test/1', ['test/1']),
 | 
			
		||||
    (b'  test/1/2/3', ['test/1/2/3']),
 | 
			
		||||
    (b'  remotes/origin/HEAD -> origin/master', []),
 | 
			
		||||
    (b'  just-another-branch', ['just-another-branch']),
 | 
			
		||||
    (b'* master\n  just-another-branch', ['master', 'just-another-branch']),
 | 
			
		||||
    (b'* master\n  remotes/origin/master\n  just-another-branch',
 | 
			
		||||
@@ -51,18 +56,18 @@ def test_get_branches(branches, branch_list, git_branch):
 | 
			
		||||
@pytest.mark.parametrize('branches, command, new_command', [
 | 
			
		||||
    (b'',
 | 
			
		||||
     Command('git checkout unknown', did_not_match('unknown')),
 | 
			
		||||
     'git checkout -b unknown'),
 | 
			
		||||
     ['git checkout -b unknown']),
 | 
			
		||||
    (b'',
 | 
			
		||||
     Command('git commit unknown', did_not_match('unknown')),
 | 
			
		||||
     'git branch unknown && git commit unknown'),
 | 
			
		||||
     ['git branch unknown && git commit unknown']),
 | 
			
		||||
    (b'  test-random-branch-123',
 | 
			
		||||
     Command('git checkout tst-rdm-brnch-123',
 | 
			
		||||
             did_not_match('tst-rdm-brnch-123')),
 | 
			
		||||
     'git checkout test-random-branch-123'),
 | 
			
		||||
     ['git checkout test-random-branch-123', 'git checkout -b tst-rdm-brnch-123']),
 | 
			
		||||
    (b'  test-random-branch-123',
 | 
			
		||||
     Command('git commit tst-rdm-brnch-123',
 | 
			
		||||
             did_not_match('tst-rdm-brnch-123')),
 | 
			
		||||
     'git commit test-random-branch-123')])
 | 
			
		||||
     ['git commit test-random-branch-123'])])
 | 
			
		||||
def test_get_new_command(branches, command, new_command, git_branch):
 | 
			
		||||
    git_branch(branches)
 | 
			
		||||
    assert get_new_command(command) == new_command
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								tests/rules/test_git_commit_reset.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								tests/rules/test_git_commit_reset.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
import pytest
 | 
			
		||||
from thefuck.rules.git_commit_reset import match, get_new_command
 | 
			
		||||
from thefuck.types import Command
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('script, output', [
 | 
			
		||||
    ('git commit -m "test"', 'test output'),
 | 
			
		||||
    ('git commit', '')])
 | 
			
		||||
def test_match(output, script):
 | 
			
		||||
    assert match(Command(script, output))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('script', [
 | 
			
		||||
    'git branch foo',
 | 
			
		||||
    'git checkout feature/test_commit',
 | 
			
		||||
    'git push'])
 | 
			
		||||
def test_not_match(script):
 | 
			
		||||
    assert not match(Command(script, ''))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('script', [
 | 
			
		||||
    ('git commit -m "test commit"'),
 | 
			
		||||
    ('git commit')])
 | 
			
		||||
def test_get_new_command(script):
 | 
			
		||||
    assert get_new_command(Command(script, '')) == 'git reset HEAD~'
 | 
			
		||||
							
								
								
									
										21
									
								
								tests/rules/test_go_unknown_command.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/rules/test_go_unknown_command.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
import pytest
 | 
			
		||||
from thefuck.rules.go_unknown_command import match, get_new_command
 | 
			
		||||
from thefuck.types import Command
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def build_misspelled_output():
 | 
			
		||||
    return '''go bulid: unknown command
 | 
			
		||||
Run 'go help' for usage.'''
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_match(build_misspelled_output):
 | 
			
		||||
    assert match(Command('go bulid', build_misspelled_output))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_not_match():
 | 
			
		||||
    assert not match(Command('go run', 'go run: no go files listed'))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_get_new_command(build_misspelled_output):
 | 
			
		||||
    assert get_new_command(Command('go bulid', build_misspelled_output)) == 'go build'
 | 
			
		||||
							
								
								
									
										25
									
								
								tests/rules/test_nixos_cmd_not_found.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								tests/rules/test_nixos_cmd_not_found.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
import pytest
 | 
			
		||||
from thefuck.rules.nixos_cmd_not_found import match, get_new_command
 | 
			
		||||
from thefuck.types import Command
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('command', [
 | 
			
		||||
    Command('vim', 'nix-env -iA nixos.vim')])
 | 
			
		||||
def test_match(mocker, command):
 | 
			
		||||
    mocker.patch('thefuck.rules.nixos_cmd_not_found', return_value=None)
 | 
			
		||||
    assert match(command)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('command', [
 | 
			
		||||
    Command('vim', ''),
 | 
			
		||||
    Command('', '')])
 | 
			
		||||
def test_not_match(mocker, command):
 | 
			
		||||
    mocker.patch('thefuck.rules.nixos_cmd_not_found', return_value=None)
 | 
			
		||||
    assert not match(command)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('command, new_command', [
 | 
			
		||||
    (Command('vim', 'nix-env -iA nixos.vim'), 'nix-env -iA nixos.vim && vim'),
 | 
			
		||||
    (Command('pacman', 'nix-env -iA nixos.pacman'), 'nix-env -iA nixos.pacman && pacman')])
 | 
			
		||||
def test_get_new_command(mocker, command, new_command):
 | 
			
		||||
    assert get_new_command(command) == new_command
 | 
			
		||||
@@ -6,7 +6,7 @@ from thefuck.types import Command
 | 
			
		||||
@pytest.fixture(autouse=True)
 | 
			
		||||
def get_all_executables(mocker):
 | 
			
		||||
    mocker.patch('thefuck.rules.no_command.get_all_executables',
 | 
			
		||||
                 return_value=['vim', 'fsck', 'git', 'go'])
 | 
			
		||||
                 return_value=['vim', 'fsck', 'git', 'go', 'python'])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture(autouse=True)
 | 
			
		||||
@@ -20,6 +20,7 @@ def history_without_current(mocker):
 | 
			
		||||
@pytest.mark.parametrize('script, output', [
 | 
			
		||||
    ('vom file.py', 'vom: not found'),
 | 
			
		||||
    ('fucck', 'fucck: not found'),
 | 
			
		||||
    ('puthon', "'puthon' is not recognized as an internal or external command"),
 | 
			
		||||
    ('got commit', 'got: command not found')])
 | 
			
		||||
def test_match(mocker, script, output):
 | 
			
		||||
    mocker.patch('thefuck.rules.no_command.which', return_value=None)
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@ 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('yay -S llc', 'error: target not found: llc'),
 | 
			
		||||
    Command('yaourt -S llc', 'error: target not found: llc'),
 | 
			
		||||
    Command('pacman llc', 'error: target not found: llc'),
 | 
			
		||||
    Command('sudo pacman llc', 'error: target not found: llc')])
 | 
			
		||||
@@ -19,6 +20,7 @@ def test_match(command):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('command', [
 | 
			
		||||
    Command('yay -S llc', 'error: target not found: llc'),
 | 
			
		||||
    Command('yaourt -S llc', 'error: target not found: llc'),
 | 
			
		||||
    Command('pacman llc', 'error: target not found: llc'),
 | 
			
		||||
    Command('sudo pacman llc', 'error: target not found: llc')])
 | 
			
		||||
@@ -31,6 +33,7 @@ def test_match_mocked(subp_mock, command):
 | 
			
		||||
@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('yay -S llc', 'error: target not found: llc'), ['yay -S extra/llvm', 'yay -S extra/llvm35']),
 | 
			
		||||
    (Command('yaourt -S llc', 'error: target not found: llc'), ['yaourt -S extra/llvm', 'yaourt -S extra/llvm35']),
 | 
			
		||||
    (Command('pacman -S llc', 'error: target not found: llc'), ['pacman -S extra/llvm', 'pacman -S extra/llvm35']),
 | 
			
		||||
    (Command('sudo pacman -S llc', 'error: target not found: llc'), ['sudo pacman -S extra/llvm', 'sudo pacman -S extra/llvm35'])])
 | 
			
		||||
@@ -39,6 +42,7 @@ def test_get_new_command(command, fixed):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('command, fixed', [
 | 
			
		||||
    (Command('yay -S llc', 'error: target not found: llc'), ['yay -S extra/llvm', 'yay -S extra/llvm35']),
 | 
			
		||||
    (Command('yaourt -S llc', 'error: target not found: llc'), ['yaourt -S extra/llvm', 'yaourt -S extra/llvm35']),
 | 
			
		||||
    (Command('pacman -S llc', 'error: target not found: llc'), ['pacman -S extra/llvm', 'pacman -S extra/llvm35']),
 | 
			
		||||
    (Command('sudo pacman -S llc', 'error: target not found: llc'), ['sudo pacman -S extra/llvm', 'sudo pacman -S extra/llvm35'])])
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								tests/rules/test_pip_install.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								tests/rules/test_pip_install.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
# -*- coding: UTF-8 -*-
 | 
			
		||||
from thefuck.rules.pip_install import match, get_new_command
 | 
			
		||||
from thefuck.types import Command
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_match():
 | 
			
		||||
    response1 = """
 | 
			
		||||
    Could not install packages due to an EnvironmentError: [Errno 13] Permission denied: '/Library/Python/2.7/site-packages/entrypoints.pyc'
 | 
			
		||||
Consider using the `--user` option or check the permissions.
 | 
			
		||||
"""
 | 
			
		||||
    assert match(Command('pip install -r requirements.txt', response1))
 | 
			
		||||
 | 
			
		||||
    response2 = """
 | 
			
		||||
Collecting bacon
 | 
			
		||||
  Downloading https://files.pythonhosted.org/packages/b2/81/19fb79139ee71c8bc4e5a444546f318e2b87253b8939ec8a7e10d63b7341/bacon-0.3.1.zip (11.0MB)
 | 
			
		||||
    100% |████████████████████████████████| 11.0MB 3.0MB/s
 | 
			
		||||
Installing collected packages: bacon
 | 
			
		||||
  Running setup.py install for bacon ... done
 | 
			
		||||
Successfully installed bacon-0.3.1
 | 
			
		||||
"""
 | 
			
		||||
    assert not match(Command('pip install bacon', response2))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_get_new_command():
 | 
			
		||||
    assert get_new_command(Command('pip install -r requirements.txt', '')) == 'pip install --user -r requirements.txt'
 | 
			
		||||
    assert get_new_command(Command('pip install bacon', '')) == 'pip install --user bacon'
 | 
			
		||||
    assert get_new_command(Command('pip install --user -r requirements.txt', '')) == 'sudo pip install -r requirements.txt'
 | 
			
		||||
@@ -4,13 +4,23 @@ from thefuck.types import Command
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def pip_unknown_cmd():
 | 
			
		||||
    return '''ERROR: unknown command "instatl" - maybe you meant "install"'''
 | 
			
		||||
def pip_unknown_cmd_without_recommend():
 | 
			
		||||
    return '''ERROR: unknown command "i"'''
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def pip_unknown_cmd_without_recommend():
 | 
			
		||||
    return '''ERROR: unknown command "i"'''
 | 
			
		||||
def broken():
 | 
			
		||||
    return 'instatl'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def suggested():
 | 
			
		||||
    return 'install'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def pip_unknown_cmd(broken, suggested):
 | 
			
		||||
    return 'ERROR: unknown command "{}" - maybe you meant "{}"'.format(broken, suggested)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_match(pip_unknown_cmd, pip_unknown_cmd_without_recommend):
 | 
			
		||||
@@ -19,6 +29,9 @@ def test_match(pip_unknown_cmd, pip_unknown_cmd_without_recommend):
 | 
			
		||||
                             pip_unknown_cmd_without_recommend))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_get_new_command(pip_unknown_cmd):
 | 
			
		||||
    assert get_new_command(Command('pip instatl',
 | 
			
		||||
                                   pip_unknown_cmd)) == 'pip install'
 | 
			
		||||
@pytest.mark.parametrize('script, broken, suggested, new_cmd', [
 | 
			
		||||
    ('pip un+install thefuck', 'un+install', 'uninstall', 'pip uninstall thefuck'),
 | 
			
		||||
    ('pip instatl', 'instatl', 'install', 'pip install')])
 | 
			
		||||
def test_get_new_command(script, new_cmd, pip_unknown_cmd):
 | 
			
		||||
    assert get_new_command(Command(script,
 | 
			
		||||
                                   pip_unknown_cmd)) == new_cmd
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										52
									
								
								tests/rules/test_pyenv_no_such_command.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								tests/rules/test_pyenv_no_such_command.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
from thefuck.rules.pyenv_no_such_command import get_new_command, match
 | 
			
		||||
from thefuck.types import Command
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def output(pyenv_cmd):
 | 
			
		||||
    return "pyenv: no such command `{}'".format(pyenv_cmd)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture(autouse=True)
 | 
			
		||||
def Popen(mocker):
 | 
			
		||||
    mock = mocker.patch('thefuck.rules.pyenv_no_such_command.Popen')
 | 
			
		||||
    mock.return_value.stdout.readlines.return_value = (
 | 
			
		||||
        b'--version\nactivate\ncommands\ncompletions\ndeactivate\nexec_\n'
 | 
			
		||||
        b'global\nhelp\nhooks\ninit\ninstall\nlocal\nprefix_\n'
 | 
			
		||||
        b'realpath.dylib\nrehash\nroot\nshell\nshims\nuninstall\nversion_\n'
 | 
			
		||||
        b'version-file\nversion-file-read\nversion-file-write\nversion-name_\n'
 | 
			
		||||
        b'version-origin\nversions\nvirtualenv\nvirtualenv-delete_\n'
 | 
			
		||||
        b'virtualenv-init\nvirtualenv-prefix\nvirtualenvs_\n'
 | 
			
		||||
        b'virtualenvwrapper\nvirtualenvwrapper_lazy\nwhence\nwhich_\n'
 | 
			
		||||
    ).split()
 | 
			
		||||
    return mock
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('script, pyenv_cmd', [
 | 
			
		||||
    ('pyenv globe', 'globe'),
 | 
			
		||||
    ('pyenv intall 3.8.0', 'intall'),
 | 
			
		||||
    ('pyenv list', 'list'),
 | 
			
		||||
])
 | 
			
		||||
def test_match(script, pyenv_cmd, output):
 | 
			
		||||
    assert match(Command(script, output=output))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('script, output', [
 | 
			
		||||
    ('pyenv global', 'system'),
 | 
			
		||||
    ('pyenv versions', '  3.7.0\n  3.7.1\n* 3.7.2\n'),
 | 
			
		||||
    ('pyenv install --list', '  3.7.0\n  3.7.1\n  3.7.2\n'),
 | 
			
		||||
])
 | 
			
		||||
def test_not_match(script, output):
 | 
			
		||||
    assert not match(Command(script, output=output))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('script, pyenv_cmd, result', [
 | 
			
		||||
    ('pyenv globe', 'globe', 'pyenv global'),
 | 
			
		||||
    ('pyenv intall 3.8.0', 'intall', 'pyenv install 3.8.0'),
 | 
			
		||||
    ('pyenv list', 'list', 'pyenv install --list'),
 | 
			
		||||
    ('pyenv remove 3.8.0', 'remove', 'pyenv uninstall 3.8.0'),
 | 
			
		||||
])
 | 
			
		||||
def test_get_new_command(script, pyenv_cmd, output, result):
 | 
			
		||||
    assert result in get_new_command(Command(script, output))
 | 
			
		||||
							
								
								
									
										38
									
								
								tests/rules/test_remove_shell_prompt_literal.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								tests/rules/test_remove_shell_prompt_literal.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
import pytest
 | 
			
		||||
from thefuck.rules.remove_shell_prompt_literal import match, get_new_command
 | 
			
		||||
from thefuck.types import Command
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def output():
 | 
			
		||||
    return "$: command not found"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize("script", ["$ cd newdir", " $ cd newdir"])
 | 
			
		||||
def test_match(script, output):
 | 
			
		||||
    assert match(Command(script, output))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize(
 | 
			
		||||
    "command",
 | 
			
		||||
    [
 | 
			
		||||
        Command("$", "$: command not found"),
 | 
			
		||||
        Command(" $", "$: command not found"),
 | 
			
		||||
        Command("$?", "127: command not found"),
 | 
			
		||||
        Command(" $?", "127: command not found"),
 | 
			
		||||
        Command("", ""),
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
def test_not_match(command):
 | 
			
		||||
    assert not match(command)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize(
 | 
			
		||||
    "script, new_command",
 | 
			
		||||
    [
 | 
			
		||||
        ("$ cd newdir", "cd newdir"),
 | 
			
		||||
        ("$ python3 -m virtualenv env", "python3 -m virtualenv env"),
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
def test_get_new_command(script, new_command, output):
 | 
			
		||||
    assert get_new_command(Command(script, output)) == new_command
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
# -*- encoding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
from thefuck.rules import switch_lang
 | 
			
		||||
from thefuck.types import Command
 | 
			
		||||
 | 
			
		||||
@@ -9,7 +10,8 @@ from thefuck.types import Command
 | 
			
		||||
    Command(u'фзе-пуе', 'command not found: фзе-пуе'),
 | 
			
		||||
    Command(u'λσ', 'command not found: λσ'),
 | 
			
		||||
    Command(u'שפא-עקא', 'command not found: שפא-עקא'),
 | 
			
		||||
    Command(u'ךד', 'command not found: ךד')])
 | 
			
		||||
    Command(u'ךד', 'command not found: ךד'),
 | 
			
		||||
    Command(u'녀애 ㅣㄴ', 'command not found: 녀애 ㅣㄴ')])
 | 
			
		||||
def test_match(command):
 | 
			
		||||
    assert switch_lang.match(command)
 | 
			
		||||
 | 
			
		||||
@@ -19,7 +21,8 @@ def test_match(command):
 | 
			
		||||
    Command(u'ls', 'command not found: ls'),
 | 
			
		||||
    Command(u'агсл', 'command not found: агсл'),
 | 
			
		||||
    Command(u'фзе-пуе', 'some info'),
 | 
			
		||||
    Command(u'שפא-עקא', 'some info')])
 | 
			
		||||
    Command(u'שפא-עקא', 'some info'),
 | 
			
		||||
    Command(u'녀애 ㅣㄴ', 'some info')])
 | 
			
		||||
def test_not_match(command):
 | 
			
		||||
    assert not switch_lang.match(command)
 | 
			
		||||
 | 
			
		||||
@@ -28,6 +31,9 @@ def test_not_match(command):
 | 
			
		||||
    (Command(u'фзе-пуе штыефдд мшь', ''), 'apt-get install vim'),
 | 
			
		||||
    (Command(u'λσ -λα', ''), 'ls -la'),
 | 
			
		||||
    (Command(u'שפא-עקא ןמדאשךך הןצ', ''), 'apt-get install vim'),
 | 
			
		||||
    (Command(u'ךד -ךש', ''), 'ls -la')])
 | 
			
		||||
    (Command(u'ךד -ךש', ''), 'ls -la'),
 | 
			
		||||
    (Command(u'멧-ㅎㄷㅅ ㅑㅜㄴㅅ미ㅣ 퍄ㅡ', ''), 'apt-get install vim'),
 | 
			
		||||
    (Command(u'ㅣㄴ -ㅣㅁ', ''), 'ls -la'),
 | 
			
		||||
    (Command(u'ㅔㅁㅅ촤', ''), 'patchk'), ])
 | 
			
		||||
def test_get_new_command(command, new_command):
 | 
			
		||||
    assert switch_lang.get_new_command(command) == new_command
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										33
									
								
								tests/rules/test_terraform_init.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								tests/rules/test_terraform_init.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
import pytest
 | 
			
		||||
from thefuck.rules.terraform_init import match, get_new_command
 | 
			
		||||
from thefuck.types import Command
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('script, output', [
 | 
			
		||||
    ('terraform plan', 'Error: Initialization required. '
 | 
			
		||||
                       'Please see the error message above.'),
 | 
			
		||||
    ('terraform plan', 'This module is not yet installed. Run "terraform init" '
 | 
			
		||||
                       'to install all modules required by this configuration.'),
 | 
			
		||||
    ('terraform apply', 'Error: Initialization required. '
 | 
			
		||||
                        'Please see the error message above.'),
 | 
			
		||||
    ('terraform apply', 'This module is not yet installed. Run "terraform init" '
 | 
			
		||||
                        'to install all modules required by this configuration.')])
 | 
			
		||||
def test_match(script, output):
 | 
			
		||||
    assert match(Command(script, output))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('script, output', [
 | 
			
		||||
    ('terraform --version', 'Terraform v0.12.2'),
 | 
			
		||||
    ('terraform plan', 'No changes. Infrastructure is up-to-date.'),
 | 
			
		||||
    ('terraform apply', 'Apply complete! Resources: 0 added, 0 changed, 0 destroyed.'),
 | 
			
		||||
])
 | 
			
		||||
def test_not_match(script, output):
 | 
			
		||||
    assert not match(Command(script, output=output))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('command, new_command', [
 | 
			
		||||
    (Command('terraform plan', ''), 'terraform init && terraform plan'),
 | 
			
		||||
    (Command('terraform apply', ''), 'terraform init && terraform apply'),
 | 
			
		||||
])
 | 
			
		||||
def test_get_new_command(command, new_command):
 | 
			
		||||
    assert get_new_command(command) == new_command
 | 
			
		||||
							
								
								
									
										173
									
								
								tests/rules/test_yum_invalid_operation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								tests/rules/test_yum_invalid_operation.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,173 @@
 | 
			
		||||
from io import BytesIO
 | 
			
		||||
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
from thefuck.rules.yum_invalid_operation import match, get_new_command, _get_operations
 | 
			
		||||
from thefuck.types import Command
 | 
			
		||||
 | 
			
		||||
yum_help_text = '''Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
 | 
			
		||||
Usage: yum [options] COMMAND
 | 
			
		||||
 | 
			
		||||
List of Commands:
 | 
			
		||||
 | 
			
		||||
check          Check for problems in the rpmdb
 | 
			
		||||
check-update   Check for available package updates
 | 
			
		||||
clean          Remove cached data
 | 
			
		||||
deplist        List a package's dependencies
 | 
			
		||||
distribution-synchronization Synchronize installed packages to the latest available versions
 | 
			
		||||
downgrade      downgrade a package
 | 
			
		||||
erase          Remove a package or packages from your system
 | 
			
		||||
fs             Acts on the filesystem data of the host, mainly for removing docs/lanuages for minimal hosts.
 | 
			
		||||
fssnapshot     Creates filesystem snapshots, or lists/deletes current snapshots.
 | 
			
		||||
groups         Display, or use, the groups information
 | 
			
		||||
help           Display a helpful usage message
 | 
			
		||||
history        Display, or use, the transaction history
 | 
			
		||||
info           Display details about a package or group of packages
 | 
			
		||||
install        Install a package or packages on your system
 | 
			
		||||
langavailable  Check available languages
 | 
			
		||||
langinfo       List languages information
 | 
			
		||||
langinstall    Install appropriate language packs for a language
 | 
			
		||||
langlist       List installed languages
 | 
			
		||||
langremove     Remove installed language packs for a language
 | 
			
		||||
list           List a package or groups of packages
 | 
			
		||||
load-transaction load a saved transaction from filename
 | 
			
		||||
makecache      Generate the metadata cache
 | 
			
		||||
provides       Find what package provides the given value
 | 
			
		||||
reinstall      reinstall a package
 | 
			
		||||
repo-pkgs      Treat a repo. as a group of packages, so we can install/remove all of them
 | 
			
		||||
repolist       Display the configured software repositories
 | 
			
		||||
search         Search package details for the given string
 | 
			
		||||
shell          Run an interactive yum shell
 | 
			
		||||
swap           Simple way to swap packages, instead of using shell
 | 
			
		||||
update         Update a package or packages on your system
 | 
			
		||||
update-minimal Works like upgrade, but goes to the 'newest' package match which fixes a problem that affects your system
 | 
			
		||||
updateinfo     Acts on repository update information
 | 
			
		||||
upgrade        Update packages taking obsoletes into account
 | 
			
		||||
version        Display a version for the machine and/or available repos.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Options:
 | 
			
		||||
  -h, --help            show this help message and exit
 | 
			
		||||
  -t, --tolerant        be tolerant of errors
 | 
			
		||||
  -C, --cacheonly       run entirely from system cache, don't update cache
 | 
			
		||||
  -c [config file], --config=[config file]
 | 
			
		||||
                        config file location
 | 
			
		||||
  -R [minutes], --randomwait=[minutes]
 | 
			
		||||
                        maximum command wait time
 | 
			
		||||
  -d [debug level], --debuglevel=[debug level]
 | 
			
		||||
                        debugging output level
 | 
			
		||||
  --showduplicates      show duplicates, in repos, in list/search commands
 | 
			
		||||
  -e [error level], --errorlevel=[error level]
 | 
			
		||||
                        error output level
 | 
			
		||||
  --rpmverbosity=[debug level name]
 | 
			
		||||
                        debugging output level for rpm
 | 
			
		||||
  -q, --quiet           quiet operation
 | 
			
		||||
  -v, --verbose         verbose operation
 | 
			
		||||
  -y, --assumeyes       answer yes for all questions
 | 
			
		||||
  --assumeno            answer no for all questions
 | 
			
		||||
  --version             show Yum version and exit
 | 
			
		||||
  --installroot=[path]  set install root
 | 
			
		||||
  --enablerepo=[repo]   enable one or more repositories (wildcards allowed)
 | 
			
		||||
  --disablerepo=[repo]  disable one or more repositories (wildcards allowed)
 | 
			
		||||
  -x [package], --exclude=[package]
 | 
			
		||||
                        exclude package(s) by name or glob
 | 
			
		||||
  --disableexcludes=[repo]
 | 
			
		||||
                        disable exclude from main, for a repo or for
 | 
			
		||||
                        everything
 | 
			
		||||
  --disableincludes=[repo]
 | 
			
		||||
                        disable includepkgs for a repo or for everything
 | 
			
		||||
  --obsoletes           enable obsoletes processing during updates
 | 
			
		||||
  --noplugins           disable Yum plugins
 | 
			
		||||
  --nogpgcheck          disable gpg signature checking
 | 
			
		||||
  --disableplugin=[plugin]
 | 
			
		||||
                        disable plugins by name
 | 
			
		||||
  --enableplugin=[plugin]
 | 
			
		||||
                        enable plugins by name
 | 
			
		||||
  --skip-broken         skip packages with depsolving problems
 | 
			
		||||
  --color=COLOR         control whether color is used
 | 
			
		||||
  --releasever=RELEASEVER
 | 
			
		||||
                        set value of $releasever in yum config and repo files
 | 
			
		||||
  --downloadonly        don't update, just download
 | 
			
		||||
  --downloaddir=DLDIR   specifies an alternate directory to store packages
 | 
			
		||||
  --setopt=SETOPTS      set arbitrary config and repo options
 | 
			
		||||
  --bugfix              Include bugfix relevant packages, in updates
 | 
			
		||||
  --security            Include security relevant packages, in updates
 | 
			
		||||
  --advisory=ADVS, --advisories=ADVS
 | 
			
		||||
                        Include packages needed to fix the given advisory, in
 | 
			
		||||
                        updates
 | 
			
		||||
  --bzs=BZS             Include packages needed to fix the given BZ, in
 | 
			
		||||
                        updates
 | 
			
		||||
  --cves=CVES           Include packages needed to fix the given CVE, in
 | 
			
		||||
                        updates
 | 
			
		||||
  --sec-severity=SEVS, --secseverity=SEVS
 | 
			
		||||
                        Include security relevant packages matching the
 | 
			
		||||
                        severity, in updates
 | 
			
		||||
 | 
			
		||||
  Plugin Options:
 | 
			
		||||
    --samearch-priorities
 | 
			
		||||
                        Priority-exclude packages based on name + arch
 | 
			
		||||
'''
 | 
			
		||||
yum_unsuccessful_search_text = '''Warning: No matches found for: {}
 | 
			
		||||
No matches found
 | 
			
		||||
'''
 | 
			
		||||
yum_successful_vim_search_text = '''================================================== N/S matched: vim ===================================================
 | 
			
		||||
protobuf-vim.x86_64 : Vim syntax highlighting for Google Protocol Buffers descriptions
 | 
			
		||||
vim-X11.x86_64 : The VIM version of the vi editor for the X Window System - GVim
 | 
			
		||||
vim-common.x86_64 : The common files needed by any version of the VIM editor
 | 
			
		||||
vim-enhanced.x86_64 : A version of the VIM editor which includes recent enhancements
 | 
			
		||||
vim-filesystem.x86_64 : VIM filesystem layout
 | 
			
		||||
vim-filesystem.noarch : VIM filesystem layout
 | 
			
		||||
vim-minimal.x86_64 : A minimal version of the VIM editor
 | 
			
		||||
 | 
			
		||||
  Name and summary matches only, use "search all" for everything.
 | 
			
		||||
'''
 | 
			
		||||
 | 
			
		||||
yum_invalid_op_text = '''Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
 | 
			
		||||
No such command: {}. Please use /usr/bin/yum --help
 | 
			
		||||
'''
 | 
			
		||||
 | 
			
		||||
yum_operations = [
 | 
			
		||||
    'check', 'check-update', 'clean', 'deplist', 'distribution-synchronization', 'downgrade', 'erase', 'fs',
 | 
			
		||||
    'fssnapshot', 'groups', 'help', 'history', 'info', 'install', 'langavailable', 'langinfo', 'langinstall',
 | 
			
		||||
    'langlist', 'langremove', 'list', 'load-transaction', 'makecache', 'provides', 'reinstall', 'repo-pkgs', 'repolist',
 | 
			
		||||
    'search', 'shell', 'swap', 'update', 'update-minimal', 'updateinfo', 'upgrade', 'version', ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('command', [
 | 
			
		||||
    'saerch', 'uninstall',
 | 
			
		||||
])
 | 
			
		||||
def test_match(command):
 | 
			
		||||
    assert match(Command('yum {}'.format(command), yum_invalid_op_text.format(command)))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('command, output', [
 | 
			
		||||
    ('vim', ''),
 | 
			
		||||
    ('yum', yum_help_text,),
 | 
			
		||||
    ('yum help', yum_help_text,),
 | 
			
		||||
    ('yum search asdf', yum_unsuccessful_search_text.format('asdf'),),
 | 
			
		||||
    ('yum search vim', yum_successful_vim_search_text)
 | 
			
		||||
])
 | 
			
		||||
def test_not_match(command, output):
 | 
			
		||||
    assert not match(Command(command, output))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def yum_help(mocker):
 | 
			
		||||
    mock = mocker.patch('subprocess.Popen')
 | 
			
		||||
    mock.return_value.stdout = BytesIO(bytes(yum_help_text.encode('utf-8')))
 | 
			
		||||
    return mock
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.usefixtures('no_memoize', 'yum_help')
 | 
			
		||||
def test_get_operations():
 | 
			
		||||
    assert _get_operations() == yum_operations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.usefixtures('no_memoize', 'yum_help')
 | 
			
		||||
@pytest.mark.parametrize('script, output, result', [
 | 
			
		||||
    ('yum uninstall', yum_invalid_op_text.format('uninstall'), 'yum remove',),
 | 
			
		||||
    ('yum saerch asdf', yum_invalid_op_text.format('saerch'), 'yum search asdf',),
 | 
			
		||||
    ('yum hlep', yum_invalid_op_text.format('hlep'), 'yum help',),
 | 
			
		||||
])
 | 
			
		||||
def test_get_new_command(script, output, result):
 | 
			
		||||
    assert get_new_command(Command(script, output))[0] == result
 | 
			
		||||
@@ -11,6 +11,11 @@ class TestBash(object):
 | 
			
		||||
    def shell(self):
 | 
			
		||||
        return Bash()
 | 
			
		||||
 | 
			
		||||
    @pytest.fixture(autouse=True)
 | 
			
		||||
    def Popen(self, mocker):
 | 
			
		||||
        mock = mocker.patch('thefuck.shells.bash.Popen')
 | 
			
		||||
        return mock
 | 
			
		||||
 | 
			
		||||
    @pytest.fixture(autouse=True)
 | 
			
		||||
    def shell_aliases(self):
 | 
			
		||||
        os.environ['TF_SHELL_ALIASES'] = (
 | 
			
		||||
@@ -74,7 +79,12 @@ class TestBash(object):
 | 
			
		||||
        config_exists.return_value = False
 | 
			
		||||
        assert not shell.how_to_configure().can_configure_automatically
 | 
			
		||||
 | 
			
		||||
    def test_info(self, shell, mocker):
 | 
			
		||||
        patch = mocker.patch('thefuck.shells.bash.Popen')
 | 
			
		||||
        patch.return_value.stdout.read.side_effect = [b'3.5.9']
 | 
			
		||||
    def test_info(self, shell, Popen):
 | 
			
		||||
        Popen.return_value.stdout.read.side_effect = [b'3.5.9']
 | 
			
		||||
        assert shell.info() == 'Bash 3.5.9'
 | 
			
		||||
 | 
			
		||||
    def test_get_version_error(self, shell, Popen):
 | 
			
		||||
        Popen.return_value.stdout.read.side_effect = OSError
 | 
			
		||||
        with pytest.raises(OSError):
 | 
			
		||||
            shell._get_version()
 | 
			
		||||
        assert Popen.call_args[0][0] == ['bash', '-c', 'echo $BASH_VERSION']
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
import pytest
 | 
			
		||||
from thefuck.const import ARGUMENT_PLACEHOLDER
 | 
			
		||||
from thefuck.shells import Fish
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -28,8 +29,9 @@ class TestFish(object):
 | 
			
		||||
        ('THEFUCK_OVERRIDDEN_ALIASES', '\ncut,\n\ngit,\tsed\r')])
 | 
			
		||||
    def test_get_overridden_aliases(self, shell, os_environ, key, value):
 | 
			
		||||
        os_environ[key] = value
 | 
			
		||||
        assert shell._get_overridden_aliases() == {'cd', 'cut', 'git', 'grep',
 | 
			
		||||
                                                   'ls', 'man', 'open', 'sed'}
 | 
			
		||||
        overridden = shell._get_overridden_aliases()
 | 
			
		||||
        assert set(overridden) == {'cd', 'cut', 'git', 'grep',
 | 
			
		||||
                                   'ls', 'man', 'open', 'sed'}
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize('before, after', [
 | 
			
		||||
        ('cd', 'cd'),
 | 
			
		||||
@@ -81,6 +83,7 @@ class TestFish(object):
 | 
			
		||||
        assert 'TF_SHELL=fish' in shell.app_alias('fuck')
 | 
			
		||||
        assert 'TF_ALIAS=fuck PYTHONIOENCODING' in shell.app_alias('fuck')
 | 
			
		||||
        assert 'PYTHONIOENCODING=utf-8 thefuck' in shell.app_alias('fuck')
 | 
			
		||||
        assert ARGUMENT_PLACEHOLDER in shell.app_alias('fuck')
 | 
			
		||||
 | 
			
		||||
    def test_app_alias_alter_history(self, settings, shell):
 | 
			
		||||
        settings.alter_history = True
 | 
			
		||||
@@ -113,6 +116,17 @@ class TestFish(object):
 | 
			
		||||
        config_exists.return_value = False
 | 
			
		||||
        assert not shell.how_to_configure().can_configure_automatically
 | 
			
		||||
 | 
			
		||||
    def test_info(self, shell, Popen):
 | 
			
		||||
        Popen.return_value.stdout.read.side_effect = [b'3.5.9']
 | 
			
		||||
        assert shell.info() == 'Fish Shell 3.5.9'
 | 
			
		||||
    def test_get_version(self, shell, Popen):
 | 
			
		||||
        Popen.return_value.stdout.read.side_effect = [b'fish, version 3.5.9\n']
 | 
			
		||||
        assert shell._get_version() == '3.5.9'
 | 
			
		||||
        assert Popen.call_args[0][0] == ['fish', '--version']
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize('side_effect, exception', [
 | 
			
		||||
        ([b'\n'], IndexError),
 | 
			
		||||
        (OSError('file not found'), OSError),
 | 
			
		||||
    ])
 | 
			
		||||
    def test_get_version_error(self, side_effect, exception, shell, Popen):
 | 
			
		||||
        Popen.return_value.stdout.read.side_effect = side_effect
 | 
			
		||||
        with pytest.raises(exception):
 | 
			
		||||
            shell._get_version()
 | 
			
		||||
        assert Popen.call_args[0][0] == ['fish', '--version']
 | 
			
		||||
 
 | 
			
		||||
@@ -43,3 +43,14 @@ class TestGeneric(object):
 | 
			
		||||
 | 
			
		||||
    def test_how_to_configure(self, shell):
 | 
			
		||||
        assert shell.how_to_configure() is None
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize('side_effect, expected_info, warn', [
 | 
			
		||||
        ([u'3.5.9'], u'Generic Shell 3.5.9', False),
 | 
			
		||||
        ([OSError], u'Generic Shell', True),
 | 
			
		||||
    ])
 | 
			
		||||
    def test_info(self, side_effect, expected_info, warn, shell, mocker):
 | 
			
		||||
        warn_mock = mocker.patch('thefuck.shells.generic.warn')
 | 
			
		||||
        shell._get_version = mocker.Mock(side_effect=side_effect)
 | 
			
		||||
        assert shell.info() == expected_info
 | 
			
		||||
        assert warn_mock.called is warn
 | 
			
		||||
        assert shell._get_version.called
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,11 @@ class TestPowershell(object):
 | 
			
		||||
    def shell(self):
 | 
			
		||||
        return Powershell()
 | 
			
		||||
 | 
			
		||||
    @pytest.fixture(autouse=True)
 | 
			
		||||
    def Popen(self, mocker):
 | 
			
		||||
        mock = mocker.patch('thefuck.shells.powershell.Popen')
 | 
			
		||||
        return mock
 | 
			
		||||
 | 
			
		||||
    def test_and_(self, shell):
 | 
			
		||||
        assert shell.and_('ls', 'cd') == '(ls) -and (cd)'
 | 
			
		||||
 | 
			
		||||
@@ -20,3 +25,20 @@ class TestPowershell(object):
 | 
			
		||||
 | 
			
		||||
    def test_how_to_configure(self, shell):
 | 
			
		||||
        assert not shell.how_to_configure().can_configure_automatically
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize('side_effect, expected_version, call_args', [
 | 
			
		||||
        ([b'''Major  Minor  Build  Revision
 | 
			
		||||
-----  -----  -----  --------
 | 
			
		||||
5      1      17763  316     \n'''], 'PowerShell 5.1.17763.316', ['powershell.exe']),
 | 
			
		||||
        ([IOError, b'PowerShell 6.1.2\n'], 'PowerShell 6.1.2', ['powershell.exe', 'pwsh'])])
 | 
			
		||||
    def test_info(self, side_effect, expected_version, call_args, shell, Popen):
 | 
			
		||||
        Popen.return_value.stdout.read.side_effect = side_effect
 | 
			
		||||
        assert shell.info() == expected_version
 | 
			
		||||
        assert Popen.call_count == len(call_args)
 | 
			
		||||
        assert all([Popen.call_args_list[i][0][0][0] == call_arg for i, call_arg in enumerate(call_args)])
 | 
			
		||||
 | 
			
		||||
    def test_get_version_error(self, shell, Popen):
 | 
			
		||||
        Popen.return_value.stdout.read.side_effect = RuntimeError
 | 
			
		||||
        with pytest.raises(RuntimeError):
 | 
			
		||||
            shell._get_version()
 | 
			
		||||
        assert Popen.call_args[0][0] == ['powershell.exe', '$PSVersionTable.PSVersion']
 | 
			
		||||
 
 | 
			
		||||
@@ -61,3 +61,17 @@ class TestTcsh(object):
 | 
			
		||||
                                                    config_exists):
 | 
			
		||||
        config_exists.return_value = False
 | 
			
		||||
        assert not shell.how_to_configure().can_configure_automatically
 | 
			
		||||
 | 
			
		||||
    def test_info(self, shell, Popen):
 | 
			
		||||
        Popen.return_value.stdout.read.side_effect = [
 | 
			
		||||
            b'tcsh 6.20.00 (Astron) 2016-11-24 (unknown-unknown-bsd44) \n']
 | 
			
		||||
        assert shell.info() == 'Tcsh 6.20.00'
 | 
			
		||||
        assert Popen.call_args[0][0] == ['tcsh', '--version']
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize('side_effect, exception', [
 | 
			
		||||
        ([b'\n'], IndexError), (OSError, OSError)])
 | 
			
		||||
    def test_get_version_error(self, side_effect, exception, shell, Popen):
 | 
			
		||||
        Popen.return_value.stdout.read.side_effect = side_effect
 | 
			
		||||
        with pytest.raises(exception):
 | 
			
		||||
            shell._get_version()
 | 
			
		||||
        assert Popen.call_args[0][0] == ['tcsh', '--version']
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,11 @@ class TestZsh(object):
 | 
			
		||||
    def shell(self):
 | 
			
		||||
        return Zsh()
 | 
			
		||||
 | 
			
		||||
    @pytest.fixture(autouse=True)
 | 
			
		||||
    def Popen(self, mocker):
 | 
			
		||||
        mock = mocker.patch('thefuck.shells.zsh.Popen')
 | 
			
		||||
        return mock
 | 
			
		||||
 | 
			
		||||
    @pytest.fixture(autouse=True)
 | 
			
		||||
    def shell_aliases(self):
 | 
			
		||||
        os.environ['TF_SHELL_ALIASES'] = (
 | 
			
		||||
@@ -69,7 +74,12 @@ class TestZsh(object):
 | 
			
		||||
        config_exists.return_value = False
 | 
			
		||||
        assert not shell.how_to_configure().can_configure_automatically
 | 
			
		||||
 | 
			
		||||
    def test_info(self, shell, mocker):
 | 
			
		||||
        patch = mocker.patch('thefuck.shells.zsh.Popen')
 | 
			
		||||
        patch.return_value.stdout.read.side_effect = [b'3.5.9']
 | 
			
		||||
    def test_info(self, shell, Popen):
 | 
			
		||||
        Popen.return_value.stdout.read.side_effect = [b'3.5.9']
 | 
			
		||||
        assert shell.info() == 'ZSH 3.5.9'
 | 
			
		||||
 | 
			
		||||
    def test_get_version_error(self, shell, Popen):
 | 
			
		||||
        Popen.return_value.stdout.read.side_effect = OSError
 | 
			
		||||
        with pytest.raises(OSError):
 | 
			
		||||
            shell._get_version()
 | 
			
		||||
        assert Popen.call_args[0][0] == ['zsh', '-c', 'echo $ZSH_VERSION']
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
import pytest
 | 
			
		||||
import warnings
 | 
			
		||||
from mock import Mock, patch
 | 
			
		||||
from mock import Mock, call, patch
 | 
			
		||||
from thefuck.utils import default_settings, \
 | 
			
		||||
    memoize, get_closest, get_all_executables, replace_argument, \
 | 
			
		||||
    get_all_matched_commands, is_app, for_app, cache, \
 | 
			
		||||
@@ -76,6 +76,24 @@ def test_get_all_executables():
 | 
			
		||||
    assert 'fuck' not in all_callables
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def os_environ_pathsep(monkeypatch, path, pathsep):
 | 
			
		||||
    env = {'PATH': path}
 | 
			
		||||
    monkeypatch.setattr('os.environ', env)
 | 
			
		||||
    monkeypatch.setattr('os.pathsep', pathsep)
 | 
			
		||||
    return env
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.usefixtures('no_memoize', 'os_environ_pathsep')
 | 
			
		||||
@pytest.mark.parametrize('path, pathsep', [
 | 
			
		||||
    ('/foo:/bar:/baz:/foo/bar', ':'),
 | 
			
		||||
    (r'C:\\foo;C:\\bar;C:\\baz;C:\\foo\\bar', ';')])
 | 
			
		||||
def test_get_all_executables_pathsep(path, pathsep):
 | 
			
		||||
    with patch('thefuck.utils.Path') as Path_mock:
 | 
			
		||||
        get_all_executables()
 | 
			
		||||
        Path_mock.assert_has_calls([call(p) for p in path.split(pathsep)], True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('args, result', [
 | 
			
		||||
    (('apt-get instol vim', 'instol', 'install'), 'apt-get install vim'),
 | 
			
		||||
    (('git brnch', 'brnch', 'branch'), 'git branch')])
 | 
			
		||||
@@ -207,9 +225,12 @@ class TestGetValidHistoryWithoutCurrent(object):
 | 
			
		||||
 | 
			
		||||
    @pytest.fixture(autouse=True)
 | 
			
		||||
    def history(self, mocker):
 | 
			
		||||
        return mocker.patch('thefuck.shells.shell.get_history',
 | 
			
		||||
                            return_value=['le cat', 'fuck', 'ls cat',
 | 
			
		||||
                                          'diff x', 'nocommand x', u'café ô'])
 | 
			
		||||
        mock = mocker.patch('thefuck.shells.shell.get_history')
 | 
			
		||||
        #  Passing as an argument causes `UnicodeDecodeError`
 | 
			
		||||
        #  with newer py.test and python 2.7
 | 
			
		||||
        mock.return_value = ['le cat', 'fuck', 'ls cat',
 | 
			
		||||
                             'diff x', 'nocommand x', u'café ô']
 | 
			
		||||
        return mock
 | 
			
		||||
 | 
			
		||||
    @pytest.fixture(autouse=True)
 | 
			
		||||
    def alias(self, mocker):
 | 
			
		||||
 
 | 
			
		||||
@@ -55,7 +55,7 @@ class Parser(object):
 | 
			
		||||
        """It's too dangerous to use `-y` and `-r` together."""
 | 
			
		||||
        group = self._parser.add_mutually_exclusive_group()
 | 
			
		||||
        group.add_argument(
 | 
			
		||||
            '-y', '--yes', '--yeah',
 | 
			
		||||
            '-y', '--yes', '--yeah', '--hard',
 | 
			
		||||
            action='store_true',
 | 
			
		||||
            help='execute fixed command without confirmation')
 | 
			
		||||
        group.add_argument(
 | 
			
		||||
 
 | 
			
		||||
@@ -22,10 +22,13 @@ def main():
 | 
			
		||||
    elif known_args.version:
 | 
			
		||||
        logs.version(get_installation_info().version,
 | 
			
		||||
                     sys.version.split()[0], shell.info())
 | 
			
		||||
    elif known_args.command or 'TF_HISTORY' in os.environ:
 | 
			
		||||
        fix_command(known_args)
 | 
			
		||||
    # It's important to check if an alias is being requested before checking if
 | 
			
		||||
    # `TF_HISTORY` is in `os.environ`, otherwise it might mess with subshells.
 | 
			
		||||
    # Check https://github.com/nvbn/thefuck/issues/921 for reference
 | 
			
		||||
    elif known_args.alias:
 | 
			
		||||
        print_alias(known_args)
 | 
			
		||||
    elif known_args.command or 'TF_HISTORY' in os.environ:
 | 
			
		||||
        fix_command(known_args)
 | 
			
		||||
    elif known_args.shell_logger:
 | 
			
		||||
        try:
 | 
			
		||||
            from .shell_logger import shell_logger  # noqa: E402
 | 
			
		||||
 
 | 
			
		||||
@@ -106,7 +106,7 @@ def how_to_configure_alias(configuration_details):
 | 
			
		||||
 | 
			
		||||
        if configuration_details.can_configure_automatically:
 | 
			
		||||
            print(
 | 
			
		||||
                u"Or run {bold}fuck{reset} second time for configuring"
 | 
			
		||||
                u"Or run {bold}fuck{reset} a second time to configure"
 | 
			
		||||
                u" it automatically.".format(
 | 
			
		||||
                    bold=color(colorama.Style.BRIGHT),
 | 
			
		||||
                    reset=color(colorama.Style.RESET_ALL)))
 | 
			
		||||
 
 | 
			
		||||
@@ -53,8 +53,9 @@ def get_output(script, expanded):
 | 
			
		||||
    env = dict(os.environ)
 | 
			
		||||
    env.update(settings.env)
 | 
			
		||||
 | 
			
		||||
    is_slow = shlex.split(expanded) in settings.slow_commands
 | 
			
		||||
    with logs.debug_time(u'Call: {}; with env: {}; is slow: '.format(
 | 
			
		||||
    split_expand = shlex.split(expanded)
 | 
			
		||||
    is_slow = split_expand[0] in settings.slow_commands if split_expand else False
 | 
			
		||||
    with logs.debug_time(u'Call: {}; with env: {}; is slow: {}'.format(
 | 
			
		||||
            script, env, is_slow)):
 | 
			
		||||
        result = Popen(expanded, shell=True, stdin=PIPE,
 | 
			
		||||
                       stdout=PIPE, stderr=STDOUT, env=env)
 | 
			
		||||
 
 | 
			
		||||
@@ -6,8 +6,8 @@ from thefuck.utils import for_app, eager, replace_command
 | 
			
		||||
enabled_by_default = apt_available
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@for_app('apt', 'apt-get', 'apt-cache')
 | 
			
		||||
@sudo_support
 | 
			
		||||
@for_app('apt', 'apt-get', 'apt-cache')
 | 
			
		||||
def match(command):
 | 
			
		||||
    return 'E: Invalid operation' in command.output
 | 
			
		||||
 | 
			
		||||
@@ -34,7 +34,8 @@ def _parse_apt_get_and_cache_operations(help_text_lines):
 | 
			
		||||
                return
 | 
			
		||||
 | 
			
		||||
            yield line.split()[0]
 | 
			
		||||
        elif line.startswith('Commands:'):
 | 
			
		||||
        elif line.startswith('Commands:') \
 | 
			
		||||
                or line.startswith('Most used commands:'):
 | 
			
		||||
            is_commands_list = True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -53,5 +54,10 @@ def _get_operations(app):
 | 
			
		||||
@sudo_support
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    invalid_operation = command.output.split()[-1]
 | 
			
		||||
    operations = _get_operations(command.script_parts[0])
 | 
			
		||||
    return replace_command(command, invalid_operation, operations)
 | 
			
		||||
 | 
			
		||||
    if invalid_operation == 'uninstall':
 | 
			
		||||
        return [command.script.replace('uninstall', 'remove')]
 | 
			
		||||
 | 
			
		||||
    else:
 | 
			
		||||
        operations = _get_operations(command.script_parts[0])
 | 
			
		||||
        return replace_command(command, invalid_operation, operations)
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ enabled_by_default = apt_available
 | 
			
		||||
@sudo_support
 | 
			
		||||
@for_app('apt')
 | 
			
		||||
def match(command):
 | 
			
		||||
    return "Run 'apt list --upgradable' to see them." in command.output
 | 
			
		||||
    return 'apt list --upgradable' in command.output
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@sudo_support
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								thefuck/rules/choco_install.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								thefuck/rules/choco_install.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
from thefuck.utils import for_app, which
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@for_app("choco", "cinst")
 | 
			
		||||
def match(command):
 | 
			
		||||
    return ((command.script.startswith('choco install') or 'cinst' in command.script_parts)
 | 
			
		||||
            and 'Installing the following packages' in command.output)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    # Find the argument that is the package name
 | 
			
		||||
    for script_part in command.script_parts:
 | 
			
		||||
        if (
 | 
			
		||||
            script_part not in ["choco", "cinst", "install"]
 | 
			
		||||
            # Need exact match (bc chocolatey is a package)
 | 
			
		||||
            and not script_part.startswith('-')
 | 
			
		||||
            # Leading hyphens are parameters; some packages contain them though
 | 
			
		||||
            and '=' not in script_part and '/' not in script_part
 | 
			
		||||
            # These are certainly parameters
 | 
			
		||||
        ):
 | 
			
		||||
            return command.script.replace(script_part, script_part + ".install")
 | 
			
		||||
    return []
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
enabled_by_default = bool(which("choco")) or bool(which("cinst"))
 | 
			
		||||
							
								
								
									
										15
									
								
								thefuck/rules/cp_create_destination.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								thefuck/rules/cp_create_destination.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
from thefuck.shells import shell
 | 
			
		||||
from thefuck.utils import for_app
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@for_app("cp", "mv")
 | 
			
		||||
def match(command):
 | 
			
		||||
    return (
 | 
			
		||||
        "No such file or directory" in command.output
 | 
			
		||||
        or command.output.startswith("cp: directory")
 | 
			
		||||
        and command.output.rstrip().endswith("does not exist")
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    return shell.and_(u"mkdir -p {}".format(command.script_parts[-1]), command.script)
 | 
			
		||||
@@ -8,8 +8,8 @@ from thefuck.specific.dnf import dnf_available
 | 
			
		||||
regex = re.compile(r'No such command: (.*)\.')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@for_app('dnf')
 | 
			
		||||
@sudo_support
 | 
			
		||||
@for_app('dnf')
 | 
			
		||||
def match(command):
 | 
			
		||||
    return 'no such command' in command.output.lower()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								thefuck/rules/docker_image_being_used_by_container.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								thefuck/rules/docker_image_being_used_by_container.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
from thefuck.utils import for_app
 | 
			
		||||
from thefuck.shells import shell
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@for_app('docker')
 | 
			
		||||
def match(command):
 | 
			
		||||
    '''
 | 
			
		||||
    Matches a command's output with docker's output
 | 
			
		||||
    warning you that you need to remove a container before removing an image.
 | 
			
		||||
    '''
 | 
			
		||||
    return 'image is being used by running container' in command.output
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    '''
 | 
			
		||||
    Prepends docker container rm -f {container ID} to
 | 
			
		||||
    the previous docker image rm {image ID} command
 | 
			
		||||
    '''
 | 
			
		||||
    container_id = command.output.strip().split(' ')
 | 
			
		||||
    return shell.and_('docker container rm -f {}', '{}').format(container_id[-1], command.script)
 | 
			
		||||
							
								
								
									
										12
									
								
								thefuck/rules/docker_login.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								thefuck/rules/docker_login.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
from thefuck.utils import for_app
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@for_app('docker')
 | 
			
		||||
def match(command):
 | 
			
		||||
    return ('docker' in command.script
 | 
			
		||||
            and "access denied" in command.output
 | 
			
		||||
            and "may require 'docker login'" in command.output)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    return 'docker login && {}'.format(command.script)
 | 
			
		||||
@@ -8,16 +8,30 @@ from thefuck.specific.sudo import sudo_support
 | 
			
		||||
@sudo_support
 | 
			
		||||
@for_app('docker')
 | 
			
		||||
def match(command):
 | 
			
		||||
    return 'is not a docker command' in command.output
 | 
			
		||||
    return 'is not a docker command' in command.output or 'Usage:	docker' in command.output
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _parse_commands(lines, starts_with):
 | 
			
		||||
    lines = dropwhile(lambda line: not line.startswith(starts_with), lines)
 | 
			
		||||
    lines = islice(lines, 1, None)
 | 
			
		||||
    lines = list(takewhile(lambda line: line.strip(), lines))
 | 
			
		||||
    return [line.strip().split(' ')[0] for line in lines]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_docker_commands():
 | 
			
		||||
    proc = subprocess.Popen('docker', stdout=subprocess.PIPE)
 | 
			
		||||
    lines = [line.decode('utf-8') for line in proc.stdout.readlines()]
 | 
			
		||||
    lines = dropwhile(lambda line: not line.startswith('Commands:'), lines)
 | 
			
		||||
    lines = islice(lines, 1, None)
 | 
			
		||||
    lines = list(takewhile(lambda line: line != '\n', lines))
 | 
			
		||||
    return [line.strip().split(' ')[0] for line in lines]
 | 
			
		||||
    proc = subprocess.Popen('docker', stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 | 
			
		||||
 | 
			
		||||
    # Old version docker returns its output to stdout, while newer version returns to stderr.
 | 
			
		||||
    lines = proc.stdout.readlines() or proc.stderr.readlines()
 | 
			
		||||
    lines = [line.decode('utf-8') for line in lines]
 | 
			
		||||
 | 
			
		||||
    # Only newer versions of docker have management commands in the help text.
 | 
			
		||||
    if 'Management Commands:\n' in lines:
 | 
			
		||||
        management_commands = _parse_commands(lines, 'Management Commands:')
 | 
			
		||||
    else:
 | 
			
		||||
        management_commands = []
 | 
			
		||||
    regular_commands = _parse_commands(lines, 'Commands:')
 | 
			
		||||
    return management_commands + regular_commands
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if which('docker'):
 | 
			
		||||
@@ -26,6 +40,10 @@ if which('docker'):
 | 
			
		||||
 | 
			
		||||
@sudo_support
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    if 'Usage:' in command.output and len(command.script_parts) > 1:
 | 
			
		||||
        management_subcommands = _parse_commands(command.output.split('\n'), 'Commands:')
 | 
			
		||||
        return replace_command(command, command.script_parts[2], management_subcommands)
 | 
			
		||||
 | 
			
		||||
    wrong_command = re.findall(
 | 
			
		||||
        r"docker: '(\w+)' is not a docker command.", command.output)[0]
 | 
			
		||||
    return replace_command(command, wrong_command, get_docker_commands())
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								thefuck/rules/git_branch_delete_checked_out.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								thefuck/rules/git_branch_delete_checked_out.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
from thefuck.shells import shell
 | 
			
		||||
from thefuck.specific.git import git_support
 | 
			
		||||
from thefuck.utils import replace_argument
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@git_support
 | 
			
		||||
def match(command):
 | 
			
		||||
    return (
 | 
			
		||||
        ("branch -d" in command.script or "branch -D" in command.script)
 | 
			
		||||
        and "error: Cannot delete branch '" in command.output
 | 
			
		||||
        and "' checked out at '" in command.output
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@git_support
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    return shell.and_("git checkout master", "{}").format(
 | 
			
		||||
        replace_argument(command.script, "-d", "-D")
 | 
			
		||||
    )
 | 
			
		||||
@@ -8,7 +8,7 @@ from thefuck.shells import shell
 | 
			
		||||
 | 
			
		||||
@git_support
 | 
			
		||||
def match(command):
 | 
			
		||||
    return ('did not match any file(s) known to git.' in command.output
 | 
			
		||||
    return ('did not match any file(s) known to git' in command.output
 | 
			
		||||
            and "Did you forget to 'git add'?" not in command.output)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -18,10 +18,12 @@ def get_branches():
 | 
			
		||||
        stdout=subprocess.PIPE)
 | 
			
		||||
    for line in proc.stdout.readlines():
 | 
			
		||||
        line = line.decode('utf-8')
 | 
			
		||||
        if '->' in line:    # Remote HEAD like b'  remotes/origin/HEAD -> origin/master'
 | 
			
		||||
            continue
 | 
			
		||||
        if line.startswith('*'):
 | 
			
		||||
            line = line.split(' ')[1]
 | 
			
		||||
        if '/' in line:
 | 
			
		||||
            line = line.split('/')[-1]
 | 
			
		||||
        if line.strip().startswith('remotes/'):
 | 
			
		||||
            line = '/'.join(line.split('/')[2:])
 | 
			
		||||
        yield line.strip()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -29,13 +31,19 @@ def get_branches():
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    missing_file = re.findall(
 | 
			
		||||
        r"error: pathspec '([^']*)' "
 | 
			
		||||
        r"did not match any file\(s\) known to git.", command.output)[0]
 | 
			
		||||
        r"did not match any file\(s\) known to git", command.output)[0]
 | 
			
		||||
    closest_branch = utils.get_closest(missing_file, get_branches(),
 | 
			
		||||
                                       fallback_to_first=False)
 | 
			
		||||
 | 
			
		||||
    new_commands = []
 | 
			
		||||
 | 
			
		||||
    if closest_branch:
 | 
			
		||||
        return replace_argument(command.script, missing_file, closest_branch)
 | 
			
		||||
    elif command.script_parts[1] == 'checkout':
 | 
			
		||||
        return replace_argument(command.script, 'checkout', 'checkout -b')
 | 
			
		||||
    else:
 | 
			
		||||
        return shell.and_('git branch {}', '{}').format(
 | 
			
		||||
            missing_file, command.script)
 | 
			
		||||
        new_commands.append(replace_argument(command.script, missing_file, closest_branch))
 | 
			
		||||
    if command.script_parts[1] == 'checkout':
 | 
			
		||||
        new_commands.append(replace_argument(command.script, 'checkout', 'checkout -b'))
 | 
			
		||||
 | 
			
		||||
    if not new_commands:
 | 
			
		||||
        new_commands.append(shell.and_('git branch {}', '{}').format(
 | 
			
		||||
            missing_file, command.script))
 | 
			
		||||
 | 
			
		||||
    return new_commands
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								thefuck/rules/git_commit_reset.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								thefuck/rules/git_commit_reset.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
from thefuck.specific.git import git_support
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@git_support
 | 
			
		||||
def match(command):
 | 
			
		||||
    return ('commit' in command.script_parts)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@git_support
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    return 'git reset HEAD~'
 | 
			
		||||
							
								
								
									
										28
									
								
								thefuck/rules/go_unknown_command.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								thefuck/rules/go_unknown_command.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
from itertools import dropwhile, islice, takewhile
 | 
			
		||||
import subprocess
 | 
			
		||||
 | 
			
		||||
from thefuck.utils import get_closest, replace_argument, for_app, which, cache
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_golang_commands():
 | 
			
		||||
    proc = subprocess.Popen('go', stderr=subprocess.PIPE)
 | 
			
		||||
    lines = [line.decode('utf-8').strip() for line in proc.stderr.readlines()]
 | 
			
		||||
    lines = dropwhile(lambda line: line != 'The commands are:', lines)
 | 
			
		||||
    lines = islice(lines, 2, None)
 | 
			
		||||
    lines = takewhile(lambda line: line, lines)
 | 
			
		||||
    return [line.split(' ')[0] for line in lines]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if which('go'):
 | 
			
		||||
    get_docker_commands = cache(which('go'))(get_golang_commands)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@for_app('go')
 | 
			
		||||
def match(command):
 | 
			
		||||
    return 'unknown command' in command.output
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    closest_subcommand = get_closest(command.script_parts[1], get_golang_commands())
 | 
			
		||||
    return replace_argument(command.script, command.script_parts[1],
 | 
			
		||||
                            closest_subcommand)
 | 
			
		||||
							
								
								
									
										15
									
								
								thefuck/rules/nixos_cmd_not_found.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								thefuck/rules/nixos_cmd_not_found.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
import re
 | 
			
		||||
from thefuck.specific.nix import nix_available
 | 
			
		||||
from thefuck.shells import shell
 | 
			
		||||
 | 
			
		||||
regex = re.compile(r'nix-env -iA ([^\s]*)')
 | 
			
		||||
enabled_by_default = nix_available
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def match(command):
 | 
			
		||||
    return regex.findall(command.output)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    name = regex.findall(command.output)[0]
 | 
			
		||||
    return shell.and_('nix-env -iA {}'.format(name), command.script)
 | 
			
		||||
@@ -6,7 +6,8 @@ from thefuck.specific.sudo import sudo_support
 | 
			
		||||
@sudo_support
 | 
			
		||||
def match(command):
 | 
			
		||||
    return (not which(command.script_parts[0])
 | 
			
		||||
            and 'not found' in command.output
 | 
			
		||||
            and ('not found' in command.output
 | 
			
		||||
                 or 'is not recognized as' in command.output)
 | 
			
		||||
            and bool(get_close_matches(command.script_parts[0],
 | 
			
		||||
                                       get_all_executables())))
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
""" Fixes wrong package names with pacman or yaourt.
 | 
			
		||||
 | 
			
		||||
For example the `llc` program is in package `llvm` so this:
 | 
			
		||||
    yaourt -S llc
 | 
			
		||||
    yay -S llc
 | 
			
		||||
should be:
 | 
			
		||||
    yaourt -S llvm
 | 
			
		||||
    yay -S llvm
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from thefuck.utils import replace_command
 | 
			
		||||
@@ -12,7 +12,7 @@ from thefuck.specific.archlinux import get_pkgfile, archlinux_env
 | 
			
		||||
 | 
			
		||||
def match(command):
 | 
			
		||||
    return (command.script_parts
 | 
			
		||||
            and (command.script_parts[0] in ('pacman', 'yaourt')
 | 
			
		||||
            and (command.script_parts[0] in ('pacman', 'yay', 'yaourt')
 | 
			
		||||
                 or command.script_parts[0:2] == ['sudo', 'pacman'])
 | 
			
		||||
            and 'error: target not found:' in command.output)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								thefuck/rules/pip_install.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								thefuck/rules/pip_install.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
from thefuck.utils import for_app
 | 
			
		||||
from thefuck.specific.sudo import sudo_support
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@sudo_support
 | 
			
		||||
@for_app('pip')
 | 
			
		||||
def match(command):
 | 
			
		||||
    return ('pip install' in command.script and 'Permission denied' in command.output)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    if '--user' not in command.script:  # add --user (attempt 1)
 | 
			
		||||
        return command.script.replace(' install ', ' install --user ')
 | 
			
		||||
 | 
			
		||||
    return 'sudo {}'.format(command.script.replace(' --user', ''))  # since --user didn't fix things, let's try sudo (attempt 2)
 | 
			
		||||
@@ -12,8 +12,8 @@ def match(command):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    broken_cmd = re.findall(r'ERROR: unknown command \"([a-z]+)\"',
 | 
			
		||||
    broken_cmd = re.findall(r'ERROR: unknown command "([^"]+)"',
 | 
			
		||||
                            command.output)[0]
 | 
			
		||||
    new_cmd = re.findall(r'maybe you meant \"([a-z]+)\"', command.output)[0]
 | 
			
		||||
    new_cmd = re.findall(r'maybe you meant "([^"]+)"', command.output)[0]
 | 
			
		||||
 | 
			
		||||
    return replace_argument(command.script, broken_cmd, new_cmd)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										33
									
								
								thefuck/rules/pyenv_no_such_command.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								thefuck/rules/pyenv_no_such_command.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
import re
 | 
			
		||||
from subprocess import PIPE, Popen
 | 
			
		||||
 | 
			
		||||
from thefuck.utils import (cache, for_app, replace_argument, replace_command,
 | 
			
		||||
                           which)
 | 
			
		||||
 | 
			
		||||
COMMON_TYPOS = {
 | 
			
		||||
    'list': ['versions', 'install --list'],
 | 
			
		||||
    'remove': ['uninstall'],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@for_app('pyenv')
 | 
			
		||||
def match(command):
 | 
			
		||||
    return 'pyenv: no such command' in command.output
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_pyenv_commands():
 | 
			
		||||
    proc = Popen(['pyenv', 'commands'], stdout=PIPE)
 | 
			
		||||
    return [line.decode('utf-8').strip() for line in proc.stdout.readlines()]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if which('pyenv'):
 | 
			
		||||
    get_pyenv_commands = cache(which('pyenv'))(get_pyenv_commands)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@for_app('pyenv')
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    broken = re.findall(r"pyenv: no such command `([^']*)'", command.output)[0]
 | 
			
		||||
    matched = [replace_argument(command.script, broken, common_typo)
 | 
			
		||||
               for common_typo in COMMON_TYPOS.get(broken, [])]
 | 
			
		||||
    matched.extend(replace_command(command, broken, get_pyenv_commands()))
 | 
			
		||||
    return matched
 | 
			
		||||
							
								
								
									
										22
									
								
								thefuck/rules/remove_shell_prompt_literal.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								thefuck/rules/remove_shell_prompt_literal.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
"""Fixes error for commands containing the shell prompt symbol '$'.
 | 
			
		||||
 | 
			
		||||
This usually happens when commands are copied from documentations
 | 
			
		||||
including them in their code blocks.
 | 
			
		||||
 | 
			
		||||
Example:
 | 
			
		||||
> $ git clone https://github.com/nvbn/thefuck.git
 | 
			
		||||
bash: $: command not found...
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def match(command):
 | 
			
		||||
    return (
 | 
			
		||||
        "$: command not found" in command.output
 | 
			
		||||
        and re.search(r"^[\s]*\$ [\S]+", command.script) is not None
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    return command.script.replace("$", "", 1).strip()
 | 
			
		||||
@@ -21,7 +21,7 @@ patterns = ['permission denied',
 | 
			
		||||
            'edspermissionerror',
 | 
			
		||||
            'you don\'t have write permissions',
 | 
			
		||||
            'use `sudo`',
 | 
			
		||||
            'SudoRequiredError',
 | 
			
		||||
            'sudorequirederror',
 | 
			
		||||
            'error: insufficient privileges']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,22 +2,56 @@
 | 
			
		||||
from thefuck.utils import memoize, get_alias
 | 
			
		||||
 | 
			
		||||
target_layout = '''qwertyuiop[]asdfghjkl;'zxcvbnm,./QWERTYUIOP{}ASDFGHJKL:"ZXCVBNM<>?'''
 | 
			
		||||
# any new keyboard layout must be appended
 | 
			
		||||
 | 
			
		||||
greek = u''';ςερτυθιοπ[]ασδφγηξκλ΄ζχψωβνμ,./:΅ΕΡΤΥΘΙΟΠ{}ΑΣΔΦΓΗΞΚΛ¨"ΖΧΨΩΒΝΜ<>?'''
 | 
			
		||||
korean = u'''ㅂㅈㄷㄱㅅㅛㅕㅑㅐㅔ[]ㅁㄴㅇㄹㅎㅗㅓㅏㅣ;'ㅋㅌㅊㅍㅠㅜㅡ,./ㅃㅉㄸㄲㅆㅛㅕㅑㅒㅖ{}ㅁㄴㅇㄹㅎㅗㅓㅏㅣ:"ㅋㅌㅊㅍㅠㅜㅡ<>?'''
 | 
			
		||||
 | 
			
		||||
source_layouts = [u'''йцукенгшщзхъфывапролджэячсмитьбю.ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ,''',
 | 
			
		||||
                  u'''йцукенгшщзхїфівапролджєячсмитьбю.ЙЦУКЕНГШЩЗХЇФІВАПРОЛДЖЄЯЧСМИТЬБЮ,''',
 | 
			
		||||
                  u'''ضصثقفغعهخحجچشسیبلاتنمکگظطزرذدپو./ًٌٍَُِّْ][}{ؤئيإأآة»«:؛كٓژٰٔء><؟''',
 | 
			
		||||
                  u''';ςερτυθιοπ[]ασδφγηξκλ΄ζχψωβνμ,./:΅ΕΡΤΥΘΙΟΠ{}ΑΣΔΦΓΗΞΚΛ¨"ΖΧΨΩΒΝΜ<>?''',
 | 
			
		||||
                  u'''/'קראטוןםפ][שדגכעיחלךף,זסבהנמצתץ.QWERTYUIOP{}ASDFGHJKL:"ZXCVBNM<>?''']
 | 
			
		||||
                  u'''/'קראטוןםפ][שדגכעיחלךף,זסבהנמצתץ.QWERTYUIOP{}ASDFGHJKL:"ZXCVBNM<>?''',
 | 
			
		||||
                  greek,
 | 
			
		||||
                  korean]
 | 
			
		||||
 | 
			
		||||
source_to_target = {
 | 
			
		||||
    greek: {u';': "q", u'ς': "w", u'ε': "e", u'ρ': "r", u'τ': "t", u'υ': "y",
 | 
			
		||||
            u'θ': "u", u'ι': "i", u'ο': "o", u'π': "p", u'[': "[", u']': "]",
 | 
			
		||||
            u'α': "a", u'σ': "s", u'δ': "d", u'φ': "f", u'γ': "g", u'η': "h",
 | 
			
		||||
            u'ξ': "j", u'κ': "k", u'λ': "l", u'΄': "'", u'ζ': "z", u'χ': "x",
 | 
			
		||||
            u'ψ': "c", u'ω': "v", u'β': "b", u'ν': "n", u'μ': "m", u',': ",",
 | 
			
		||||
            u'.': ".", u'/': "/", u':': "Q", u'΅': "W", u'Ε': "E", u'Ρ': "R",
 | 
			
		||||
            u'Τ': "T", u'Υ': "Y", u'Θ': "U", u'Ι': "I", u'Ο': "O", u'Π': "P",
 | 
			
		||||
            u'{': "{", u'}': "}", u'Α': "A", u'Σ': "S", u'Δ': "D", u'Φ': "F",
 | 
			
		||||
            u'Γ': "G", u'Η': "H", u'Ξ': "J", u'Κ': "K", u'Λ': "L", u'¨': ":",
 | 
			
		||||
            u'"': '"', u'Ζ': "Z", u'Χ': "X", u'Ψ': "C", u'Ω': "V", u'Β': "B",
 | 
			
		||||
            u'Ν': "N", u'Μ': "M", u'<': "<", u'>': ">", u'?': "?", u'ά': "a",
 | 
			
		||||
            u'έ': "e", u'ύ': "y", u'ί': "i", u'ό': "o", u'ή': 'h', u'ώ': u"v",
 | 
			
		||||
            u'Ά': "A", u'Έ': "E", u'Ύ': "Y", u'Ί': "I", u'Ό': "O", u'Ή': "H",
 | 
			
		||||
            u'Ώ': "V"},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
'''Lists used for decomposing korean letters.'''
 | 
			
		||||
HEAD_LIST = [u'ㄱ', u'ㄲ', u'ㄴ', u'ㄷ', u'ㄸ', u'ㄹ', u'ㅁ', u'ㅂ', u'ㅃ', u'ㅅ', u'ㅆ',
 | 
			
		||||
             u'ㅇ', u'ㅈ', u'ㅉ', u'ㅊ', u'ㅋ', u'ㅌ', u'ㅍ', u'ㅎ']
 | 
			
		||||
BODY_LIST = [u'ㅏ', u'ㅐ', u'ㅑ', u'ㅒ', u'ㅓ', u'ㅔ', u'ㅕ', u'ㅖ', u'ㅗ', u'ㅘ', u'ㅙ',
 | 
			
		||||
             u'ㅚ', u'ㅛ', u'ㅜ', u'ㅝ', u'ㅞ', u'ㅟ', u'ㅠ', u'ㅡ', u'ㅢ', u'ㅣ']
 | 
			
		||||
TAIL_LIST = [u' ', u'ㄱ', u'ㄲ', u'ㄳ', u'ㄴ', u'ㄵ', u'ㄶ', u'ㄷ', u'ㄹ', u'ㄺ', u'ㄻ',
 | 
			
		||||
             u'ㄼ', u'ㄽ', u'ㄾ', u'ㄿ', u'ㅀ', u'ㅁ', u'ㅂ', u'ㅄ', u'ㅅ', u'ㅆ', u'ㅇ', u'ㅈ',
 | 
			
		||||
             u'ㅊ', u'ㅋ', u'ㅌ', u'ㅍ', u'ㅎ']
 | 
			
		||||
DOUBLE_LIST = [u'ㅘ', u'ㅙ', u'ㅚ', u'ㅝ', u'ㅞ', u'ㅟ', u'ㅢ', u'ㄳ', u'ㄵ', u'ㄶ', u'ㄺ',
 | 
			
		||||
               u'ㄻ', u'ㄼ', u'ㄽ', u'ㄾ', u'ㅀ', u'ㅄ']
 | 
			
		||||
DOUBLE_MOD_LIST = [u'ㅗㅏ', u'ㅗㅐ', u'ㅗㅣ', u'ㅜㅓ', u'ㅜㅔ', u'ㅜㅣ', u'ㅡㅣ', u'ㄱㅅ',
 | 
			
		||||
                   u'ㄴㅈ', u'ㄴㅎ', u'ㄹㄱ', u'ㄹㅁ', u'ㄹㅂ', u'ㄹㅅ', u'ㄹㅌ', u'ㄹㅎ', u'ㅂㅅ']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@memoize
 | 
			
		||||
def _get_matched_layout(command):
 | 
			
		||||
    # don't use command.split_script here because a layout mismatch will likely
 | 
			
		||||
    # result in a non-splitable sript as per shlex
 | 
			
		||||
    # result in a non-splitable script as per shlex
 | 
			
		||||
    cmd = command.script.split(' ')
 | 
			
		||||
    for source_layout in source_layouts:
 | 
			
		||||
        is_all_match = True
 | 
			
		||||
 | 
			
		||||
        for cmd_part in cmd:
 | 
			
		||||
            if not all([ch in source_layout or ch in '-_' for ch in cmd_part]):
 | 
			
		||||
                is_all_match = False
 | 
			
		||||
@@ -30,22 +64,54 @@ def _get_matched_layout(command):
 | 
			
		||||
def _switch(ch, layout):
 | 
			
		||||
    if ch in layout:
 | 
			
		||||
        return target_layout[layout.index(ch)]
 | 
			
		||||
    else:
 | 
			
		||||
        return ch
 | 
			
		||||
    return ch
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _switch_command(command, layout):
 | 
			
		||||
    # Layouts with different amount of characters than English
 | 
			
		||||
    if layout in source_to_target:
 | 
			
		||||
        return ''.join(source_to_target[layout].get(ch, ch)
 | 
			
		||||
                       for ch in command.script)
 | 
			
		||||
 | 
			
		||||
    return ''.join(_switch(ch, layout) for ch in command.script)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _decompose_korean(command):
 | 
			
		||||
    def _change_double(ch):
 | 
			
		||||
        if ch in DOUBLE_LIST:
 | 
			
		||||
            return DOUBLE_MOD_LIST[DOUBLE_LIST.index(ch)]
 | 
			
		||||
        return ch
 | 
			
		||||
 | 
			
		||||
    hg_str = u''
 | 
			
		||||
    for ch in command.script:
 | 
			
		||||
        if u'가' <= ch <= u'힣':
 | 
			
		||||
            ord_ch = ord(ch) - ord(u'가')
 | 
			
		||||
            hd = ord_ch // 588
 | 
			
		||||
            bd = (ord_ch - 588 * hd) // 28
 | 
			
		||||
            tl = ord_ch - 588 * hd - 28 * bd
 | 
			
		||||
            for ch in [HEAD_LIST[hd], BODY_LIST[bd], TAIL_LIST[tl]]:
 | 
			
		||||
                if ch != ' ':
 | 
			
		||||
                    hg_str += _change_double(ch)
 | 
			
		||||
        else:
 | 
			
		||||
            hg_str += _change_double(ch)
 | 
			
		||||
    return hg_str
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def match(command):
 | 
			
		||||
    if 'not found' not in command.output:
 | 
			
		||||
        return False
 | 
			
		||||
    if any(u'ㄱ' <= ch <= u'ㅎ' or u'ㅏ' <= ch <= u'ㅣ' or u'가' <= ch <= u'힣'
 | 
			
		||||
            for ch in command.script):
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    matched_layout = _get_matched_layout(command)
 | 
			
		||||
    return (matched_layout and
 | 
			
		||||
            _switch_command(command, matched_layout) != get_alias())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    if any(u'ㄱ' <= ch <= u'ㅎ' or u'ㅏ' <= ch <= u'ㅣ' or u'가' <= ch <= u'힣'
 | 
			
		||||
            for ch in command.script):
 | 
			
		||||
        command.script = _decompose_korean(command)
 | 
			
		||||
    matched_layout = _get_matched_layout(command)
 | 
			
		||||
    return _switch_command(command, matched_layout)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								thefuck/rules/terraform_init.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								thefuck/rules/terraform_init.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
from thefuck.shells import shell
 | 
			
		||||
from thefuck.utils import for_app
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@for_app('terraform')
 | 
			
		||||
def match(command):
 | 
			
		||||
    return ('this module is not yet installed' in command.output.lower() or
 | 
			
		||||
            'initialization required' in command.output.lower()
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    return shell.and_('terraform init', command.script)
 | 
			
		||||
@@ -9,6 +9,6 @@ def match(command):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    path = path = re.findall(
 | 
			
		||||
    path = re.findall(
 | 
			
		||||
        r"touch: (?:cannot touch ')?(.+)/.+'?:", command.output)[0]
 | 
			
		||||
    return shell.and_(u'mkdir -p {}'.format(path), command.script)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										39
									
								
								thefuck/rules/yum_invalid_operation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								thefuck/rules/yum_invalid_operation.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
import subprocess
 | 
			
		||||
from itertools import dropwhile, islice, takewhile
 | 
			
		||||
 | 
			
		||||
from thefuck.specific.sudo import sudo_support
 | 
			
		||||
from thefuck.specific.yum import yum_available
 | 
			
		||||
from thefuck.utils import for_app, replace_command, which, cache
 | 
			
		||||
 | 
			
		||||
enabled_by_default = yum_available
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@sudo_support
 | 
			
		||||
@for_app('yum')
 | 
			
		||||
def match(command):
 | 
			
		||||
    return 'No such command: ' in command.output
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _get_operations():
 | 
			
		||||
    proc = subprocess.Popen('yum', stdout=subprocess.PIPE)
 | 
			
		||||
 | 
			
		||||
    lines = proc.stdout.readlines()
 | 
			
		||||
    lines = [line.decode('utf-8') for line in lines]
 | 
			
		||||
    lines = dropwhile(lambda line: not line.startswith("List of Commands:"), lines)
 | 
			
		||||
    lines = islice(lines, 2, None)
 | 
			
		||||
    lines = list(takewhile(lambda line: line.strip(), lines))
 | 
			
		||||
    return [line.strip().split(' ')[0] for line in lines]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if which('yum'):
 | 
			
		||||
    _get_operations = cache(which('yum'))(_get_operations)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@sudo_support
 | 
			
		||||
def get_new_command(command):
 | 
			
		||||
    invalid_operation = command.script_parts[1]
 | 
			
		||||
 | 
			
		||||
    if invalid_operation == 'uninstall':
 | 
			
		||||
        return [command.script.replace('uninstall', 'remove')]
 | 
			
		||||
 | 
			
		||||
    return replace_command(command, invalid_operation, _get_operations())
 | 
			
		||||
@@ -9,6 +9,8 @@ from .generic import Generic
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Bash(Generic):
 | 
			
		||||
    friendly_name = 'Bash'
 | 
			
		||||
 | 
			
		||||
    def app_alias(self, alias_name):
 | 
			
		||||
        # It is VERY important to have the variables declared WITHIN the function
 | 
			
		||||
        return '''
 | 
			
		||||
@@ -20,8 +22,8 @@ class Bash(Generic):
 | 
			
		||||
                export TF_HISTORY=$(fc -ln -10);
 | 
			
		||||
                export PYTHONIOENCODING=utf-8;
 | 
			
		||||
                TF_CMD=$(
 | 
			
		||||
                    thefuck {argument_placeholder} $@
 | 
			
		||||
                ) && eval $TF_CMD;
 | 
			
		||||
                    thefuck {argument_placeholder} "$@"
 | 
			
		||||
                ) && eval "$TF_CMD";
 | 
			
		||||
                unset TF_HISTORY;
 | 
			
		||||
                export PYTHONIOENCODING=$TF_PYTHONIOENCODING;
 | 
			
		||||
                {alter_history}
 | 
			
		||||
@@ -79,13 +81,12 @@ class Bash(Generic):
 | 
			
		||||
            config = 'bash config'
 | 
			
		||||
 | 
			
		||||
        return self._create_shell_configuration(
 | 
			
		||||
            content=u'eval $(thefuck --alias)',
 | 
			
		||||
            content=u'eval "$(thefuck --alias)"',
 | 
			
		||||
            path=config,
 | 
			
		||||
            reload=u'source {}'.format(config))
 | 
			
		||||
 | 
			
		||||
    def info(self):
 | 
			
		||||
        """Returns the name and version of the current shell"""
 | 
			
		||||
    def _get_version(self):
 | 
			
		||||
        """Returns the version of the current shell"""
 | 
			
		||||
        proc = Popen(['bash', '-c', 'echo $BASH_VERSION'],
 | 
			
		||||
                     stdout=PIPE, stderr=DEVNULL)
 | 
			
		||||
        version = proc.stdout.read().decode('utf-8').strip()
 | 
			
		||||
        return u'Bash {}'.format(version)
 | 
			
		||||
        return proc.stdout.read().decode('utf-8').strip()
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ import sys
 | 
			
		||||
import six
 | 
			
		||||
from .. import logs
 | 
			
		||||
from ..conf import settings
 | 
			
		||||
from ..const import ARGUMENT_PLACEHOLDER
 | 
			
		||||
from ..utils import DEVNULL, cache
 | 
			
		||||
from .generic import Generic
 | 
			
		||||
 | 
			
		||||
@@ -37,13 +38,15 @@ def _get_aliases(overridden):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Fish(Generic):
 | 
			
		||||
    friendly_name = 'Fish Shell'
 | 
			
		||||
 | 
			
		||||
    def _get_overridden_aliases(self):
 | 
			
		||||
        overridden = os.environ.get('THEFUCK_OVERRIDDEN_ALIASES',
 | 
			
		||||
                                    os.environ.get('TF_OVERRIDDEN_ALIASES', ''))
 | 
			
		||||
        default = {'cd', 'grep', 'ls', 'man', 'open'}
 | 
			
		||||
        for alias in overridden.split(','):
 | 
			
		||||
            default.add(alias.strip())
 | 
			
		||||
        return default
 | 
			
		||||
        return sorted(default)
 | 
			
		||||
 | 
			
		||||
    def app_alias(self, alias_name):
 | 
			
		||||
        if settings.alter_history:
 | 
			
		||||
@@ -56,11 +59,11 @@ class Fish(Generic):
 | 
			
		||||
        return ('function {0} -d "Correct your previous console command"\n'
 | 
			
		||||
                '  set -l fucked_up_command $history[1]\n'
 | 
			
		||||
                '  env TF_SHELL=fish TF_ALIAS={0} PYTHONIOENCODING=utf-8'
 | 
			
		||||
                ' thefuck $fucked_up_command | read -l unfucked_command\n'
 | 
			
		||||
                ' thefuck $fucked_up_command {2} $argv | read -l unfucked_command\n'
 | 
			
		||||
                '  if [ "$unfucked_command" != "" ]\n'
 | 
			
		||||
                '    eval $unfucked_command\n{1}'
 | 
			
		||||
                '  end\n'
 | 
			
		||||
                'end').format(alias_name, alter_history)
 | 
			
		||||
                'end').format(alias_name, alter_history, ARGUMENT_PLACEHOLDER)
 | 
			
		||||
 | 
			
		||||
    def get_aliases(self):
 | 
			
		||||
        overridden = self._get_overridden_aliases()
 | 
			
		||||
@@ -103,12 +106,10 @@ class Fish(Generic):
 | 
			
		||||
            path='~/.config/fish/config.fish',
 | 
			
		||||
            reload='fish')
 | 
			
		||||
 | 
			
		||||
    def info(self):
 | 
			
		||||
        """Returns the name and version of the current shell"""
 | 
			
		||||
        proc = Popen(['fish', '-c', 'echo $FISH_VERSION'],
 | 
			
		||||
                     stdout=PIPE, stderr=DEVNULL)
 | 
			
		||||
        version = proc.stdout.read().decode('utf-8').strip()
 | 
			
		||||
        return u'Fish Shell {}'.format(version)
 | 
			
		||||
    def _get_version(self):
 | 
			
		||||
        """Returns the version of the current shell"""
 | 
			
		||||
        proc = Popen(['fish', '--version'], stdout=PIPE, stderr=DEVNULL)
 | 
			
		||||
        return proc.stdout.read().decode('utf-8').split()[-1]
 | 
			
		||||
 | 
			
		||||
    def put_to_history(self, command):
 | 
			
		||||
        try:
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,8 @@ ShellConfiguration = namedtuple('ShellConfiguration', (
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Generic(object):
 | 
			
		||||
    friendly_name = 'Generic Shell'
 | 
			
		||||
 | 
			
		||||
    def get_aliases(self):
 | 
			
		||||
        return {}
 | 
			
		||||
 | 
			
		||||
@@ -34,8 +36,8 @@ class Generic(object):
 | 
			
		||||
        return command_script
 | 
			
		||||
 | 
			
		||||
    def app_alias(self, alias_name):
 | 
			
		||||
        return "alias {0}='eval $(TF_ALIAS={0} PYTHONIOENCODING=utf-8 " \
 | 
			
		||||
               "thefuck $(fc -ln -1))'".format(alias_name)
 | 
			
		||||
        return """alias {0}='eval "$(TF_ALIAS={0} PYTHONIOENCODING=utf-8 """ \
 | 
			
		||||
               """thefuck "$(fc -ln -1)")"'""".format(alias_name)
 | 
			
		||||
 | 
			
		||||
    def instant_mode_alias(self, alias_name):
 | 
			
		||||
        warn("Instant mode not supported by your shell")
 | 
			
		||||
@@ -131,9 +133,18 @@ class Generic(object):
 | 
			
		||||
                'type', 'typeset', 'ulimit', 'umask', 'unalias', 'unset',
 | 
			
		||||
                'until', 'wait', 'while']
 | 
			
		||||
 | 
			
		||||
    def _get_version(self):
 | 
			
		||||
        """Returns the version of the current shell"""
 | 
			
		||||
        return ''
 | 
			
		||||
 | 
			
		||||
    def info(self):
 | 
			
		||||
        """Returns the name and version of the current shell"""
 | 
			
		||||
        return 'Generic Shell'
 | 
			
		||||
        try:
 | 
			
		||||
            version = self._get_version()
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            warn(u'Could not determine shell version: {}'.format(e))
 | 
			
		||||
            version = ''
 | 
			
		||||
        return u'{} {}'.format(self.friendly_name, version).rstrip()
 | 
			
		||||
 | 
			
		||||
    def _create_shell_configuration(self, content, path, reload):
 | 
			
		||||
        return ShellConfiguration(
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,11 @@
 | 
			
		||||
from subprocess import Popen, PIPE
 | 
			
		||||
from ..utils import DEVNULL
 | 
			
		||||
from .generic import Generic, ShellConfiguration
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Powershell(Generic):
 | 
			
		||||
    friendly_name = 'PowerShell'
 | 
			
		||||
 | 
			
		||||
    def app_alias(self, alias_name):
 | 
			
		||||
        return 'function ' + alias_name + ' {\n' \
 | 
			
		||||
               '    $history = (Get-History -Count 1).CommandLine;\n' \
 | 
			
		||||
@@ -20,7 +24,20 @@ class Powershell(Generic):
 | 
			
		||||
 | 
			
		||||
    def how_to_configure(self):
 | 
			
		||||
        return ShellConfiguration(
 | 
			
		||||
            content=u'iex "thefuck --alias"',
 | 
			
		||||
            content=u'iex "$(thefuck --alias)"',
 | 
			
		||||
            path='$profile',
 | 
			
		||||
            reload='& $profile',
 | 
			
		||||
            reload='. $profile',
 | 
			
		||||
            can_configure_automatically=False)
 | 
			
		||||
 | 
			
		||||
    def _get_version(self):
 | 
			
		||||
        """Returns the version of the current shell"""
 | 
			
		||||
        try:
 | 
			
		||||
            proc = Popen(
 | 
			
		||||
                ['powershell.exe', '$PSVersionTable.PSVersion'],
 | 
			
		||||
                stdout=PIPE,
 | 
			
		||||
                stderr=DEVNULL)
 | 
			
		||||
            version = proc.stdout.read().decode('utf-8').rstrip().split('\n')
 | 
			
		||||
            return '.'.join(version[-1].split())
 | 
			
		||||
        except IOError:
 | 
			
		||||
            proc = Popen(['pwsh', '--version'], stdout=PIPE, stderr=DEVNULL)
 | 
			
		||||
            return proc.stdout.read().decode('utf-8').split()[-1]
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,8 @@ from .generic import Generic
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Tcsh(Generic):
 | 
			
		||||
    friendly_name = 'Tcsh'
 | 
			
		||||
 | 
			
		||||
    def app_alias(self, alias_name):
 | 
			
		||||
        return ("alias {0} 'setenv TF_SHELL tcsh && setenv TF_ALIAS {0} && "
 | 
			
		||||
                "set fucked_cmd=`history -h 2 | head -n 1` && "
 | 
			
		||||
@@ -35,3 +37,8 @@ class Tcsh(Generic):
 | 
			
		||||
            content=u'eval `thefuck --alias`',
 | 
			
		||||
            path='~/.tcshrc',
 | 
			
		||||
            reload='tcsh')
 | 
			
		||||
 | 
			
		||||
    def _get_version(self):
 | 
			
		||||
        """Returns the version of the current shell"""
 | 
			
		||||
        proc = Popen(['tcsh', '--version'], stdout=PIPE, stderr=DEVNULL)
 | 
			
		||||
        return proc.stdout.read().decode('utf-8').split()[1]
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,8 @@ from .generic import Generic
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Zsh(Generic):
 | 
			
		||||
    friendly_name = 'ZSH'
 | 
			
		||||
 | 
			
		||||
    def app_alias(self, alias_name):
 | 
			
		||||
        # It is VERY important to have the variables declared WITHIN the function
 | 
			
		||||
        return '''
 | 
			
		||||
@@ -87,9 +89,8 @@ class Zsh(Generic):
 | 
			
		||||
            path='~/.zshrc',
 | 
			
		||||
            reload='source ~/.zshrc')
 | 
			
		||||
 | 
			
		||||
    def info(self):
 | 
			
		||||
        """Returns the name and version of the current shell"""
 | 
			
		||||
    def _get_version(self):
 | 
			
		||||
        """Returns the version of the current shell"""
 | 
			
		||||
        proc = Popen(['zsh', '-c', 'echo $ZSH_VERSION'],
 | 
			
		||||
                     stdout=PIPE, stderr=DEVNULL)
 | 
			
		||||
        version = proc.stdout.read().decode('utf-8').strip()
 | 
			
		||||
        return u'ZSH {}'.format(version)
 | 
			
		||||
        return proc.stdout.read().decode('utf-8').strip()
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,9 @@ def get_pkgfile(command):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def archlinux_env():
 | 
			
		||||
    if utils.which('yaourt'):
 | 
			
		||||
    if utils.which('yay'):
 | 
			
		||||
        pacman = 'yay'
 | 
			
		||||
    elif utils.which('yaourt'):
 | 
			
		||||
        pacman = 'yaourt'
 | 
			
		||||
    elif utils.which('pacman'):
 | 
			
		||||
        pacman = 'sudo pacman'
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								thefuck/specific/nix.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								thefuck/specific/nix.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
from thefuck.utils import which
 | 
			
		||||
 | 
			
		||||
nix_available = bool(which('nix'))
 | 
			
		||||
							
								
								
									
										3
									
								
								thefuck/specific/yum.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								thefuck/specific/yum.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
from thefuck.utils import which
 | 
			
		||||
 | 
			
		||||
yum_available = bool(which('yum'))
 | 
			
		||||
@@ -52,7 +52,7 @@ class CommandSelector(object):
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def value(self):
 | 
			
		||||
        """:rtype hefuck.types.CorrectedCommand"""
 | 
			
		||||
        """:rtype thefuck.types.CorrectedCommand"""
 | 
			
		||||
        return self._commands[self._index]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -98,7 +98,7 @@ def get_closest(word, possibilities, cutoff=0.6, fallback_to_first=True):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_close_matches(word, possibilities, n=None, cutoff=0.6):
 | 
			
		||||
    """Overrides `difflib.get_close_match` to controle argument `n`."""
 | 
			
		||||
    """Overrides `difflib.get_close_match` to control argument `n`."""
 | 
			
		||||
    if n is None:
 | 
			
		||||
        n = settings.num_close_matches
 | 
			
		||||
    return difflib_get_close_matches(word, possibilities, n, cutoff)
 | 
			
		||||
@@ -118,7 +118,7 @@ def get_all_executables():
 | 
			
		||||
    tf_entry_points = ['thefuck', 'fuck']
 | 
			
		||||
 | 
			
		||||
    bins = [exe.name.decode('utf8') if six.PY2 else exe.name
 | 
			
		||||
            for path in os.environ.get('PATH', '').split(':')
 | 
			
		||||
            for path in os.environ.get('PATH', '').split(os.pathsep)
 | 
			
		||||
            for exe in _safe(lambda: list(Path(path).iterdir()), [])
 | 
			
		||||
            if not _safe(exe.is_dir, True)
 | 
			
		||||
            and exe.name not in tf_entry_points]
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user