1
0
mirror of https://github.com/nvbn/thefuck.git synced 2025-11-04 00:52:04 +00:00

Compare commits

..

236 Commits
2.9 ... 3.8

Author SHA1 Message Date
nvbn
c6af8409d9 Bump to 3.8 2016-04-08 14:36:53 +03:00
Vladimir Iakovlev
95e7d00aec Merge pull request #492 from scorphus/overridden-aliases
Treat overridden aliases in a better way
2016-04-07 13:09:08 +03:00
Pablo Santiago Blum de Aguiar
cdccf1881e #253: Use a better name for that env var 2016-04-06 23:11:19 -03:00
Pablo Santiago Blum de Aguiar
db6053b301 #253: Update default overridden aliases with user's 2016-04-06 22:58:08 -03:00
nvbn
183b70c8b8 Merge branch 'scorphus-git-branch-exists' 2016-04-03 14:08:26 +03:00
nvbn
5e0cc8c703 #491: yield possible fixes in git_branch_exists rule 2016-04-03 14:07:39 +03:00
nvbn
1aa2ec1795 Merge branch 'git-branch-exists' of https://github.com/scorphus/thefuck into scorphus-git-branch-exists 2016-04-03 14:02:32 +03:00
Pablo Santiago Blum de Aguiar
0c98053f74 #N/A Add a new rule git_branch_exists 2016-04-03 00:09:15 -03:00
Vladimir Iakovlev
17b2fba48d Merge pull request #489 from scorphus/improve-readme
Improve readme
2016-04-02 01:44:51 +03:00
Pablo Santiago Blum de Aguiar
43886c38ff #N/A Add more fancy badges 2016-03-31 22:07:10 -03:00
Pablo Santiago Blum de Aguiar
9070748a86 #N/A Use reference links 2016-03-31 22:06:01 -03:00
Pablo Santiago Blum de Aguiar
61de6f4a51 #N/A Reformat parts of README.md 2016-03-31 15:53:32 -03:00
Vladimir Iakovlev
d102af41d9 #488 Add AppVeyor badge 2016-03-31 04:50:40 +03:00
Vladimir Iakovlev
b7002bb9f9 Merge pull request #488 from scorphus/app-veyor
App veyor
2016-03-31 04:44:44 +03:00
Pablo Santiago Blum de Aguiar
18b4f5df6a #486: Run tests on AppVeyor 2016-03-29 23:39:53 -03:00
Pablo Santiago Blum de Aguiar
28153db4a8 #486: Ignore a test on Windows 2016-03-29 23:39:53 -03:00
Pablo Santiago Blum de Aguiar
047a1a6072 #486: Use Path instead of PosixPath 2016-03-29 23:39:53 -03:00
Pablo Santiago Blum de Aguiar
69db5c70e6 #486: Fix path joining on Windows 2016-03-29 23:39:45 -03:00
nvbn
fa1edd4bae Bump to 3.7 2016-03-23 05:12:29 +02:00
Vladimir Iakovlev
333c4b2a3f Merge pull request #483 from shakaran/patch-1
Update install procedure for pip
2016-03-23 05:11:07 +02:00
Vladimir Iakovlev
b1f10642fa Merge pull request #487 from scorphus/stdout-encoding-none
#486: Use alternative encoding when sys.stdout.encoding is None
2016-03-23 05:09:36 +02:00
Pablo Santiago Blum de Aguiar
047efd5575 #486: Use alternative encoding when sys.stdout.encoding is None
Fix #486
2016-03-22 16:13:59 -03:00
Vladimir Iakovlev
f604756cb7 Merge pull request #485 from scorphus/484-stdin-pipe
#484: Use PIPE as stdin when Popening the script
2016-03-21 22:35:18 +02:00
Pablo Santiago Blum de Aguiar
a27115bff1 #484: Use PIPE as stdin when Popening the script
Fix #484
2016-03-21 16:59:35 -03:00
Ángel Guzmán Maeso
5d00b3bc25 Update install procedure for pip
Avoid the warning:

The directory '/home/someuser/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
2016-03-21 17:48:41 +01:00
Vladimir Iakovlev
0cf4f5e8b0 Merge pull request #481 from scorphus/fix-git-add
Fix `git_add` rule
2016-03-19 12:59:22 +02:00
Pablo Santiago Blum de Aguiar
41707b80c6 #N/A: Fix git_add rule 2016-03-18 22:46:38 -03:00
Vladimir Iakovlev
3a39deb485 Merge pull request #478 from MattKotsenas/feature/powershell-shell
Add Powershell as shell
2016-03-19 02:45:26 +02:00
Matt Kotsenas
d4bc8cebf1 Replace raise with return for Ctrl+C in Windows
- Replace the raise `const.CtrlC` with `return const.CtrlC` the match the
  unix implementation and prevent a stacktrace when cancelling a command
  on Windows
2016-03-16 16:37:59 -07:00
Matt Kotsenas
6daf687237 Add Powershell as a supported shell
- There may be additional functionality to implement, but I've been
  running this way for a month with no known issues
2016-03-16 16:06:09 -07:00
Matt Kotsenas
2207dd2668 Update _get_shell to work with Windows
- _get_shell assumed the parent process would always be the shell process, in Powershell the
  parent process is Python, with the grandparent being the shell
- Switched to walking the process tree so the same code path can be used in both places
2016-03-15 14:10:04 -07:00
Vladimir Iakovlev
d1ab08a797 Merge pull request #477 from scorphus/git-rm-recursive
#N/A: Add new `git_rm_recursive` rule
2016-03-15 04:30:31 +03:00
Pablo Santiago Blum de Aguiar
51e89a36ef #N/A: Add new git_rm_recursive rule 2016-03-14 18:59:32 -03:00
nvbn
39f7cc37eb Bump to 3.6 2016-03-13 17:46:14 +03:00
nvbn
251b69b5a0 #475: Try to use already used executable in no_command 2016-03-13 15:10:37 +03:00
nvbn
8b1f078e27 Bump to 3.5 2016-03-13 03:14:18 +03:00
Vladimir Iakovlev
a47e84fa6b Merge pull request #476 from scorphus/git-help-aliased
#N/A: Add new `git_help_aliased` rule
2016-03-13 01:24:57 +03:00
Pablo Santiago Blum de Aguiar
bcab700215 #N/A: Add new git_help_aliased rule 2016-03-12 18:51:47 -03:00
Vladimir Iakovlev
4fb99fd7a8 Merge pull request #474 from scorphus/alias-variables
#301: Set variables within the alias
2016-03-10 13:25:50 +03:00
Pablo Santiago Blum de Aguiar
bb5f6bb705 #301: Set variables within the alias
Fix #301
2016-03-09 21:58:18 -03:00
Vladimir Iakovlev
d92765d5df Merge pull request #473 from scorphus/gdbm-unavailable
#439 & #447: Remove cache if created with unavailable db
2016-03-10 02:52:33 +03:00
Pablo Santiago Blum de Aguiar
d8de5cfd20 #439 & #447: Remove cache if created with unavailable db
When switching between Python versions, the database package used to
create the cache might be unavailable and an ImportError is raised,
such as `ImportError: No module named gdbm`.
2016-03-08 14:38:16 -03:00
Vladimir Iakovlev
d73b14ce4b Merge pull request #472 from PLNech/master
Rules: git remote add instead of set-url if remote does not exist
2016-03-06 13:33:14 +03:00
Paul-Louis NECH
04b83cf7e8 Rules: git remote add instead of set-url if remote does not exist
Tests: Added test for git_remote_seturl_add

Rules: renamed new rule with a more appropriate name

README: added new rule

Style: Formatting

New rule: corrected test name

Developed tests
2016-03-04 22:35:55 +01:00
nvbn
019f0abf67 Bump to 3.4 2016-03-04 00:21:51 +03:00
nvbn
c8d3dcd1bf Merge branch 'lawrencebenson-master' 2016-03-04 00:20:43 +03:00
nvbn
4f5b382df4 #471: Use parametrized tests 2016-03-04 00:20:33 +03:00
lawrencebenson
77ad68b04b Fix encoding error in source file example 2016-03-03 10:43:33 +01:00
lawrencebenson
6b0311181d Fix encoding error for Python 2 2016-03-02 23:19:22 +01:00
lawrencebenson
48808f93ac Add no hard link support for ln 2016-03-02 17:57:53 +01:00
nvbn
7ce4307c87 #402: Don't invoke bash for getting aliases 2016-03-01 01:28:21 +03:00
nvbn
f7f0660114 #402: Don't invoke zsh for getting aliases 2016-03-01 01:21:51 +03:00
nvbn
46f2351907 #N/A: zsh history doesn't update on travis-ci without manual fc -r call 2016-02-22 18:47:15 +03:00
nvbn
e9de01fa41 #N/A: Move all consts to const 2016-02-22 18:40:28 +03:00
nvbn
9b260eb239 ⚠️ #442: Change history only on shell side 2016-02-22 18:31:28 +03:00
Vladimir Iakovlev
f20d4dbf85 Merge pull request #465 from mcarton/histfile2
Let bash handle bash’s history
2016-02-22 17:31:59 +03:00
mcarton
4af7dc2748 Let bash handle bash’s history 2016-02-22 14:53:53 +01:00
Vladimir Iakovlev
c8e9606c7d Merge pull request #462 from scorphus/fish-alias
#N/A Remove fucked up cmd from history regardless of status
2016-02-22 15:48:06 +03:00
Pablo Santiago Blum de Aguiar
d71b9c2e62 #N/A Remove fucked up cmd from history regardless of status
Most fucked up commands are erroneous, but that's not always the case.
2016-02-18 15:17:46 -02:00
Vladimir Iakovlev
60497b9d04 Merge pull request #461 from mcarton/ruby-gem
Add ruby gem error message to sudo patterns
2016-02-18 12:21:54 +03:00
mcarton
619af2638a Make sudo patterns lowercase 2016-02-16 22:27:01 +01:00
mcarton
a1f15bfe5f Add ruby gem error message to sudo patterns 2016-02-16 22:26:22 +01:00
Vladimir Iakovlev
ce959b2a8b Merge pull request #458 from scorphus/anydbm
#439 #447 Except anydbm instead of gdbm for PY2
2016-02-15 14:21:37 +03:00
Pablo Santiago Blum de Aguiar
3cc4940842 #439 #447 Except anydbm instead of gdbm for PY2
Fix #439 and close #447
2016-02-14 00:43:07 -02:00
nvbn
470c0ef699 #444: Check pip version in setup.py 2016-02-12 20:11:08 +03:00
nvbn
4f95b3365a #N/A: Add grep_arguments_order rule 2016-02-08 11:04:19 +03:00
nvbn
bbfd53d718 #N/A: Use shutil.which when possible 2016-02-06 16:42:42 +03:00
nvbn
28d078708b #N/A: Check that brew/apt available in related rules 2016-02-06 16:37:11 +03:00
nvbn
778d5f3e6e #N/A: Add npm_wrong_command rule 2016-02-06 15:18:44 +03:00
Vladimir Iakovlev
c5acee54ea Merge pull request #452 from scorphus/increase-coverage
Increase coverage
2016-02-01 17:52:08 +03:00
Pablo Santiago Blum de Aguiar
c3e9c1bfc1 #N/A Completely test rules.apt_get 2016-01-31 19:55:45 -02:00
Pablo Santiago Blum de Aguiar
6c25b33b9e #N/A Add parameter and skip a test for apt_get rule 2016-01-31 19:55:45 -02:00
Pablo Santiago Blum de Aguiar
052f415d94 #N/A Completely test rules.gulp_not_task 2016-01-31 19:55:44 -02:00
Pablo Santiago Blum de Aguiar
3438d6dde7 #N/A Completely test rules.git_checkout 2016-01-31 19:55:44 -02:00
Vladimir Iakovlev
af0fe66a9f Merge pull request #441 from nvbn/simplify-shells
Split `shells` module
2016-01-31 00:04:35 +03:00
nvbn
fe07fcaa62 #441: Remove shells methods wrappers 2016-01-29 13:09:40 +03:00
nvbn
b5dc7aab6d #441: Remove all logic from shells methods wrappers 2016-01-29 12:30:31 +03:00
nvbn
a2ec5aa3ff #441: Move function for getting current alias to utils 2016-01-29 12:22:31 +03:00
nvbn
0b2bda9e85 Merge branch 'master' into simplify-shells 2016-01-29 12:15:05 +03:00
nvbn
68c882cf1a Merge branch 'fix-fish-how-to' of https://github.com/scorphus/thefuck into scorphus-fix-fish-how-to 2016-01-29 12:07:27 +03:00
nvbn
abe8fb84c6 Merge branch 'master' of github.com:nvbn/thefuck 2016-01-29 12:04:07 +03:00
nvbn
86b17eb570 Fix travis builds 2016-01-29 12:03:47 +03:00
Pablo Santiago Blum de Aguiar
dcc0ce7ff3 #449 Fix Fish.how_to_configure()
Fix #449
2016-01-28 20:47:17 -02:00
Vladimir Iakovlev
fee874cddc Merge pull request #443 from aureooms/patch-1
new pattern in sudo rule
2016-01-24 16:45:17 +03:00
Aurélien Ooms
2ce1c6bf90 new pattern in sudo rule
`pacman-key --refresh-keys` outputs the following when not run as root

```
==> ERROR: pacman-key needs to be run as root for this operation.
```
2016-01-24 14:38:13 +01:00
nvbn
9b129fad08 #N/A: Add docsting in shells 2016-01-24 04:39:27 +03:00
nvbn
20adefbe7d Merge branch 'master' into simplify-shells 2016-01-23 23:49:26 +03:00
nvbn
52ef1fa47d #438: Replace [[ with [ in install script 2016-01-23 23:48:51 +03:00
nvbn
94f8652175 #N/A: Add tests for tcsh 2016-01-23 05:06:33 +03:00
nvbn
abe287a52b #N/A: Split shells module 2016-01-23 05:06:22 +03:00
nvbn
60e19a054a #N/A: Replace PY3 checks with PY2 checks 2016-01-22 17:02:08 +03:00
Vladimir Iakovlev
45add1e3d6 Merge pull request #437 from BuBuaBu/master
Exclude recursively tests packages
2016-01-22 16:56:29 +03:00
Vladimir Iakovlev
934870f650 Merge pull request #436 from scorphus/shelve-open-errors
Fix cache problem when going from Python 3 to 2
2016-01-22 16:56:08 +03:00
BuBuaBu
738cc0c9a8 Exclude recursively tests packages 2016-01-22 13:47:31 +01:00
Pablo Santiago Blum de Aguiar
cb6f964a30 Fix cache problem when going from Python 3 to 2 2016-01-21 23:57:17 -02:00
Vladimir Iakovlev
9c9a7343de Merge pull request #435 from scorphus/cache-fish-aliases
#353 Cache Fish aliases too
2016-01-21 18:40:11 +03:00
Pablo Santiago Blum de Aguiar
3803452980 #353 Cache Fish aliases too 2016-01-20 21:43:00 -02:00
Vladimir Iakovlev
a19833d0c7 Merge pull request #434 from scorphus/433-ioencoding
#433: Set env vars right in the aliases
2016-01-17 14:00:23 +03:00
Pablo Santiago Blum de Aguiar
084b907ac0 #433: Set env vars right in the aliases
Fix #433
2016-01-16 21:35:15 -02:00
nvbn
bd5cf38271 Bump to 3.3 2016-01-13 22:33:04 +03:00
Vladimir Iakovlev
3c3d17e0ea Merge pull request #432 from nvbn/422-not-alter-history
#422: Add `alter_history` settings option
2016-01-13 22:31:19 +03:00
nvbn
2f353498de #422: Add alter_history settings option 2016-01-13 22:22:51 +03:00
Vladimir Iakovlev
f0f49c1865 Merge pull request #430 from nvbn/429-apt-invalid-operation
#429: Add `apt_invalid_operation` rule
2016-01-13 22:12:35 +03:00
nvbn
20fff3142c #429: Fix tests with python 2 2016-01-13 22:08:24 +03:00
Vladimir Iakovlev
6e22b9ec6c Merge pull request #431 from nvbn/428-readonly-history
#428: Don't fail when history is readonly
2016-01-13 22:03:31 +03:00
nvbn
d53240b777 #428: Don't fail when history is readonly 2016-01-13 22:00:20 +03:00
nvbn
cab933e7e6 #429: Add apt_invalid_operation rule 2016-01-13 21:53:11 +03:00
Vladimir Iakovlev
8b05f6d46f Merge pull request #427 from makalaaneesh/master
#425 command had to be re escaped
2016-01-08 16:38:05 +03:00
Vladimir Iakovlev
ec64fbd5ea Merge pull request #426 from web-connect/patch-1
Fixing typos
2016-01-08 16:37:23 +03:00
makalaaneesh
4f9fb796c4 fixes #425. command had to be re escaped 2016-01-08 00:50:26 +05:30
Justin Turner
be744f20ba Fixing typos 2016-01-07 09:36:37 -06:00
Vladimir Iakovlev
1b12cd85e9 Merge pull request #423 from MattKotsenas/bugfix/cd_mkdir
Add Windows error message support to cd_mkdir rule
2016-01-06 03:34:03 +03:00
Matt Kotsenas
47df80f6b8 Add Windows error message support to cd_mkdir rule
Add the Windows error message 'the system cannot find the path specified'
to the list of recognized messages for cd_mkdir.
2016-01-05 13:55:59 -08:00
Vladimir Iakovlev
a0ef0efe46 Merge pull request #419 from mcarton/fix-unzip
Fix the `dirty_unzip` rule
2015-12-30 00:58:30 +03:00
Vladimir Iakovlev
25662ad737 Merge pull request #418 from makalaaneesh/master
sudo sh execute for && in commands - preventing double sudo
2015-12-30 00:57:50 +03:00
mcarton
42b344676e Fix dirty_unzip rule on non-zip files 2015-12-29 18:46:35 +01:00
mcarton
a3e1cb6718 Fix thefuck unzip, fix #416 2015-12-29 18:38:58 +01:00
makalaaneesh
f249098336 sudo sh execute for && in commands - preventing double sudo 2015-12-23 14:35:47 +05:30
nvbn
c3b1ba7637 #415: Prevent double sudo 2015-12-11 07:41:13 +08:00
nvbn
b65a9a0a4f #414: Initialize output before any colorama import 2015-12-04 18:34:52 +08:00
nvbn
29c1d1efcf #414: Move system-dependent utils in system module 2015-12-03 20:03:27 +08:00
nvbn
0560f4ba8e #414: Install and use win_unicode_console only on windows 2015-12-01 20:15:27 +08:00
Pavel Krymets
f9aa0e7c6b Fix windows unicode output issues 2015-11-30 16:24:31 -08:00
Pavel Krymets
b18a049886 Fix getch on windows 2015-11-30 12:33:28 -08:00
nvbn
9192b555b5 Merge branch 'master' of github.com:nvbn/thefuck 2015-11-26 03:42:16 +08:00
nvbn
d750d3d6d1 #412: Add _script_from_history for generic shell 2015-11-26 03:42:03 +08:00
Vladimir Iakovlev
3ad953001d Merge pull request #411 from scorphus/unicode
Support non-ascii content in Python 2
2015-11-25 20:41:20 +08:00
Pablo Santiago Blum de Aguiar
3b4b87d8ed #398: Test PYTHONIOENCODING=utf-8 in shell aliases 2015-11-25 02:34:33 -02:00
Pablo Santiago Blum de Aguiar
6c3d67763a #398: Add PYTHONIOENCODING=utf-8 to Fish Shell alias 2015-11-25 02:34:33 -02:00
Pablo Santiago Blum de Aguiar
959680d24d #N/A Set TF_ALIAS as an environment variable
For more info, check:

http://fishshell.com/docs/current/faq.html#faq-single-env
2015-11-25 02:34:33 -02:00
Pablo Santiago Blum de Aguiar
b0adc7f2ca #N/A Indent Fish alias with two spaces (default) 2015-11-25 02:34:33 -02:00
Pablo Santiago Blum de Aguiar
fc05364233 #398 & #408: Support non-ascii IO in Python 2 2015-11-25 02:34:19 -02:00
Pablo Santiago Blum de Aguiar
ad3db4ac67 #N/A Fix F812 list comprehension redefines cmd 2015-11-25 02:34:15 -02:00
Pablo Santiago Blum de Aguiar
4a7b335d7c #N/A Add ability to get Fish Shell history 2015-11-25 02:34:02 -02:00
Pablo Santiago Blum de Aguiar
465f6191b0 #N/A Cleanup and adjust syntax 2015-11-25 01:58:07 -02:00
Vladimir Iakovlev
b2836319ad Update README.md 2015-11-19 11:22:56 +08:00
Vladimir Iakovlev
b3e9b36bd1 Merge pull request #409 from nvbn/394-history-limit
#394 history limit
2015-11-19 11:17:21 +08:00
lovedboy
ae2949cfa2 python2.7 unicode error 2015-11-19 09:40:44 +08:00
nvbn
1bb04b41eb #398: Add PYTHONIOENCODING=utf-8 to shell aliases 2015-11-18 18:37:11 +08:00
Vladimir Iakovlev
acd0b3e024 Merge pull request #406 from mcarton/py2→3
Fix cache problem when going from Python 2 to 3
2015-11-18 18:32:24 +08:00
mcarton
7c5676491a Fix some more warnings from flake8 2015-11-15 18:08:59 +01:00
mcarton
8feb722ed0 Fix some pep8 warnings 2015-11-15 18:02:37 +01:00
mcarton
c3ea2fd0c7 Fix cache problem when going from Python 2 to 3 2015-11-15 16:55:07 +01:00
nvbn
b55464b2ea #403 Add sudo rule's pattern for dscl 2015-11-13 15:37:13 +08:00
nvbn
8ddb61ae89 #N/A Add python-gdbm to install script 2015-11-12 18:43:15 +08:00
Vladimir Iakovlev
fe91008a9c Merge pull request #400 from alessio/fix-memoize
Fix misinterpretation of the disabled flag
2015-11-06 02:19:07 +08:00
Alessio Treglia
7f777213c5 Fix misinterpretation of the disabled flag
The old implementation was misinterpretating the disabled flag and
effectively applying memoization even when explicitly disabled.
The 'or' operator is a short-circuit one; namely, it evaluates the
second argument if and only if the first is False. Therefore the
following conditions caused unexpected side effects:

- memoize.disabled = True, key not yet memoized

  Having disabled the memoize function wrapper, the client expects
  that no memoization happens. Instead the execution enters the
  if clause and store the value into the 'memo' dictionary

- memoize.disabled = True, key memoized

  Having disabled the memoize function wrapper, the client expects
  that no memoization happens and the function will be evaluated
  anyway, whether or not its return value had already been stored in
  the 'memo' dictionary by a previous call. On the contrary, the last
  statement of wrapper() access the value stored by the last function
  execution.

This commit attempts to improve the function readability too.
2015-11-04 22:44:50 +00:00
nvbn
89f868c115 Bump to 3.2 2015-11-03 17:38:07 +08:00
nvbn
81f6a25abc #398: Fix UnicodeDecodeError in logs 2015-11-01 14:42:48 +08:00
nvbn
cc9af78787 Merge branch 'master' of github.com:nvbn/thefuck 2015-11-01 13:17:15 +08:00
nvbn
1fc3f1b5bf #398: Fix UnicodeDecodeError in logs 2015-11-01 13:16:58 +08:00
Vladimir Iakovlev
45574d06c9 Merge pull request #397 from janek-warchol/use-force-with-lease
Use --force-with-lease instead of --force for git push
2015-10-31 02:47:51 +08:00
Jan Warchoł
dc23d67a42 Use --force-with-lease instead of --force for git push
--force flag can be very dangerous, because it unconditionally
overwrites remote branch - if someone pushed new commits to the remote
repo after you last fetched/pulled, and you do push --force, you will
overwrite his commits without even knowing that you did that.  Using
--force-with-lease is much safer because it only overwrites remote
branch when it points to the same commit that you think it points to.

Read more:
https://developer.atlassian.com/blog/2015/04/force-with-lease/
2015-10-30 16:17:56 +01:00
nvbn
2fea0d4c60 #394: Force history_limit to be int 2015-10-30 16:23:19 +08:00
nvbn
8c8abca8d5 #394: readlines isn't lazy 2015-10-29 22:51:30 +08:00
nvbn
bd6ee68c03 #394: Try simpler solution to limit lines count 2015-10-29 20:17:17 +08:00
nvbn
16533e85a7 Merge branch 'debug' of git://github.com/lovedboy/thefuck into lovedboy-debug 2015-10-29 20:00:04 +08:00
lovedboy
b3a19fe439 history limit from settings 2015-10-29 10:14:34 +08:00
nvbn
959b96cf6e #392: Show only debug message if script isn't splitable 2015-10-29 01:03:27 +08:00
nvbn
f20311fa89 #392: Little refactoring 2015-10-29 00:13:59 +08:00
nvbn
a4c391096a Merge branch 'fix-split' of https://github.com/mcarton/thefuck into mcarton-fix-split 2015-10-29 00:04:29 +08:00
mcarton
e71a3e0cdb Replace (almost) all instance of script.split 2015-10-28 16:43:24 +01:00
mcarton
2d995d464f Fix the cpp11 rule 2015-10-28 15:27:10 +01:00
mcarton
280751b36e Fix the unzip rules and filenames with spaces 2015-10-28 15:13:33 +01:00
mcarton
0a6a3db65d Fix the untar rules and filenames with spaces 2015-10-28 15:12:59 +01:00
mcarton
ecfc180280 Add shells.quote 2015-10-28 14:16:01 +01:00
mcarton
dae58211ba Parse command line with shlex
I put that in shells so that weird shells might try to parse it
differently.
2015-10-28 14:01:14 +01:00
Vladimir Iakovlev
5e9b2c56da Merge pull request #391 from mcarton/tox-3.5
#374 Test python 3.5 with tox
2015-10-28 20:52:45 +08:00
mcarton
192ab0bfb0 Test python 3.5 with tox 2015-10-28 13:32:37 +01:00
lovedboy
372e983459 add THEFUCK_HISTORY_LIMIT, my machine is so slow 2015-10-22 19:25:00 +08:00
nvbn
346cb99217 #385 Little refactoring 2015-10-21 18:13:22 +08:00
nvbn
bbfedb861f Merge branch 'xdg' of https://github.com/mcarton/thefuck into mcarton-xdg 2015-10-21 18:03:39 +08:00
nvbn
f5b0e96747 #382 Prevent partial execution of install.sh 2015-10-21 18:00:08 +08:00
Vladimir Iakovlev
12a33f56bc Merge pull request #389 from scorphus/fix-touch
Fix `rules.touch` tests
2015-10-21 17:50:09 +08:00
Pablo Santiago Blum de Aguiar
590fdba2aa Fix rules.touch tests
Move them to `rules` sub-directory and import `shells` instead of `and_`
which in turn triggers the `generic_shell` fixture fixing the tests on
Fish Shell.
2015-10-18 19:49:46 -02:00
Vladimir Iakovlev
f374142bf8 Merge pull request #384 from scorphus/fish-func
Improve the Fish Shell function making it faster
2015-10-19 01:50:53 +08:00
Vladimir Iakovlev
540ff7e16d Merge pull request #387 from scorphus/git-two-dashes
Add `git_two_dashes` rule
2015-10-19 01:50:04 +08:00
Vladimir Iakovlev
806dad18bf Merge pull request #386 from mcarton/CONTRIBUTING
Add a CONTRIBUTING file
2015-10-19 01:49:02 +08:00
Vladimir Iakovlev
8b416f269f Merge pull request #388 from scorphus/fix-brew-tests
Fix rules.brew_install tests on Mac
2015-10-19 01:48:53 +08:00
Pablo Santiago Blum de Aguiar
5e44fb22be Fix rules.brew_install tests on Mac 2015-10-17 18:46:07 -03:00
Pablo Santiago Blum de Aguiar
5389d0c106 Add git_two_dashes rule 2015-10-17 18:40:53 -03:00
mcarton
c970f190d2 Add a CONTRIBUTING file 2015-10-17 15:45:13 +02:00
mcarton
8f25c95f06 Use XDG_CACHE_HOME for cache 2015-10-16 17:33:52 +02:00
mcarton
4a48108c69 Follow the XDG Base Directory Specification 2015-10-16 16:52:03 +02:00
Pablo Santiago Blum de Aguiar
f5e8fe954e Improve the Fish Shell function making it faster
It works now with no temp file involved, which makes it a lot faster.
Also, `history --merge`, although only supported on Fish Shell 2.2+,
merges the corrected entry back into history. Neat!

Ref #89
2015-10-16 00:42:34 -03:00
nvbn
3da26192cb Bump to 3.1 2015-10-08 10:30:38 +08:00
Vladimir Iakovlev
11c133523a Merge pull request #375 from jab/patch-1
rm -f $eval_script
2015-10-03 10:24:39 +08:00
Vladimir Iakovlev
4b3e6a1448 Merge pull request #374 from mcarton/python3.5
Test on python 3.5
2015-10-03 10:23:41 +08:00
jab
09d9f63c98 use /bin/rm rather than rm -f 2015-10-02 10:12:50 -04:00
jab
e8883429c6 rm -f $eval_script
Without this change, users who have "rm" aliased to "rm -i"
have to confirm removal of the file after running fuck. This
change allows such users to run fuck without having to do
the superfluous rm confirmation.
2015-10-02 10:09:19 -04:00
nvbn
c1b67f2514 Show python version in --version 2015-09-28 16:47:54 +08:00
mcarton
3d6e7b17db Test on python 3.5 2015-09-15 02:17:56 +02:00
Vladimir Iakovlev
75ef866214 Merge pull request #373 from grammaright/master
Add j, k key for arrow action at read_actions
2015-09-13 12:38:55 +03:00
grammaright
5021d16cea Add j, k key for arrow action at read_actions 2015-09-13 01:27:21 +09:00
Vladimir Iakovlev
af259846b4 Merge pull request #370 from nvbn/369-git-fix-stash-fails
#369 Fix `git_fix_stash` fails when script is just `git`
2015-09-10 15:11:34 +03:00
nvbn
213791d3c2 #369 Fix git_fix_stash fails when script is just git 2015-09-10 14:28:22 +03:00
nvbn
71dc2666cc Bump to 3.0 2015-09-09 10:59:07 +03:00
Vladimir Iakovlev
3e66a294c4 Merge pull request #367 from nvbn/355-touch-rule
#355 Add `touch` rule
2015-09-09 10:57:55 +03:00
nvbn
3e8db28a73 #355 Add touch rule 2015-09-09 10:53:56 +03:00
Vladimir Iakovlev
6e886c6b4f Merge pull request #366 from nvbn/unned-abstractions
Improve code structure
2015-09-08 17:53:37 +03:00
nvbn
3fc2efee0f #366 Don't make bash history checks in travis-ci, it works incorrectly 2015-09-08 17:48:33 +03:00
nvbn
cb14aded6b #366 Remove sleep before checking history 2015-09-08 17:47:04 +03:00
nvbn
08af616e3d #366 Add sleep before checking history 2015-09-08 17:39:52 +03:00
nvbn
dfa22bc92b #366 Add type annotations in core components 2015-09-08 15:54:07 +03:00
nvbn
eb17e696c3 #366 Fix python 2 support 2015-09-08 15:32:19 +03:00
nvbn
b8ce95ad68 Minor refactoring 2015-09-08 15:24:49 +03:00
nvbn
1173f9f59c Organize settings initialization logic in Settings 2015-09-08 15:15:53 +03:00
nvbn
a8dbc48fd4 Move commands-related logic to Command and CorrectedCommand 2015-09-08 15:00:57 +03:00
nvbn
4a27595e97 Move rule-related code to Rule 2015-09-08 14:18:11 +03:00
nvbn
bf80d97062 Remove obscure SortedCorrectedCommandsSequence 2015-09-08 12:52:10 +03:00
nvbn
1fb6dd925b Remove on_change from CommandSelector 2015-09-08 12:27:17 +03:00
nvbn
b2be0b3cad Remove obscure RulesNamesList and DefaultRulesNames 2015-09-08 12:14:39 +03:00
Vladimir Iakovlev
122541b7d8 Merge pull request #365 from mcarton/fix-unzip
Fix #363
2015-09-07 23:36:13 +03:00
mcarton
488c1dad79 Merge branch 'master' of github.com:nvbn/thefuck into fix-unzip 2015-09-07 21:12:14 +02:00
mcarton
c3fe7e5e68 Fix #363 2015-09-07 20:48:10 +02:00
nvbn
3d56204f92 Update readme 2015-09-07 19:13:17 +03:00
Vladimir Iakovlev
293f16c3c8 Merge pull request #364 from nvbn/global-settings
Don't pass `settings` explicitly
2015-09-07 19:09:31 +03:00
nvbn
7339a97b90 #364 Make aliases cache persistent 2015-09-07 19:05:38 +03:00
nvbn
f3525e9fe0 #364 Attach user_dir to settings 2015-09-07 18:59:10 +03:00
nvbn
df4d2cc88d ⚠️ Remove settings param from rules match, get_new_command and side_effect 2015-09-07 13:00:29 +03:00
nvbn
382eb8b86c Fix tests 2015-09-07 12:12:16 +03:00
nvbn
105d3d8137 Make settings a global singleton 2015-09-06 21:47:12 +03:00
Vladimir Iakovlev
191a2e588d Merge pull request #362 from nvbn/356-fuck-endpoint
#356 fuck endpoint
2015-09-06 13:43:24 +03:00
nvbn
f964c65f16 #362 Fix tests for python 2 2015-09-06 13:40:29 +03:00
nvbn
dd0667ea8f #356 Ignore thefuck entry points 2015-09-06 13:37:48 +03:00
nvbn
4392872568 #356 Print useful information when fuck called and alias isn't configured 2015-09-06 13:29:42 +03:00
Vladimir Iakovlev
f7ce0fda25 Merge pull request #361 from nvbn/357-exclude-rules
#357 Add `exclude_rules` settings option
2015-09-06 12:59:34 +03:00
nvbn
2f9db24ed1 #357 Add exclude_rules settings option 2015-09-06 12:55:59 +03:00
Vladimir Iakovlev
4ae2e9bbc4 Merge pull request #359 from nvbn/use-pytest-docker-pexpect
Use pytest-docker-pexpect
2015-09-06 01:28:37 +03:00
nvbn
5cfd493d05 Make "arrows" tests less dependent on environment 2015-09-06 01:24:29 +03:00
nvbn
22eac045c8 Use @pytest.mark.once_without_docker 2015-09-06 01:14:49 +03:00
nvbn
cdd5f21e88 Add functional marker 2015-09-06 01:13:44 +03:00
nvbn
8cc19daaaa Use pytest-docker-pexpect for func tests 2015-09-06 00:56:18 +03:00
nvbn
8bf4182f86 Fix install script on non-ubuntu 2015-09-05 11:54:59 +03:00
nvbn
6df772ba05 Bump to 2.9.1 2015-09-05 11:46:34 +03:00
nvbn
e2e8b6fc86 Fix without result 2015-09-05 11:45:39 +03:00
226 changed files with 3849 additions and 2380 deletions

View File

@@ -1,5 +1,7 @@
language: python language: python
sudo: false
python: python:
- "3.5"
- "3.4" - "3.4"
- "3.3" - "3.3"
- "2.7" - "2.7"
@@ -14,14 +16,13 @@ addons:
- tcsh - tcsh
- pandoc - pandoc
- git - git
env:
- FUNCTIONAL=true BARE=true
install: install:
- pip install coveralls - pip install -U pip
- pip install -r requirements.txt - pip install -U coveralls
- pip install -Ur requirements.txt
- python setup.py develop - python setup.py develop
- rm -rf build - rm -rf build
script: script:
- export COVERAGE_PYTHON_VERSION=python-${TRAVIS_PYTHON_VERSION:0:1} - export COVERAGE_PYTHON_VERSION=python-${TRAVIS_PYTHON_VERSION:0:1}
- coverage run --source=thefuck,tests -m py.test -v --capture=sys - coverage run --source=thefuck,tests -m py.test -v --capture=sys --run-without-docker --enable-functional
after_success: coveralls after_success: coveralls

25
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,25 @@
# Report issues
If you have any issue with The Fuck, sorry about that, but we will do what we
can to fix that. Actually, maybe we already have, so first thing to do is to
update The Fuck and see if the bug is still there.
If it is (sorry again), check if the problem has not already been reported and
if not, just open an issue on [GitHub](https://github.com/nvbn/thefuck) with
the following basic information:
- the output of `thefuck --version` (something like `The Fuck 3.1 using
Python 3.5.0`);
- your shell and its version (`bash`, `zsh`, *Windows PowerShell*, etc.);
- your system (Debian 7, ArchLinux, Windows, etc.);
- how to reproduce the bug;
- the output of The Fuck with `THEFUCK_DEBUG=true` exported (typically execute
`export THEFUCK_DEBUG=true` in your shell before The Fuck);
- if the bug only appears with a specific application, the output of that
application and its version;
- anything else you think is relevant.
It's only with enough information that we can do something to fix the problem.
# Make a pull request
We gladly accept pull request on the [official
repository](https://github.com/nvbn/thefuck) for new rules, new features, bug
fixes, etc.

View File

@@ -1,10 +1,10 @@
# The Fuck [![Build Status](https://travis-ci.org/nvbn/thefuck.svg?branch=master)](https://travis-ci.org/nvbn/thefuck) # The Fuck [![Version][version-badge]][version-link] [![Build Status][travis-badge]][travis-link] [![Windows Build Status][appveyor-badge]][appveyor-link] [![Coverage][coverage-badge]][coverage-link] [![MIT License][license-badge]](LICENSE.md)
Magnificent app which corrects your previous console command, Magnificent app which corrects your previous console command,
inspired by a [@liamosaur](https://twitter.com/liamosaur/) inspired by a [@liamosaur](https://twitter.com/liamosaur/)
[tweet](https://twitter.com/liamosaur/status/506975850596536320). [tweet](https://twitter.com/liamosaur/status/506975850596536320).
[![gif with examples](https://raw.githubusercontent.com/nvbn/thefuck/master/example.gif)](https://raw.githubusercontent.com/nvbn/thefuck/master/example.gif) [![gif with examples][examples-link]][examples-link]
Few more examples: Few more examples:
@@ -52,7 +52,7 @@ Python 3.4.2 (default, Oct 8 2014, 13:08:17)
git: 'brnch' is not a git command. See 'git --help'. git: 'brnch' is not a git command. See 'git --help'.
Did you mean this? Did you mean this?
branch branch
➜ fuck ➜ fuck
git branch [enter/↑/↓/ctrl+c] git branch [enter/↑/↓/ctrl+c]
@@ -97,7 +97,7 @@ Reading package lists... Done
## Installation [*experimental*] ## Installation [*experimental*]
On Ubuntu and OS X you can install `The Fuck` with installation script: On Ubuntu and OS X you can install `The Fuck` with installation script:
```bash ```bash
wget -O - https://raw.githubusercontent.com/nvbn/thefuck/master/install.sh | sh - && $0 wget -O - https://raw.githubusercontent.com/nvbn/thefuck/master/install.sh | sh - && $0
``` ```
@@ -107,7 +107,7 @@ wget -O - https://raw.githubusercontent.com/nvbn/thefuck/master/install.sh | sh
Install `The Fuck` with `pip`: Install `The Fuck` with `pip`:
```bash ```bash
sudo pip install thefuck sudo -H pip install thefuck
``` ```
[Or using an OS package manager (OS X, Ubuntu, Arch).](https://github.com/nvbn/thefuck/wiki/Installation) [Or using an OS package manager (OS X, Ubuntu, Arch).](https://github.com/nvbn/thefuck/wiki/Installation)
@@ -155,19 +155,25 @@ using the matched rule and runs it. Rules enabled by default are as follows:
* `dry` – fixes repetitions like `git git push`; * `dry` – fixes repetitions like `git git push`;
* `fix_alt_space` – replaces Alt+Space with Space character; * `fix_alt_space` – replaces Alt+Space with Space character;
* `fix_file` – opens a file with an error in your `$EDITOR`; * `fix_file` – opens a file with an error in your `$EDITOR`;
* `git_add` – fixes *"Did you forget to 'git add'?"*; * `git_add` – fixes *"pathspec 'foo' did not match any file(s) known to git."*;
* `git_branch_delete` – changes `git branch -d` to `git branch -D`; * `git_branch_delete` – changes `git branch -d` to `git branch -D`;
* `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_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_checkout` – fixes branch name or creates new branch;
* `git_diff_staged` – adds `--staged` to previous `git diff` with unexpected output; * `git_diff_staged` – adds `--staged` to previous `git diff` with unexpected output;
* `git_fix_stash` – fixes `git stash` commands (misspelled subcommand and missing `save`); * `git_fix_stash` – fixes `git stash` commands (misspelled subcommand and missing `save`);
* `git_help_aliased` &ndash; fixes `git help <alias>` commands replacing <alias> with the aliased command;
* `git_not_command` &ndash; fixes wrong git commands like `git brnch`; * `git_not_command` &ndash; fixes wrong git commands like `git brnch`;
* `git_pull` &ndash; sets upstream before executing previous `git pull`; * `git_pull` &ndash; sets upstream before executing previous `git pull`;
* `git_pull_clone` &ndash; clones instead of pulling when the repo does not exist; * `git_pull_clone` &ndash; clones instead of pulling when the repo does not exist;
* `git_push` &ndash; adds `--set-upstream origin $branch` to previous failed `git push`; * `git_push` &ndash; adds `--set-upstream origin $branch` to previous failed `git push`;
* `git_push_pull` &ndash; runs `git pull` when `push` was rejected; * `git_push_pull` &ndash; runs `git pull` when `push` was rejected;
* `git_rm_recursive` &ndash; adds `-r` when you try to `rm` a directory;
* `git_remote_seturl_add` &ndash; runs `git remote add` when `git remote set_url` on nonexistant remote;
* `git_stash` &ndash; stashes you local modifications before rebasing or switching branch; * `git_stash` &ndash; stashes you local modifications before rebasing or switching branch;
* `go_run` &ndash; appends `.go` extension when compiling/running Go programs * `git_two_dashes` &ndash; adds a missing dash to commands like `git commit -amend` or `git rebase -continue`;
* `go_run` &ndash; appends `.go` extension when compiling/running Go programs;
* `grep_arguments_order` &ndash; fixes grep arguments order for situations like `grep -lir . test`;
* `grep_recursive` &ndash; adds `-r` when you trying to `grep` directory; * `grep_recursive` &ndash; adds `-r` when you trying to `grep` directory;
* `gulp_not_task` &ndash; fixes misspelled `gulp` tasks; * `gulp_not_task` &ndash; fixes misspelled `gulp` tasks;
* `has_exists_script` &ndash; prepends `./` when script/binary exists; * `has_exists_script` &ndash; prepends `./` when script/binary exists;
@@ -176,6 +182,7 @@ using the matched rule and runs it. Rules enabled by default are as follows:
* `java` &ndash; removes `.java` extension when running Java programs; * `java` &ndash; removes `.java` extension when running Java programs;
* `javac` &ndash; appends missing `.java` when compiling Java files; * `javac` &ndash; appends missing `.java` when compiling Java files;
* `lein_not_task` &ndash; fixes wrong `lein` tasks like `lein rpl`; * `lein_not_task` &ndash; fixes wrong `lein` tasks like `lein rpl`;
* `ln_no_hard_link` &ndash; catches hard link creation on directories, suggest symbolic link;
* `ls_lah` &ndash; adds `-lah` to `ls`; * `ls_lah` &ndash; adds `-lah` to `ls`;
* `man` &ndash; changes manual section; * `man` &ndash; changes manual section;
* `man_no_space` &ndash; fixes man commands without spaces, for example `mandiff`; * `man_no_space` &ndash; fixes man commands without spaces, for example `mandiff`;
@@ -183,6 +190,7 @@ using the matched rule and runs it. Rules enabled by default are as follows:
* `mkdir_p` &ndash; adds `-p` when you trying to create directory without parent; * `mkdir_p` &ndash; adds `-p` when you trying to create directory without parent;
* `mvn_no_command` &ndash; adds `clean package` to `mvn`; * `mvn_no_command` &ndash; adds `clean package` to `mvn`;
* `mvn_unknown_lifecycle_phase` &ndash; fixes misspelled lifecycle phases with `mvn`; * `mvn_unknown_lifecycle_phase` &ndash; fixes misspelled lifecycle phases with `mvn`;
* `npm_wrong_command` &ndash; fixes wrong npm commands like `npm urgrade`;
* `no_command` &ndash; fixes wrong console commands, for example `vom/vim`; * `no_command` &ndash; fixes wrong console commands, for example `vom/vim`;
* `no_such_file` &ndash; creates missing directories with `mv` and `cp` commands; * `no_such_file` &ndash; creates missing directories with `mv` and `cp` commands;
* `open` &ndash; prepends `http` to address passed to `open`; * `open` &ndash; prepends `http` to address passed to `open`;
@@ -198,6 +206,7 @@ using the matched rule and runs it. Rules enabled by default are as follows:
* `switch_lang` &ndash; switches command from your local layout to en; * `switch_lang` &ndash; switches command from your local layout to en;
* `systemctl` &ndash; correctly orders parameters of confusing `systemctl`; * `systemctl` &ndash; correctly orders parameters of confusing `systemctl`;
* `test.py` &ndash; runs `py.test` instead of `test.py`; * `test.py` &ndash; runs `py.test` instead of `test.py`;
* `touch` &ndash; creates missing directories before "touching";
* `tsuru_login` &ndash; runs `tsuru login` if not authenticated or session expired; * `tsuru_login` &ndash; runs `tsuru login` if not authenticated or session expired;
* `tsuru_not_command` &ndash; fixes wrong `tsuru` commands like `tsuru shell`; * `tsuru_not_command` &ndash; fixes wrong `tsuru` commands like `tsuru shell`;
* `tmux` &ndash; fixes `tmux` commands; * `tmux` &ndash; fixes `tmux` commands;
@@ -209,6 +218,7 @@ Enabled by default only on specific platforms:
* `apt_get` &ndash; installs app from apt if it not installed (requires `python-commandnotfound` / `python3-commandnotfound`); * `apt_get` &ndash; installs app from apt if it not installed (requires `python-commandnotfound` / `python3-commandnotfound`);
* `apt_get_search` &ndash; changes trying to search using `apt-get` with searching using `apt-cache`; * `apt_get_search` &ndash; changes trying to search using `apt-get` with searching using `apt-cache`;
* `apt_invalid_operation` &ndash; fixes invalid `apt` and `apt-get` calls, like `apt-get isntall vim`;
* `brew_install` &ndash; fixes formula name for `brew install`; * `brew_install` &ndash; fixes formula name for `brew install`;
* `brew_unknown_command` &ndash; fixes wrong brew commands, for example `brew docto/brew doctor`; * `brew_unknown_command` &ndash; fixes wrong brew commands, for example `brew docto/brew doctor`;
* `brew_upgrade` &ndash; appends `--all` to `brew upgrade` as per Homebrew's new behaviour; * `brew_upgrade` &ndash; appends `--all` to `brew upgrade` as per Homebrew's new behaviour;
@@ -217,45 +227,46 @@ Enabled by default only on specific platforms:
Bundled, but not enabled by default: Bundled, but not enabled by default:
* `git_push_force` &ndash; adds `--force` to a `git push` (may conflict with `git_push_pull`); * `git_push_force` &ndash; adds `--force-with-lease` to a `git push` (may conflict with `git_push_pull`);
* `rm_root` &ndash; adds `--no-preserve-root` to `rm -rf /` command. * `rm_root` &ndash; adds `--no-preserve-root` to `rm -rf /` command.
## Creating your own rules ## Creating your own rules
For adding your own rule you should create `your-rule-name.py` For adding your own rule you should create `your-rule-name.py`
in `~/.thefuck/rules`. The rule should contain two functions: in `~/.config/thefuck/rules`. The rule should contain two functions:
```python ```python
match(command: Command, settings: Settings) -> bool match(command: Command) -> bool
get_new_command(command: Command, settings: Settings) -> str | list[str] get_new_command(command: Command) -> str | list[str]
``` ```
Also the rule can contain an optional function Also the rule can contain an optional function
```python ```python
side_effect(old_command: Command, fixed_command: str, settings: Settings) -> None side_effect(old_command: Command, fixed_command: str) -> None
``` ```
and optional `enabled_by_default`, `requires_output` and `priority` variables. and optional `enabled_by_default`, `requires_output` and `priority` variables.
`Command` has three attributes: `script`, `stdout` and `stderr`. `Command` has three attributes: `script`, `stdout` and `stderr`.
`Settings` is a special object filled with `~/.thefuck/settings.py` and values from env ([see more below](#settings)). *Rules api changed in 3.0:* For accessing settings in rule you need to import it with `from thefuck.conf import settings`.
`settings` is a special object filled with `~/.config/thefuck/settings.py` and values from env ([see more below](#settings)).
Simple example of the rule for running script with `sudo`: Simple example of the rule for running script with `sudo`:
```python ```python
def match(command, settings): def match(command):
return ('permission denied' in command.stderr.lower() return ('permission denied' in command.stderr.lower()
or 'EACCES' in command.stderr) or 'EACCES' in command.stderr)
def get_new_command(command, settings): def get_new_command(command):
return 'sudo {}'.format(command.script) return 'sudo {}'.format(command.script)
# Optional: # Optional:
enabled_by_default = True enabled_by_default = True
def side_effect(command, settings): def side_effect(command, fixed_command):
subprocess.call('chmod 777 .', shell=True) subprocess.call('chmod 777 .', shell=True)
priority = 1000 # Lower first, default is 1000 priority = 1000 # Lower first, default is 1000
@@ -264,23 +275,28 @@ requires_output = True
``` ```
[More examples of rules](https://github.com/nvbn/thefuck/tree/master/thefuck/rules), [More examples of rules](https://github.com/nvbn/thefuck/tree/master/thefuck/rules),
[utility functions for rules](https://github.com/nvbn/thefuck/tree/master/thefuck/utils.py). [utility functions for rules](https://github.com/nvbn/thefuck/tree/master/thefuck/utils.py),
[app/os-specific helpers](https://github.com/nvbn/thefuck/tree/master/thefuck/specific/).
## Settings ## Settings
The Fuck has a few settings parameters which can be changed in `~/.thefuck/settings.py`: The Fuck has a few settings parameters which can be changed in `$XDG_CONFIG_HOME/thefuck/settings.py` (`$XDG_CONFIG_HOME` defaults to `~/.config`):
* `rules` &ndash; list of enabled rules, by default `thefuck.conf.DEFAULT_RULES`; * `rules` &ndash; list of enabled rules, by default `thefuck.conf.DEFAULT_RULES`;
* `exclude_rules` &ndash; list of disabled rules, by default `[]`;
* `require_confirmation` &ndash; requires confirmation before running new command, by default `True`; * `require_confirmation` &ndash; requires confirmation before running new command, by default `True`;
* `wait_command` &ndash; max amount of time in seconds for getting previous command output; * `wait_command` &ndash; max amount of time in seconds for getting previous command output;
* `no_colors` &ndash; disable colored output; * `no_colors` &ndash; disable colored output;
* `priority` &ndash; dict with rules priorities, rule with lower `priority` will be matched first; * `priority` &ndash; dict with rules priorities, rule with lower `priority` will be matched first;
* `debug` &ndash; enables debug output, by default `False`. * `debug` &ndash; enables debug output, by default `False`;
* `history_limit` &ndash; numeric value of how many history commands will be scanned, like `2000`;
* `alter_history` &ndash; push fixed command to history, by default `True`.
Example of `settings.py`: Example of `settings.py`:
```python ```python
rules = ['sudo', 'no_command'] rules = ['sudo', 'no_command']
exclude_rules = ['git_push']
require_confirmation = True require_confirmation = True
wait_command = 10 wait_command = 10
no_colors = False no_colors = False
@@ -291,21 +307,26 @@ debug = False
Or via environment variables: Or via environment variables:
* `THEFUCK_RULES` &ndash; list of enabled rules, like `DEFAULT_RULES:rm_root` or `sudo:no_command`; * `THEFUCK_RULES` &ndash; list of enabled rules, like `DEFAULT_RULES:rm_root` or `sudo:no_command`;
* `THEFUCK_EXCLUDE_RULES` &ndash; list of disabled rules, like `git_pull:git_push`;
* `THEFUCK_REQUIRE_CONFIRMATION` &ndash; require confirmation before running new command, `true/false`; * `THEFUCK_REQUIRE_CONFIRMATION` &ndash; require confirmation before running new command, `true/false`;
* `THEFUCK_WAIT_COMMAND` &ndash; max amount of time in seconds for getting previous command output; * `THEFUCK_WAIT_COMMAND` &ndash; max amount of time in seconds for getting previous command output;
* `THEFUCK_NO_COLORS` &ndash; disable colored output, `true/false`; * `THEFUCK_NO_COLORS` &ndash; disable colored output, `true/false`;
* `THEFUCK_PRIORITY` &ndash; priority of the rules, like `no_command=9999:apt_get=100`, * `THEFUCK_PRIORITY` &ndash; priority of the rules, like `no_command=9999:apt_get=100`,
rule with lower `priority` will be matched first; rule with lower `priority` will be matched first;
* `THEFUCK_DEBUG` &ndash; enables debug output, `true/false`. * `THEFUCK_DEBUG` &ndash; enables debug output, `true/false`;
* `THEFUCK_HISTORY_LIMIT` &ndash; how many history commands will be scanned, like `2000`;
* `THEFUCK_ALTER_HISTORY` &ndash; push fixed command to history `true/false`.
For example: For example:
```bash ```bash
export THEFUCK_RULES='sudo:no_command' export THEFUCK_RULES='sudo:no_command'
export THEFUCK_EXCLUDE_RULES='git_pull:git_push'
export THEFUCK_REQUIRE_CONFIRMATION='true' export THEFUCK_REQUIRE_CONFIRMATION='true'
export THEFUCK_WAIT_COMMAND=10 export THEFUCK_WAIT_COMMAND=10
export THEFUCK_NO_COLORS='false' export THEFUCK_NO_COLORS='false'
export THEFUCK_PRIORITY='no_command=9999:apt_get=100' export THEFUCK_PRIORITY='no_command=9999:apt_get=100'
export THEFUCK_HISTORY_LIMIT='2000'
``` ```
## Developing ## Developing
@@ -326,7 +347,7 @@ py.test
Run unit and functional tests (requires docker): Run unit and functional tests (requires docker):
```bash ```bash
FUNCTIONAL=true py.test py.test --enable-functional
``` ```
For sending package to pypi: For sending package to pypi:
@@ -338,3 +359,15 @@ sudo apt-get install pandoc
## License MIT ## License MIT
Project License can be found [here](LICENSE.md). Project License can be found [here](LICENSE.md).
[version-badge]: https://img.shields.io/pypi/v/thefuck.svg?label=version
[version-link]: https://pypi.python.org/pypi/thefuck/
[travis-badge]: https://img.shields.io/travis/nvbn/thefuck.svg
[travis-link]: https://travis-ci.org/nvbn/thefuck
[appveyor-badge]: https://img.shields.io/appveyor/ci/nvbn/thefuck.svg?label=windows%20build
[appveyor-link]: https://ci.appveyor.com/project/nvbn/thefuck
[coverage-badge]: https://img.shields.io/coveralls/nvbn/thefuck.svg
[coverage-link]: https://coveralls.io/github/nvbn/thefuck
[license-badge]: https://img.shields.io/badge/license-MIT-007EC7.svg
[examples-link]: https://raw.githubusercontent.com/nvbn/thefuck/master/example.gif

22
appveyor.yml Normal file
View File

@@ -0,0 +1,22 @@
build: false
environment:
matrix:
- PYTHON: "C:/Python27"
- PYTHON: "C:/Python33"
- PYTHON: "C:/Python34"
- PYTHON: "C:/Python35"
init:
- "ECHO %PYTHON%"
- ps: "ls C:/Python*"
install:
- ps: (new-object net.webclient).DownloadFile('https://bootstrap.pypa.io/get-pip.py', 'C:/get-pip.py')
- "%PYTHON%/python.exe C:/get-pip.py"
- "%PYTHON%/Scripts/pip.exe install -U setuptools"
- "%PYTHON%/python.exe setup.py develop"
- "%PYTHON%/Scripts/pip.exe install -U -r requirements.txt"
test_script:
- "%PYTHON%/Scripts/py.test.exe -sv"

View File

@@ -4,50 +4,58 @@ should_add_alias () {
[ -f $1 ] && ! grep -q thefuck $1 [ -f $1 ] && ! grep -q thefuck $1
} }
# Install os dependencies: installed () {
if [ -f $(which apt-get) ]; then hash $1 2>/dev/null
# Debian/ubuntu: }
sudo apt-get update -yy
sudo apt-get install -yy python-pip python-dev command-not-found
if [[ -n $(apt-cache search python-commandnotfound) ]]; then install_thefuck () {
# In case of different python versions: # Install OS dependencies:
sudo apt-get install -yy python-commandnotfound if installed apt-get; then
fi # Debian/Ubuntu:
else sudo apt-get update -yy
if [ -f $(which brew) ]; then sudo apt-get install -yy python-pip python-dev command-not-found python-gdbm
# OS X:
brew update if [ -n "$(apt-cache search python-commandnotfound)" ]; then
brew install python # In case of different python versions:
sudo apt-get install -yy python-commandnotfound
fi
else else
# Genreic way: if installed brew; then
wget https://bootstrap.pypa.io/get-pip.py # OS X:
sudo python get-pip.py brew update
rm get-pip.py brew install python
else
# Generic way:
wget https://bootstrap.pypa.io/get-pip.py
sudo python get-pip.py
rm get-pip.py
fi
fi fi
fi
# thefuck requires fresh versions of setuptools and pip: # thefuck requires fresh versions of setuptools and pip:
sudo pip install -U pip setuptools sudo pip install -U pip setuptools
sudo pip install -U thefuck sudo pip install -U thefuck
# Setup aliases: # Setup aliases:
if should_add_alias ~/.bashrc; then if should_add_alias ~/.bashrc; then
echo 'eval $(thefuck --alias)' >> ~/.bashrc echo 'eval $(thefuck --alias)' >> ~/.bashrc
fi fi
if should_add_alias ~/.bash_profile; then if should_add_alias ~/.bash_profile; then
echo 'eval $(thefuck --alias)' >> ~/.bash_profile echo 'eval $(thefuck --alias)' >> ~/.bash_profile
fi fi
if should_add_alias ~/.zshrc; then if should_add_alias ~/.zshrc; then
echo 'eval $(thefuck --alias)' >> ~/.zshrc echo 'eval $(thefuck --alias)' >> ~/.zshrc
fi fi
if should_add_alias ~/.config/fish/config.fish; then if should_add_alias ~/.config/fish/config.fish; then
thefuck --alias >> ~/.config/fish/config.fish thefuck --alias >> ~/.config/fish/config.fish
fi fi
if should_add_alias ~/.tcshrc; then if should_add_alias ~/.tcshrc; then
echo 'eval `thefuck --alias`' >> ~/.tcshrc echo 'eval `thefuck --alias`' >> ~/.tcshrc
fi fi
}
install_thefuck

View File

@@ -1,3 +1,4 @@
pip
pytest pytest
mock mock
pytest-mock pytest-mock
@@ -6,3 +7,4 @@ setuptools>=17.1
pexpect pexpect
pypandoc pypandoc
pytest-benchmark pytest-benchmark
pytest-docker-pexpect

View File

@@ -1,8 +1,14 @@
#!/usr/bin/env python #!/usr/bin/env python
from setuptools import setup, find_packages from setuptools import setup, find_packages
import pip
import sys import sys
import os import os
if int(pip.__version__.split('.')[0]) < 6:
print('pip older than 6.0 not supported, please upgrade pip with:\n\n'
' pip install -U pip')
sys.exit(-1)
if os.environ.get('CONVERT_README'): if os.environ.get('CONVERT_README'):
import pypandoc import pypandoc
@@ -20,10 +26,11 @@ elif (3, 0) < version < (3, 3):
' ({}.{} detected).'.format(*version)) ' ({}.{} detected).'.format(*version))
sys.exit(-1) sys.exit(-1)
VERSION = '2.9' VERSION = '3.8'
install_requires = ['psutil', 'colorama', 'six', 'decorator'] install_requires = ['psutil', 'colorama', 'six', 'decorator']
extras_require = {':python_version<"3.4"': ['pathlib']} extras_require = {':python_version<"3.4"': ['pathlib'],
":sys_platform=='win32'": ['win_unicode_console']}
setup(name='thefuck', setup(name='thefuck',
version=VERSION, version=VERSION,
@@ -34,11 +41,12 @@ setup(name='thefuck',
url='https://github.com/nvbn/thefuck', url='https://github.com/nvbn/thefuck',
license='MIT', license='MIT',
packages=find_packages(exclude=['ez_setup', 'examples', packages=find_packages(exclude=['ez_setup', 'examples',
'tests', 'release']), 'tests', 'tests.*', 'release']),
include_package_data=True, include_package_data=True,
zip_safe=False, zip_safe=False,
install_requires=install_requires, install_requires=install_requires,
extras_require=extras_require, extras_require=extras_require,
entry_points={'console_scripts': [ entry_points={'console_scripts': [
'thefuck = thefuck.main:main', 'thefuck = thefuck.main:main',
'thefuck-alias = thefuck.main:print_alias']}) 'thefuck-alias = thefuck.main:print_alias',
'fuck = thefuck.main:how_to_configure_alias']})

View File

@@ -1,5 +1,16 @@
from pathlib import Path
import pytest import pytest
from mock import Mock from thefuck import shells
from thefuck import conf, const
shells.shell = shells.Generic()
def pytest_addoption(parser):
"""Adds `--run-without-docker` argument."""
group = parser.getgroup("thefuck")
group.addoption('--enable-functional', action="store_true", default=False,
help="Enable functional tests")
@pytest.fixture @pytest.fixture
@@ -7,11 +18,45 @@ def no_memoize(monkeypatch):
monkeypatch.setattr('thefuck.utils.memoize.disabled', True) monkeypatch.setattr('thefuck.utils.memoize.disabled', True)
@pytest.fixture(autouse=True)
def settings(request):
def _reset_settings():
conf.settings.clear()
conf.settings.update(const.DEFAULT_SETTINGS)
request.addfinalizer(_reset_settings)
conf.settings.user_dir = Path('~/.thefuck')
return conf.settings
@pytest.fixture @pytest.fixture
def settings(): def no_colors(settings):
return Mock(debug=False, no_colors=True) settings.no_colors = True
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def no_cache(monkeypatch): def no_cache(monkeypatch):
monkeypatch.setattr('thefuck.utils.cache.disabled', True) monkeypatch.setattr('thefuck.utils.cache.disabled', True)
@pytest.fixture(autouse=True)
def functional(request):
if request.node.get_marker('functional') \
and not request.config.getoption('enable_functional'):
pytest.skip('functional tests are disabled')
@pytest.fixture
def source_root():
return Path(__file__).parent.parent.resolve()
@pytest.fixture
def set_shell(monkeypatch, request):
def _set(cls):
shell = cls()
monkeypatch.setattr('thefuck.shells.shell', shell)
request.addfinalizer()
return shell
return _set

View File

@@ -1,6 +1,3 @@
from pexpect import TIMEOUT
def _set_confirmation(proc, require): def _set_confirmation(proc, require):
proc.sendline(u'mkdir -p ~/.thefuck') proc.sendline(u'mkdir -p ~/.thefuck')
proc.sendline( proc.sendline(
@@ -8,7 +5,7 @@ def _set_confirmation(proc, require):
require)) require))
def with_confirmation(proc): def with_confirmation(proc, TIMEOUT):
"""Ensures that command can be fixed when confirmation enabled.""" """Ensures that command can be fixed when confirmation enabled."""
_set_confirmation(proc, True) _set_confirmation(proc, True)
@@ -23,19 +20,19 @@ def with_confirmation(proc):
assert proc.expect([TIMEOUT, u'test']) assert proc.expect([TIMEOUT, u'test'])
def history_changed(proc, to): def history_changed(proc, TIMEOUT, to):
"""Ensures that history changed.""" """Ensures that history changed."""
proc.send('\033[A') proc.send('\033[A')
assert proc.expect([TIMEOUT, to]) assert proc.expect([TIMEOUT, to])
def history_not_changed(proc): def history_not_changed(proc, TIMEOUT):
"""Ensures that history not changed.""" """Ensures that history not changed."""
proc.send('\033[A') proc.send('\033[A')
assert proc.expect([TIMEOUT, u'fuck']) assert proc.expect([TIMEOUT, u'fuck'])
def select_command_with_arrows(proc): def select_command_with_arrows(proc, TIMEOUT):
"""Ensures that command can be selected with arrow keys.""" """Ensures that command can be selected with arrow keys."""
_set_confirmation(proc, True) _set_confirmation(proc, True)
@@ -50,12 +47,14 @@ def select_command_with_arrows(proc):
assert proc.expect([TIMEOUT, u'git help']) assert proc.expect([TIMEOUT, u'git help'])
proc.send('\033[A') proc.send('\033[A')
assert proc.expect([TIMEOUT, u'git push']) assert proc.expect([TIMEOUT, u'git push'])
proc.send('\033[B')
assert proc.expect([TIMEOUT, u'git help'])
proc.send('\n') proc.send('\n')
assert proc.expect([TIMEOUT, u'Not a git repository']) assert proc.expect([TIMEOUT, u'usage'])
def refuse_with_confirmation(proc): def refuse_with_confirmation(proc, TIMEOUT):
"""Ensures that fix can be refused when confirmation enabled.""" """Ensures that fix can be refused when confirmation enabled."""
_set_confirmation(proc, True) _set_confirmation(proc, True)
@@ -70,7 +69,7 @@ def refuse_with_confirmation(proc):
assert proc.expect([TIMEOUT, u'Aborted']) assert proc.expect([TIMEOUT, u'Aborted'])
def without_confirmation(proc): def without_confirmation(proc, TIMEOUT):
"""Ensures that command can be fixed when confirmation disabled.""" """Ensures that command can be fixed when confirmation disabled."""
_set_confirmation(proc, False) _set_confirmation(proc, False)
@@ -79,3 +78,9 @@ def without_confirmation(proc):
proc.sendline(u'fuck') proc.sendline(u'fuck')
assert proc.expect([TIMEOUT, u'echo test']) assert proc.expect([TIMEOUT, u'echo test'])
assert proc.expect([TIMEOUT, u'test']) assert proc.expect([TIMEOUT, u'test'])
def how_to_configure(proc, TIMEOUT):
proc.sendline(u'unalias fuck')
proc.sendline(u'fuck')
assert proc.expect([TIMEOUT, u"alias isn't configured"])

View File

@@ -1,53 +1,67 @@
import pytest import pytest
from tests.functional.plots import with_confirmation, without_confirmation, \ from tests.functional.plots import with_confirmation, without_confirmation, \
refuse_with_confirmation, history_changed, history_not_changed, \ refuse_with_confirmation, history_changed, history_not_changed, \
select_command_with_arrows select_command_with_arrows, how_to_configure
from tests.functional.utils import spawn, functional, images
containers = images(('ubuntu-python3-bash', u''' containers = ((u'thefuck/ubuntu-python3-bash',
FROM ubuntu:latest u'''FROM ubuntu:latest
RUN apt-get update RUN apt-get update
RUN apt-get install -yy python3 python3-pip python3-dev git RUN apt-get install -yy python3 python3-pip python3-dev git
RUN pip3 install -U setuptools RUN pip3 install -U setuptools
RUN ln -s /usr/bin/pip3 /usr/bin/pip RUN ln -s /usr/bin/pip3 /usr/bin/pip''',
'''), u'bash'),
('ubuntu-python2-bash', u''' (u'thefuck/ubuntu-python2-bash',
FROM ubuntu:latest u'''FROM ubuntu:latest
RUN apt-get update RUN apt-get update
RUN apt-get install -yy python python-pip python-dev git RUN apt-get install -yy python python-pip python-dev git
RUN pip2 install -U pip setuptools RUN pip2 install -U pip setuptools''',
''')) u'bash'))
@pytest.fixture(params=containers) @pytest.fixture(params=containers)
def proc(request): def proc(request, spawnu, run_without_docker):
tag, dockerfile = request.param proc = spawnu(*request.param)
proc = spawn(request, tag, dockerfile, u'bash') if not run_without_docker:
proc.sendline(u"pip install /src")
proc.sendline(u"export PS1='$ '") proc.sendline(u"export PS1='$ '")
proc.sendline(u'eval $(thefuck --alias)') proc.sendline(u'eval $(thefuck --alias)')
proc.sendline(u'echo > $HISTFILE') proc.sendline(u'echo > $HISTFILE')
return proc return proc
@functional @pytest.mark.functional
def test_with_confirmation(proc): @pytest.mark.once_without_docker
with_confirmation(proc) def test_with_confirmation(proc, TIMEOUT, run_without_docker):
history_changed(proc, u'echo test') with_confirmation(proc, TIMEOUT)
if not run_without_docker:
history_changed(proc, TIMEOUT, u'echo test')
@functional @pytest.mark.functional
def test_select_command_with_arrows(proc): @pytest.mark.once_without_docker
select_command_with_arrows(proc) def test_select_command_with_arrows(proc, TIMEOUT, run_without_docker):
history_changed(proc, u'git push') select_command_with_arrows(proc, TIMEOUT)
if not run_without_docker:
history_changed(proc, TIMEOUT, u'git help')
@functional @pytest.mark.functional
def test_refuse_with_confirmation(proc): @pytest.mark.once_without_docker
refuse_with_confirmation(proc) def test_refuse_with_confirmation(proc, TIMEOUT, run_without_docker):
history_not_changed(proc) refuse_with_confirmation(proc, TIMEOUT)
if not run_without_docker:
history_not_changed(proc, TIMEOUT)
@functional @pytest.mark.functional
def test_without_confirmation(proc): @pytest.mark.once_without_docker
without_confirmation(proc) def test_without_confirmation(proc, TIMEOUT, run_without_docker):
history_changed(proc, u'echo test') without_confirmation(proc, TIMEOUT)
if not run_without_docker:
history_changed(proc, TIMEOUT, u'echo test')
@pytest.mark.functional
@pytest.mark.once_without_docker
def test_how_to_configure_alias(proc, TIMEOUT):
how_to_configure(proc, TIMEOUT)

View File

@@ -1,59 +1,54 @@
import pytest import pytest
from tests.functional.plots import with_confirmation, without_confirmation, \ from tests.functional.plots import with_confirmation, without_confirmation, \
refuse_with_confirmation, select_command_with_arrows refuse_with_confirmation, select_command_with_arrows
from tests.functional.utils import spawn, functional, images, bare
containers = images(('ubuntu-python3-fish', u''' containers = (('thefuck/ubuntu-python3-fish',
FROM ubuntu:latest u'''FROM ubuntu:latest
RUN apt-get update RUN apt-get update
RUN apt-get install -yy python3 python3-pip python3-dev fish git RUN apt-get install -yy python3 python3-pip python3-dev fish git
RUN pip3 install -U setuptools RUN pip3 install -U setuptools
RUN ln -s /usr/bin/pip3 /usr/bin/pip RUN ln -s /usr/bin/pip3 /usr/bin/pip
RUN apt-get install -yy fish RUN apt-get install -yy fish''',
'''), u'fish'),
('ubuntu-python2-fish', u''' ('thefuck/ubuntu-python2-fish',
FROM ubuntu:latest u'''FROM ubuntu:latest
RUN apt-get update RUN apt-get update
RUN apt-get install -yy python python-pip python-dev git RUN apt-get install -yy python python-pip python-dev git
RUN pip2 install -U pip setuptools RUN pip2 install -U pip setuptools
RUN apt-get install -yy fish RUN apt-get install -yy fish''',
''')) u'fish'))
@pytest.fixture(params=containers) @pytest.fixture(params=containers)
def proc(request): def proc(request, spawnu):
tag, dockerfile = request.param proc = spawnu(*request.param)
proc = spawn(request, tag, dockerfile, u'fish') proc.sendline(u"pip install /src")
proc.sendline(u'thefuck --alias > ~/.config/fish/config.fish') proc.sendline(u'thefuck --alias > ~/.config/fish/config.fish')
proc.sendline(u'fish') proc.sendline(u'fish')
return proc return proc
@functional @pytest.mark.functional
@pytest.mark.skipif( @pytest.mark.skip_without_docker
bool(bare), reason='https://github.com/travis-ci/apt-source-whitelist/issues/71') def test_with_confirmation(proc, TIMEOUT):
def test_with_confirmation(proc): with_confirmation(proc, TIMEOUT)
with_confirmation(proc)
@functional @pytest.mark.functional
@pytest.mark.skipif( @pytest.mark.skip_without_docker
bool(bare), reason='https://github.com/travis-ci/apt-source-whitelist/issues/71') def test_select_command_with_arrows(proc, TIMEOUT):
def test_select_command_with_arrows(proc): select_command_with_arrows(proc, TIMEOUT)
select_command_with_arrows(proc)
@functional @pytest.mark.functional
@pytest.mark.skipif( @pytest.mark.skip_without_docker
bool(bare), reason='https://github.com/travis-ci/apt-source-whitelist/issues/71') def test_refuse_with_confirmation(proc, TIMEOUT):
def test_refuse_with_confirmation(proc): refuse_with_confirmation(proc, TIMEOUT)
refuse_with_confirmation(proc)
@functional @pytest.mark.functional
@pytest.mark.skipif( @pytest.mark.skip_without_docker
bool(bare), reason='https://github.com/travis-ci/apt-source-whitelist/issues/71') def test_without_confirmation(proc, TIMEOUT):
def test_without_confirmation(proc): without_confirmation(proc, TIMEOUT)
without_confirmation(proc)
# TODO: ensure that history changes. # TODO: ensure that history changes.

View File

@@ -1,25 +1,25 @@
import pytest import pytest
from pexpect import TIMEOUT from thefuck.utils import get_installation_info
from tests.functional.utils import spawn, functional, bare
envs = ((u'bash', 'ubuntu-bash', u''' envs = ((u'bash', 'thefuck/ubuntu-bash', u'''
FROM ubuntu:latest FROM ubuntu:latest
RUN apt-get update RUN apt-get update
RUN apt-get install -yy bash RUN apt-get install -yy bash
'''), (u'bash', 'generic-bash', u''' '''), (u'bash', 'thefuck/generic-bash', u'''
FROM fedora:latest FROM fedora:latest
RUN dnf install -yy python-devel sudo which gcc RUN dnf install -yy python-devel sudo wget gcc
''')) '''))
@functional @pytest.mark.functional
@pytest.mark.skipif( @pytest.mark.skip_without_docker
bool(bare), reason="Can't be tested in bare run")
@pytest.mark.parametrize('shell, tag, dockerfile', envs) @pytest.mark.parametrize('shell, tag, dockerfile', envs)
def test_installation(request, shell, tag, dockerfile): def test_installation(spawnu, shell, TIMEOUT, tag, dockerfile):
proc = spawn(request, tag, dockerfile, shell, install=False) proc = spawnu(tag, dockerfile, shell)
proc.sendline(u'cat /src/install.sh | sh - && $0') proc.sendline(u'cat /src/install.sh | sh - && $0')
proc.sendline(u'thefuck --version') proc.sendline(u'thefuck --version')
assert proc.expect([TIMEOUT, u'The Fuck'], timeout=600) version = get_installation_info().version
assert proc.expect([TIMEOUT, u'thefuck {}'.format(version)],
timeout=600)
proc.sendline(u'fuck') proc.sendline(u'fuck')
assert proc.expect([TIMEOUT, u'No fucks given']) assert proc.expect([TIMEOUT, u'No fucks given'])

View File

@@ -1,7 +1,5 @@
from pexpect import TIMEOUT
import pytest import pytest
import time import time
from tests.functional.utils import spawn, functional, bare
dockerfile = u''' dockerfile = u'''
FROM ubuntu:latest FROM ubuntu:latest
@@ -11,24 +9,17 @@ RUN pip3 install -U setuptools
RUN ln -s /usr/bin/pip3 /usr/bin/pip RUN ln -s /usr/bin/pip3 /usr/bin/pip
RUN adduser --disabled-password --gecos '' test RUN adduser --disabled-password --gecos '' test
ENV SEED "{seed}" ENV SEED "{seed}"
COPY thefuck /src
WORKDIR /src WORKDIR /src
RUN pip install .
USER test USER test
RUN echo 'eval $(thefuck --alias)' > /home/test/.bashrc RUN echo 'eval $(thefuck --alias)' > /home/test/.bashrc
RUN echo > /home/test/.bash_history RUN echo > /home/test/.bash_history
RUN git config --global user.email "you@example.com" RUN git config --global user.email "you@example.com"
RUN git config --global user.name "Your Name" RUN git config --global user.name "Your Name"
USER root
'''.format(seed=time.time()) '''.format(seed=time.time())
@pytest.fixture def plot(proc, TIMEOUT):
def proc(request):
return spawn(request, 'ubuntu-python3-bash-performance',
dockerfile, u'bash', install=False, copy_src=True)
def plot(proc):
proc.sendline(u'cd /home/test/') proc.sendline(u'cd /home/test/')
proc.sendline(u'fuck') proc.sendline(u'fuck')
assert proc.expect([TIMEOUT, u'No fucks given']) assert proc.expect([TIMEOUT, u'No fucks given'])
@@ -48,9 +39,12 @@ def plot(proc):
assert proc.expect([TIMEOUT, u'test']) assert proc.expect([TIMEOUT, u'test'])
@functional @pytest.mark.functional
@pytest.mark.skipif( @pytest.mark.skip_without_docker
bool(bare), reason='Would lie on a bare run')
@pytest.mark.benchmark(min_rounds=10) @pytest.mark.benchmark(min_rounds=10)
def test_performance(proc, benchmark): def test_performance(spawnu, TIMEOUT, benchmark):
assert benchmark(plot, proc) is None proc = spawnu(u'thefuck/ubuntu-python3-bash-performance',
dockerfile, u'bash')
proc.sendline(u'pip install /src')
proc.sendline(u'su test')
assert benchmark(plot, proc, TIMEOUT) is None

View File

@@ -1,51 +1,55 @@
import pytest import pytest
from tests.functional.utils import spawn, functional, images
from tests.functional.plots import with_confirmation, without_confirmation, \ from tests.functional.plots import with_confirmation, without_confirmation, \
refuse_with_confirmation, select_command_with_arrows refuse_with_confirmation, select_command_with_arrows
containers = images(('ubuntu-python3-tcsh', u''' containers = (('thefuck/ubuntu-python3-tcsh',
FROM ubuntu:latest u'''FROM ubuntu:latest
RUN apt-get update RUN apt-get update
RUN apt-get install -yy python3 python3-pip python3-dev git RUN apt-get install -yy python3 python3-pip python3-dev git
RUN pip3 install -U setuptools RUN pip3 install -U setuptools
RUN ln -s /usr/bin/pip3 /usr/bin/pip RUN ln -s /usr/bin/pip3 /usr/bin/pip
RUN apt-get install -yy tcsh RUN apt-get install -yy tcsh''',
'''), u'tcsh'),
('ubuntu-python2-tcsh', u''' ('thefuck/ubuntu-python2-tcsh',
FROM ubuntu:latest u'''FROM ubuntu:latest
RUN apt-get update RUN apt-get update
RUN apt-get install -yy python python-pip python-dev git RUN apt-get install -yy python python-pip python-dev git
RUN pip2 install -U pip setuptools RUN pip2 install -U pip setuptools
RUN apt-get install -yy tcsh RUN apt-get install -yy tcsh''',
''')) u'tcsh'))
@pytest.fixture(params=containers) @pytest.fixture(params=containers)
def proc(request): def proc(request, spawnu, run_without_docker):
tag, dockerfile = request.param proc = spawnu(*request.param)
proc = spawn(request, tag, dockerfile, u'tcsh') if not run_without_docker:
proc.sendline(u'pip install /src')
proc.sendline(u'tcsh') proc.sendline(u'tcsh')
proc.sendline(u'eval `thefuck --alias`') proc.sendline(u'eval `thefuck --alias`')
return proc return proc
@functional @pytest.mark.functional
def test_with_confirmation(proc): @pytest.mark.once_without_docker
with_confirmation(proc) def test_with_confirmation(proc, TIMEOUT):
with_confirmation(proc, TIMEOUT)
@functional @pytest.mark.functional
def test_select_command_with_arrows(proc): @pytest.mark.once_without_docker
select_command_with_arrows(proc) def test_select_command_with_arrows(proc, TIMEOUT):
select_command_with_arrows(proc, TIMEOUT)
@functional @pytest.mark.functional
def test_refuse_with_confirmation(proc): @pytest.mark.once_without_docker
refuse_with_confirmation(proc) def test_refuse_with_confirmation(proc, TIMEOUT):
refuse_with_confirmation(proc, TIMEOUT)
@functional @pytest.mark.functional
def test_without_confirmation(proc): @pytest.mark.once_without_docker
without_confirmation(proc) def test_without_confirmation(proc, TIMEOUT):
without_confirmation(proc, TIMEOUT)
# TODO: ensure that history changes. # TODO: ensure that history changes.

View File

@@ -1,29 +1,30 @@
import pytest import pytest
from tests.functional.utils import spawn, functional, images
from tests.functional.plots import with_confirmation, without_confirmation, \ from tests.functional.plots import with_confirmation, without_confirmation, \
refuse_with_confirmation, history_changed, history_not_changed, select_command_with_arrows refuse_with_confirmation, history_changed, history_not_changed, \
select_command_with_arrows, how_to_configure
containers = images(('ubuntu-python3-zsh', u''' containers = (('thefuck/ubuntu-python3-zsh',
FROM ubuntu:latest u'''FROM ubuntu:latest
RUN apt-get update RUN apt-get update
RUN apt-get install -yy python3 python3-pip python3-dev git RUN apt-get install -yy python3 python3-pip python3-dev git
RUN pip3 install -U setuptools RUN pip3 install -U setuptools
RUN ln -s /usr/bin/pip3 /usr/bin/pip RUN ln -s /usr/bin/pip3 /usr/bin/pip
RUN apt-get install -yy zsh RUN apt-get install -yy zsh''',
'''), u'zsh'),
('ubuntu-python2-zsh', u''' ('thefuck/ubuntu-python2-zsh',
FROM ubuntu:latest u'''FROM ubuntu:latest
RUN apt-get update RUN apt-get update
RUN apt-get install -yy python python-pip python-dev git RUN apt-get install -yy python python-pip python-dev git
RUN pip2 install -U pip setuptools RUN pip2 install -U pip setuptools
RUN apt-get install -yy zsh RUN apt-get install -yy zsh''',
''')) u'zsh'))
@pytest.fixture(params=containers) @pytest.fixture(params=containers)
def proc(request): def proc(request, spawnu, run_without_docker):
tag, dockerfile = request.param proc = spawnu(*request.param)
proc = spawn(request, tag, dockerfile, u'zsh') if not run_without_docker:
proc.sendline(u'pip install /src')
proc.sendline(u'eval $(thefuck --alias)') proc.sendline(u'eval $(thefuck --alias)')
proc.sendline(u'export HISTFILE=~/.zsh_history') proc.sendline(u'export HISTFILE=~/.zsh_history')
proc.sendline(u'echo > $HISTFILE') proc.sendline(u'echo > $HISTFILE')
@@ -33,25 +34,35 @@ def proc(request):
return proc return proc
@functional @pytest.mark.functional
def test_with_confirmation(proc): @pytest.mark.once_without_docker
with_confirmation(proc) def test_with_confirmation(proc, TIMEOUT):
history_changed(proc, u'echo test') with_confirmation(proc, TIMEOUT)
history_changed(proc, TIMEOUT, u'echo test')
@functional @pytest.mark.functional
def test_select_command_with_arrows(proc): @pytest.mark.once_without_docker
select_command_with_arrows(proc) def test_select_command_with_arrows(proc, TIMEOUT):
history_changed(proc, u'git push') select_command_with_arrows(proc, TIMEOUT)
history_changed(proc, TIMEOUT, u'git help')
@functional @pytest.mark.functional
def test_refuse_with_confirmation(proc): @pytest.mark.skip_without_docker
refuse_with_confirmation(proc) def test_refuse_with_confirmation(proc, TIMEOUT):
history_not_changed(proc) refuse_with_confirmation(proc, TIMEOUT)
history_not_changed(proc, TIMEOUT)
@functional @pytest.mark.functional
def test_without_confirmation(proc): @pytest.mark.once_without_docker
without_confirmation(proc) def test_without_confirmation(proc, TIMEOUT):
history_changed(proc, u'echo test') without_confirmation(proc, TIMEOUT)
history_changed(proc, TIMEOUT, u'echo test')
@pytest.mark.functional
@pytest.mark.once_without_docker
def test_how_to_configure_alias(proc, TIMEOUT):
how_to_configure(proc, TIMEOUT)

View File

@@ -1,65 +0,0 @@
import pytest
import os
import subprocess
import shutil
from tempfile import mkdtemp
from pathlib import Path
import sys
import pexpect
from tests.utils import root
bare = os.environ.get('BARE')
enabled = os.environ.get('FUNCTIONAL')
def build_container(tag, dockerfile, copy_src=False):
tmpdir = mkdtemp()
try:
if copy_src:
subprocess.call(['cp', '-a', str(root), tmpdir])
dockerfile_path = Path(tmpdir).joinpath('Dockerfile')
with dockerfile_path.open('w') as file:
file.write(dockerfile)
if subprocess.call(['docker', 'build', '--tag={}'.format(tag), tmpdir]) != 0:
raise Exception("Can't build a container")
finally:
shutil.rmtree(tmpdir)
def spawn(request, tag, dockerfile, cmd, install=True, copy_src=False):
if bare:
proc = pexpect.spawnu(cmd)
else:
tag = 'thefuck/{}'.format(tag)
build_container(tag, dockerfile, copy_src)
proc = pexpect.spawnu('docker run --rm=true --volume {}:/src --tty=true '
'--interactive=true {} {}'.format(root, tag, cmd))
if install:
proc.sendline('pip install /src')
proc.sendline('cd /')
proc.logfile = sys.stdout
def _finalizer():
proc.terminate()
if not bare:
container_id = subprocess.check_output(['docker', 'ps']) \
.decode('utf-8').split('\n')[-2].split()[0]
subprocess.check_call(['docker', 'kill', container_id])
request.addfinalizer(_finalizer)
return proc
def images(*items):
if bare:
return [items[0]]
else:
return items
functional = pytest.mark.skipif(
not enabled,
reason='Functional tests are disabled by default.')

View File

@@ -1,6 +0,0 @@
import pytest
@pytest.fixture(autouse=True)
def generic_shell(monkeypatch):
monkeypatch.setattr('thefuck.shells.and_', lambda *x: ' && '.join(x))

View File

@@ -11,7 +11,7 @@ from tests.utils import Command
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
Command(script='vim', stderr='vim: command not found')]) Command(script='vim', stderr='vim: command not found')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command, return_value', [ @pytest.mark.parametrize('command, return_value', [
@@ -24,15 +24,30 @@ def test_match(command):
def test_match_mocked(cmdnf_mock, command, return_value): def test_match_mocked(cmdnf_mock, command, return_value):
get_packages = Mock(return_value=return_value) get_packages = Mock(return_value=return_value)
cmdnf_mock.CommandNotFound.return_value = Mock(getPackages=get_packages) cmdnf_mock.CommandNotFound.return_value = Mock(getPackages=get_packages)
assert match(command, None) assert match(command)
assert cmdnf_mock.CommandNotFound.called assert cmdnf_mock.CommandNotFound.called
assert get_packages.called assert get_packages.called
# python-commandnotfound is available in ubuntu 14.04+
@pytest.mark.skipif(not getattr(apt_get, 'enabled_by_default', True),
reason='Skip if python-commandnotfound is not available')
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
Command(script='a_bad_cmd', stderr='a_bad_cmd: command not found'),
Command(script='vim', stderr=''), Command()]) Command(script='vim', stderr=''), Command()])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
@pytest.mark.parametrize('command, return_value', [
(Command(script='a_bad_cmd', stderr='a_bad_cmd: command not found'), []),
(Command(script='vim', stderr=''), []), (Command(), [])])
@patch('thefuck.rules.apt_get.CommandNotFound', create=True)
@patch.multiple(apt_get, create=True, apt_get='apt_get')
def test_not_match_mocked(cmdnf_mock, command, return_value):
get_packages = Mock(return_value=return_value)
cmdnf_mock.CommandNotFound.return_value = Mock(getPackages=get_packages)
assert not match(command)
# python-commandnotfound is available in ubuntu 14.04+ # python-commandnotfound is available in ubuntu 14.04+
@@ -44,7 +59,7 @@ def test_not_match(command):
(Command('sudo vim'), 'sudo apt-get install vim && sudo vim'), (Command('sudo vim'), 'sudo apt-get install vim && sudo vim'),
(Command('sudo convert'), 'sudo apt-get install imagemagick && sudo convert')]) (Command('sudo convert'), 'sudo apt-get install imagemagick && sudo convert')])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command
@pytest.mark.parametrize('command, new_command, return_value', [ @pytest.mark.parametrize('command, new_command, return_value', [
@@ -63,4 +78,4 @@ def test_get_new_command(command, new_command):
def test_get_new_command_mocked(cmdnf_mock, command, new_command, return_value): def test_get_new_command_mocked(cmdnf_mock, command, new_command, return_value):
get_packages = Mock(return_value=return_value) get_packages = Mock(return_value=return_value)
cmdnf_mock.CommandNotFound.return_value = Mock(getPackages=get_packages) cmdnf_mock.CommandNotFound.return_value = Mock(getPackages=get_packages)
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -4,7 +4,7 @@ from tests.utils import Command
def test_match(): def test_match():
assert match(Command('apt-get search foo'), None) assert match(Command('apt-get search foo'))
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
@@ -18,8 +18,8 @@ def test_match():
Command('apt-get update') Command('apt-get update')
]) ])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
def test_get_new_command(): def test_get_new_command():
assert get_new_command(Command('apt-get search foo'), None) == 'apt-cache search foo' assert get_new_command(Command('apt-get search foo')) == 'apt-cache search foo'

View File

@@ -0,0 +1,122 @@
from io import BytesIO
import pytest
from tests.utils import Command
from thefuck.rules.apt_invalid_operation import match, get_new_command, \
_get_operations
invalid_operation = 'E: Invalid operation {}'.format
apt_help = b'''apt 1.0.10.2ubuntu1 for amd64 compiled on Oct 5 2015 15:55:05
Usage: apt [options] command
CLI for apt.
Basic commands:
list - list packages based on package names
search - search in package descriptions
show - show package details
update - update list of available packages
install - install packages
remove - remove packages
upgrade - upgrade the system by installing/upgrading packages
full-upgrade - upgrade the system by removing/installing/upgrading packages
edit-sources - edit the source information file
'''
apt_operations = ['list', 'search', 'show', 'update', 'install', 'remove',
'upgrade', 'full-upgrade', 'edit-sources']
apt_get_help = b'''apt 1.0.10.2ubuntu1 for amd64 compiled on Oct 5 2015 15:55:05
Usage: apt-get [options] command
apt-get [options] install|remove pkg1 [pkg2 ...]
apt-get [options] source pkg1 [pkg2 ...]
apt-get is a simple command line interface for downloading and
installing packages. The most frequently used commands are update
and install.
Commands:
update - Retrieve new lists of packages
upgrade - Perform an upgrade
install - Install new packages (pkg is libc6 not libc6.deb)
remove - Remove packages
autoremove - Remove automatically all unused packages
purge - Remove packages and config files
source - Download source archives
build-dep - Configure build-dependencies for source packages
dist-upgrade - Distribution upgrade, see apt-get(8)
dselect-upgrade - Follow dselect selections
clean - Erase downloaded archive files
autoclean - Erase old downloaded archive files
check - Verify that there are no broken dependencies
changelog - Download and display the changelog for the given package
download - Download the binary package into the current directory
Options:
-h This help text.
-q Loggable output - no progress indicator
-qq No output except for errors
-d Download only - do NOT install or unpack archives
-s No-act. Perform ordering simulation
-y Assume Yes to all queries and do not prompt
-f Attempt to correct a system with broken dependencies in place
-m Attempt to continue if archives are unlocatable
-u Show a list of upgraded packages as well
-b Build the source package after fetching it
-V Show verbose version numbers
-c=? Read this configuration file
-o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp
See the apt-get(8), sources.list(5) and apt.conf(5) manual
pages for more information and options.
This APT has Super Cow Powers.
'''
apt_get_operations = ['update', 'upgrade', 'install', 'remove', 'autoremove',
'purge', 'source', 'build-dep', 'dist-upgrade',
'dselect-upgrade', 'clean', 'autoclean', 'check',
'changelog', 'download']
@pytest.mark.parametrize('script, stderr', [
('apt', invalid_operation('saerch')),
('apt-get', invalid_operation('isntall')),
('apt-cache', invalid_operation('rumove'))])
def test_match(script, stderr):
assert match(Command(script, stderr=stderr))
@pytest.mark.parametrize('script, stderr', [
('vim', invalid_operation('vim')),
('apt-get', "")])
def test_not_match(script, stderr):
assert not match(Command(script, stderr=stderr))
@pytest.fixture
def set_help(mocker):
mock = mocker.patch('subprocess.Popen')
def _set_text(text):
mock.return_value.stdout = BytesIO(text)
return _set_text
@pytest.mark.parametrize('app, help_text, operations', [
('apt', apt_help, apt_operations),
('apt-get', apt_get_help, apt_get_operations)
])
def test_get_operations(set_help, app, help_text, operations):
set_help(help_text)
assert _get_operations(app) == operations
@pytest.mark.parametrize('script, stderr, help_text, result', [
('apt-get isntall vim', invalid_operation('isntall'),
apt_get_help, 'apt-get install vim'),
('apt saerch vim', invalid_operation('saerch'),
apt_help, 'apt search vim'),
])
def test_get_new_command(set_help, stderr, script, help_text, result):
set_help(help_text)
assert get_new_command(Command(script, stderr=stderr))[0] == result

View File

@@ -28,20 +28,19 @@ def _is_not_okay_to_test():
def test_match(brew_no_available_formula, brew_already_installed, def test_match(brew_no_available_formula, brew_already_installed,
brew_install_no_argument): brew_install_no_argument):
assert match(Command('brew install elsticsearch', assert match(Command('brew install elsticsearch',
stderr=brew_no_available_formula), None) stderr=brew_no_available_formula))
assert not match(Command('brew install git', assert not match(Command('brew install git',
stderr=brew_already_installed), None) stderr=brew_already_installed))
assert not match(Command('brew install', stderr=brew_install_no_argument), assert not match(Command('brew install', stderr=brew_install_no_argument))
None)
@pytest.mark.skipif(_is_not_okay_to_test(), @pytest.mark.skipif(_is_not_okay_to_test(),
reason='No need to run if there\'s no formula') reason='No need to run if there\'s no formula')
def test_get_new_command(brew_no_available_formula): def test_get_new_command(brew_no_available_formula):
assert get_new_command(Command('brew install elsticsearch', assert get_new_command(Command('brew install elsticsearch',
stderr=brew_no_available_formula), None)\ stderr=brew_no_available_formula))\
== 'brew install elasticsearch' == 'brew install elasticsearch'
assert get_new_command(Command('brew install aa', assert get_new_command(Command('brew install aa',
stderr=brew_no_available_formula), stderr=brew_no_available_formula))\
None) != 'brew install aha' != 'brew install aha'

View File

@@ -15,15 +15,15 @@ def brew_unknown_cmd2():
def test_match(brew_unknown_cmd): def test_match(brew_unknown_cmd):
assert match(Command('brew inst', stderr=brew_unknown_cmd), None) assert match(Command('brew inst', stderr=brew_unknown_cmd))
for command in _brew_commands(): for command in _brew_commands():
assert not match(Command('brew ' + command), None) assert not match(Command('brew ' + command))
def test_get_new_command(brew_unknown_cmd, brew_unknown_cmd2): def test_get_new_command(brew_unknown_cmd, brew_unknown_cmd2):
assert get_new_command(Command('brew inst', stderr=brew_unknown_cmd), assert get_new_command(Command('brew inst', stderr=brew_unknown_cmd)) \
None) == ['brew list', 'brew install', 'brew uninstall'] == ['brew list', 'brew install', 'brew uninstall']
cmds = get_new_command(Command('brew instaa', stderr=brew_unknown_cmd2), None) cmds = get_new_command(Command('brew instaa', stderr=brew_unknown_cmd2))
assert 'brew install' in cmds assert 'brew install' in cmds
assert 'brew uninstall' in cmds assert 'brew uninstall' in cmds

View File

@@ -6,10 +6,10 @@ from tests.utils import Command
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
Command(script='brew upgrade')]) Command(script='brew upgrade')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
(Command('brew upgrade'), 'brew upgrade --all')]) (Command('brew upgrade'), 'brew upgrade --all')])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -12,10 +12,10 @@ no_such_subcommand = """No such subcommand
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
Command(script='cargo buid', stderr=no_such_subcommand)]) Command(script='cargo buid', stderr=no_such_subcommand)])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
(Command('cargo buid', stderr=no_such_subcommand), 'cargo build')]) (Command('cargo buid', stderr=no_such_subcommand), 'cargo build')])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -9,17 +9,17 @@ from tests.utils import Command
stderr='cd: foo: No such file or directory'), stderr='cd: foo: No such file or directory'),
Command(script='cd foo/bar/baz', stderr='cd: can\'t cd to foo/bar/baz')]) Command(script='cd foo/bar/baz', stderr='cd: can\'t cd to foo/bar/baz')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
Command(script='cd foo', stderr=''), Command()]) Command(script='cd foo', stderr=''), Command()])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
(Command('cd foo'), 'mkdir -p foo && cd foo'), (Command('cd foo'), 'mkdir -p foo && cd foo'),
(Command('cd foo/bar/baz'), 'mkdir -p foo/bar/baz && cd foo/bar/baz')]) (Command('cd foo/bar/baz'), 'mkdir -p foo/bar/baz && cd foo/bar/baz')])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -3,10 +3,10 @@ from tests.utils import Command
def test_match(): def test_match():
assert match(Command('cd..', stderr='cd..: command not found'), None) assert match(Command('cd..', stderr='cd..: command not found'))
assert not match(Command(), None) assert not match(Command())
def test_get_new_command(): def test_get_new_command():
assert get_new_command( assert get_new_command(
Command('cd..'), None) == 'cd ..' Command('cd..')) == 'cd ..'

View File

@@ -41,17 +41,16 @@ def composer_not_command_one_of_this():
def test_match(composer_not_command, composer_not_command_one_of_this): def test_match(composer_not_command, composer_not_command_one_of_this):
assert match(Command('composer udpate', assert match(Command('composer udpate',
stderr=composer_not_command), None) stderr=composer_not_command))
assert match(Command('composer pdate', assert match(Command('composer pdate',
stderr=composer_not_command_one_of_this), None) stderr=composer_not_command_one_of_this))
assert not match(Command('ls update', stderr=composer_not_command), assert not match(Command('ls update', stderr=composer_not_command))
None)
def test_get_new_command(composer_not_command, composer_not_command_one_of_this): def test_get_new_command(composer_not_command, composer_not_command_one_of_this):
assert get_new_command(Command('composer udpate', assert get_new_command(Command('composer udpate',
stderr=composer_not_command), None) \ stderr=composer_not_command)) \
== 'composer update' == 'composer update'
assert get_new_command( assert get_new_command(
Command('composer pdate', stderr=composer_not_command_one_of_this), Command('composer pdate', stderr=composer_not_command_one_of_this)) \
None) == 'composer selfupdate' == 'composer selfupdate'

View File

@@ -7,7 +7,7 @@ from tests.utils import Command
('cp dir', 'cp: dor: is a directory'), ('cp dir', 'cp: dor: is a directory'),
('cp dir', "cp: omitting directory 'dir'")]) ('cp dir', "cp: omitting directory 'dir'")])
def test_match(script, stderr): def test_match(script, stderr):
assert match(Command(script, stderr=stderr), None) assert match(Command(script, stderr=stderr))
@pytest.mark.parametrize('script, stderr', [ @pytest.mark.parametrize('script, stderr', [
@@ -15,8 +15,8 @@ def test_match(script, stderr):
('some dir', "cp: omitting directory 'dir'"), ('some dir', "cp: omitting directory 'dir'"),
('cp dir', '')]) ('cp dir', '')])
def test_not_match(script, stderr): def test_not_match(script, stderr):
assert not match(Command(script, stderr=stderr), None) assert not match(Command(script, stderr=stderr))
def test_get_new_command(): def test_get_new_command():
assert get_new_command(Command(script='cp dir'), None) == 'cp -a dir' assert get_new_command(Command(script='cp dir')) == 'cp -a dir'

View File

@@ -1,7 +1,8 @@
import os import os
import pytest import pytest
import tarfile import tarfile
from thefuck.rules.dirty_untar import match, get_new_command, side_effect from thefuck.rules.dirty_untar import match, get_new_command, side_effect, \
tar_extensions
from tests.utils import Command from tests.utils import Command
@@ -11,8 +12,9 @@ def tar_error(tmpdir):
path = os.path.join(str(tmpdir), filename) path = os.path.join(str(tmpdir), filename)
def reset(path): def reset(path):
os.mkdir('d')
with tarfile.TarFile(path, 'w') as archive: with tarfile.TarFile(path, 'w') as archive:
for file in ('a', 'b', 'c'): for file in ('a', 'b', 'c', 'd/e'):
with open(file, 'w') as f: with open(file, 'w') as f:
f.write('*') f.write('*')
@@ -26,38 +28,46 @@ def tar_error(tmpdir):
os.chdir(str(tmpdir)) os.chdir(str(tmpdir))
reset(path) reset(path)
assert(set(os.listdir('.')) == {filename, 'a', 'b', 'c'}) assert set(os.listdir('.')) == {filename, 'a', 'b', 'c', 'd'}
assert set(os.listdir('./d')) == {'e'}
return fixture return fixture
parametrize_filename = pytest.mark.parametrize('filename', [ parametrize_extensions = pytest.mark.parametrize('ext', tar_extensions)
'foo.tar',
'foo.tar.gz', # (filename as typed by the user, unquoted filename, quoted filename as per shells.quote)
'foo.tgz']) parametrize_filename = pytest.mark.parametrize('filename, unquoted, quoted', [
('foo{}', 'foo{}', 'foo{}'),
('foo\ bar{}', 'foo bar{}', "'foo bar{}'"),
('"foo bar{}"', 'foo bar{}', "'foo bar{}'")])
parametrize_script = pytest.mark.parametrize('script, fixed', [ parametrize_script = pytest.mark.parametrize('script, fixed', [
('tar xvf {}', 'mkdir -p foo && tar xvf {} -C foo'), ('tar xvf {}', 'mkdir -p {dir} && tar xvf {filename} -C {dir}'),
('tar -xvf {}', 'mkdir -p foo && tar -xvf {} -C foo'), ('tar -xvf {}', 'mkdir -p {dir} && tar -xvf {filename} -C {dir}'),
('tar --extract -f {}', 'mkdir -p foo && tar --extract -f {} -C foo')]) ('tar --extract -f {}', 'mkdir -p {dir} && tar --extract -f {filename} -C {dir}')])
@parametrize_extensions
@parametrize_filename @parametrize_filename
@parametrize_script @parametrize_script
def test_match(tar_error, filename, script, fixed): def test_match(ext, tar_error, filename, unquoted, quoted, script, fixed):
tar_error(filename) tar_error(unquoted.format(ext))
assert match(Command(script=script.format(filename)), None) assert match(Command(script=script.format(filename.format(ext))))
@parametrize_extensions
@parametrize_filename @parametrize_filename
@parametrize_script @parametrize_script
def test_side_effect(tar_error, filename, script, fixed): def test_side_effect(ext, tar_error, filename, unquoted, quoted, script, fixed):
tar_error(filename) tar_error(unquoted.format(ext))
side_effect(Command(script=script.format(filename)), None, None) side_effect(Command(script=script.format(filename.format(ext))), None)
assert(os.listdir('.') == [filename]) assert set(os.listdir('.')) == {unquoted.format(ext), 'd'}
@parametrize_extensions
@parametrize_filename @parametrize_filename
@parametrize_script @parametrize_script
def test_get_new_command(tar_error, filename, script, fixed): def test_get_new_command(ext, tar_error, filename, unquoted, quoted, script, fixed):
tar_error(filename) tar_error(unquoted.format(ext))
assert get_new_command(Command(script=script.format(filename)), None) == fixed.format(filename) assert (get_new_command(Command(script=script.format(filename.format(ext))))
== fixed.format(dir=quoted.format(''), filename=filename.format(ext)))

View File

@@ -1,45 +1,72 @@
# -*- coding: utf-8 -*-
import os import os
import pytest import pytest
import zipfile import zipfile
from thefuck.rules.dirty_unzip import match, get_new_command, side_effect from thefuck.rules.dirty_unzip import match, get_new_command, side_effect
from tests.utils import Command from tests.utils import Command
from unicodedata import normalize
@pytest.fixture @pytest.fixture
def zip_error(tmpdir): def zip_error(tmpdir):
path = os.path.join(str(tmpdir), 'foo.zip') def zip_error_inner(filename):
path = os.path.join(str(tmpdir), filename)
def reset(path): def reset(path):
with zipfile.ZipFile(path, 'w') as archive: with zipfile.ZipFile(path, 'w') as archive:
archive.writestr('a', '1') archive.writestr('a', '1')
archive.writestr('b', '2') archive.writestr('b', '2')
archive.writestr('c', '3') archive.writestr('c', '3')
archive.extractall() archive.writestr('d/e', '4')
os.chdir(str(tmpdir)) archive.extractall()
reset(path)
assert(set(os.listdir('.')) == {'foo.zip', 'a', 'b', 'c'}) os.chdir(str(tmpdir))
reset(path)
dir_list = os.listdir(u'.')
if filename not in dir_list:
filename = normalize('NFD', filename)
assert set(dir_list) == {filename, 'a', 'b', 'c', 'd'}
assert set(os.listdir('./d')) == {'e'}
return zip_error_inner
@pytest.mark.parametrize('script', [ @pytest.mark.parametrize('script,filename', [
'unzip foo', (u'unzip café', u'café.zip'),
'unzip foo.zip']) (u'unzip café.zip', u'café.zip'),
def test_match(zip_error, script): (u'unzip foo', u'foo.zip'),
assert match(Command(script=script), None) (u'unzip foo.zip', u'foo.zip')])
def test_match(zip_error, script, filename):
zip_error(filename)
assert match(Command(script=script))
@pytest.mark.parametrize('script', [ @pytest.mark.parametrize('script,filename', [
'unzip foo', (u'unzip café', u'café.zip'),
'unzip foo.zip']) (u'unzip café.zip', u'café.zip'),
def test_side_effect(zip_error, script): (u'unzip foo', u'foo.zip'),
side_effect(Command(script=script), None, None) (u'unzip foo.zip', u'foo.zip')])
assert(os.listdir('.') == ['foo.zip']) def test_side_effect(zip_error, script, filename):
zip_error(filename)
side_effect(Command(script=script), None)
dir_list = os.listdir(u'.')
if filename not in set(dir_list):
filename = normalize('NFD', filename)
assert set(dir_list) == {filename, 'd'}
@pytest.mark.parametrize('script,fixed', [ @pytest.mark.parametrize('script,fixed,filename', [
('unzip foo', 'unzip foo -d foo'), (u'unzip café', u"unzip café -d 'café'", u'café.zip'),
('unzip foo.zip', 'unzip foo.zip -d foo')]) (u'unzip foo', u'unzip foo -d foo', u'foo.zip'),
def test_get_new_command(zip_error, script, fixed): (u"unzip foo\\ bar.zip", u"unzip foo\\ bar.zip -d 'foo bar'", u'foo.zip'),
assert get_new_command(Command(script=script), None) == fixed (u"unzip 'foo bar.zip'", u"unzip 'foo bar.zip' -d 'foo bar'", u'foo.zip'),
(u'unzip foo.zip', u'unzip foo.zip -d foo', u'foo.zip')])
def test_get_new_command(zip_error, script, fixed, filename):
zip_error(filename)
assert get_new_command(Command(script=script)) == fixed

View File

@@ -41,13 +41,13 @@ south.exceptions.GhostMigrations:
def test_match(stderr): def test_match(stderr):
assert match(Command('./manage.py migrate', stderr=stderr), None) assert match(Command('./manage.py migrate', stderr=stderr))
assert match(Command('python manage.py migrate', stderr=stderr), None) assert match(Command('python manage.py migrate', stderr=stderr))
assert not match(Command('./manage.py migrate'), None) assert not match(Command('./manage.py migrate'))
assert not match(Command('app migrate', stderr=stderr), None) assert not match(Command('app migrate', stderr=stderr))
assert not match(Command('./manage.py test', stderr=stderr), None) assert not match(Command('./manage.py test', stderr=stderr))
def test_get_new_command(): def test_get_new_command():
assert get_new_command(Command('./manage.py migrate auth'), None)\ assert get_new_command(Command('./manage.py migrate auth'))\
== './manage.py migrate auth --delete-ghost-migrations' == './manage.py migrate auth --delete-ghost-migrations'

View File

@@ -31,13 +31,13 @@ The following options are available:
def test_match(stderr): def test_match(stderr):
assert match(Command('./manage.py migrate', stderr=stderr), None) assert match(Command('./manage.py migrate', stderr=stderr))
assert match(Command('python manage.py migrate', stderr=stderr), None) assert match(Command('python manage.py migrate', stderr=stderr))
assert not match(Command('./manage.py migrate'), None) assert not match(Command('./manage.py migrate'))
assert not match(Command('app migrate', stderr=stderr), None) assert not match(Command('app migrate', stderr=stderr))
assert not match(Command('./manage.py test', stderr=stderr), None) assert not match(Command('./manage.py test', stderr=stderr))
def test_get_new_command(): def test_get_new_command():
assert get_new_command(Command('./manage.py migrate auth'), None) \ assert get_new_command(Command('./manage.py migrate auth')) \
== './manage.py migrate auth --merge' == './manage.py migrate auth --merge'

View File

@@ -110,14 +110,14 @@ def stderr(cmd):
def test_match(): def test_match():
assert match(Command('docker pes', stderr=stderr('pes')), None) assert match(Command('docker pes', stderr=stderr('pes')))
@pytest.mark.parametrize('script, stderr', [ @pytest.mark.parametrize('script, stderr', [
('docker ps', ''), ('docker ps', ''),
('cat pes', stderr('pes'))]) ('cat pes', stderr('pes'))])
def test_not_match(script, stderr): def test_not_match(script, stderr):
assert not match(Command(script, stderr=stderr), None) assert not match(Command(script, stderr=stderr))
@pytest.mark.usefixtures('docker_help') @pytest.mark.usefixtures('docker_help')
@@ -126,4 +126,4 @@ def test_not_match(script, stderr):
('tags', ['tag', 'stats', 'images'])]) ('tags', ['tag', 'stats', 'images'])])
def test_get_new_command(wrong, fixed): def test_get_new_command(wrong, fixed):
command = Command('docker {}'.format(wrong), stderr=stderr(wrong)) command = Command('docker {}'.format(wrong), stderr=stderr(wrong))
assert get_new_command(command, None) == ['docker {}'.format(x) for x in fixed] assert get_new_command(command) == ['docker {}'.format(x) for x in fixed]

View File

@@ -7,11 +7,11 @@ from tests.utils import Command
Command(script='cd cd foo'), Command(script='cd cd foo'),
Command(script='git git push origin/master')]) Command(script='git git push origin/master')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
(Command('cd cd foo'), 'cd foo'), (Command('cd cd foo'), 'cd foo'),
(Command('git git push origin/master'), 'git push origin/master')]) (Command('git git push origin/master'), 'git push origin/master')])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -11,12 +11,12 @@ def test_match():
""" """
assert match(Command(u'ps -ef | grep foo', assert match(Command(u'ps -ef | grep foo',
stderr=u'-bash:  grep: command not found'), None) stderr=u'-bash:  grep: command not found'))
assert not match(Command('ps -ef | grep foo'), None) assert not match(Command('ps -ef | grep foo'))
assert not match(Command(), None) assert not match(Command())
def test_get_new_command(): def test_get_new_command():
""" Replace the Alt+Space character by a simple space """ """ Replace the Alt+Space character by a simple space """
assert get_new_command(Command(u'ps -ef | grep foo'), None)\ assert get_new_command(Command(u'ps -ef | grep foo'))\
== 'ps -ef | grep foo' == 'ps -ef | grep foo'

View File

@@ -1,8 +1,9 @@
# -*- coding: utf-8 -*-
import pytest import pytest
import os import os
from thefuck.rules.fix_file import match, get_new_command from thefuck.rules.fix_file import match, get_new_command
from tests.utils import Command from tests.utils import Command
from thefuck.types import Settings
# (script, file, line, col (or None), stdout, stderr) # (script, file, line, col (or None), stdout, stderr)
@@ -88,6 +89,20 @@ Traceback (most recent call last):
TypeError: first argument must be string or compiled pattern TypeError: first argument must be string or compiled pattern
"""), """),
(u'python café.py', u'café.py', 8, None, '',
u"""
Traceback (most recent call last):
File "café.py", line 8, in <module>
match("foo")
File "café.py", line 5, in match
m = re.search(None, command)
File "/usr/lib/python3.4/re.py", line 170, in search
return _compile(pattern, flags).search(string)
File "/usr/lib/python3.4/re.py", line 293, in _compile
raise TypeError("first argument must be string or compiled pattern")
TypeError: first argument must be string or compiled pattern
"""),
('ruby a.rb', 'a.rb', 3, None, '', ('ruby a.rb', 'a.rb', 3, None, '',
""" """
a.rb:3: syntax error, unexpected keyword_end a.rb:3: syntax error, unexpected keyword_end
@@ -184,7 +199,7 @@ E NameError: name 'mocker' is not defined
def test_match(mocker, monkeypatch, test): def test_match(mocker, monkeypatch, test):
mocker.patch('os.path.isfile', return_value=True) mocker.patch('os.path.isfile', return_value=True)
monkeypatch.setenv('EDITOR', 'dummy_editor') monkeypatch.setenv('EDITOR', 'dummy_editor')
assert match(Command(stdout=test[4], stderr=test[5]), None) assert match(Command(stdout=test[4], stderr=test[5]))
@pytest.mark.parametrize('test', tests) @pytest.mark.parametrize('test', tests)
@@ -194,7 +209,7 @@ def test_no_editor(mocker, monkeypatch, test):
if 'EDITOR' in os.environ: if 'EDITOR' in os.environ:
monkeypatch.delenv('EDITOR') monkeypatch.delenv('EDITOR')
assert not match(Command(stdout=test[4], stderr=test[5]), None) assert not match(Command(stdout=test[4], stderr=test[5]))
@pytest.mark.parametrize('test', tests) @pytest.mark.parametrize('test', tests)
@@ -203,7 +218,7 @@ def test_not_file(mocker, monkeypatch, test):
mocker.patch('os.path.isfile', return_value=False) mocker.patch('os.path.isfile', return_value=False)
monkeypatch.setenv('EDITOR', 'dummy_editor') monkeypatch.setenv('EDITOR', 'dummy_editor')
assert not match(Command(stdout=test[4], stderr=test[5]), None) assert not match(Command(stdout=test[4], stderr=test[5]))
@pytest.mark.parametrize('test', tests) @pytest.mark.parametrize('test', tests)
@@ -219,16 +234,16 @@ def test_get_new_command(mocker, monkeypatch, test):
@pytest.mark.parametrize('test', tests) @pytest.mark.parametrize('test', tests)
@pytest.mark.usefixtures('no_memoize') @pytest.mark.usefixtures('no_memoize')
def test_get_new_command_with_settings(mocker, monkeypatch, test): def test_get_new_command_with_settings(mocker, monkeypatch, test, settings):
mocker.patch('os.path.isfile', return_value=True) mocker.patch('os.path.isfile', return_value=True)
monkeypatch.setenv('EDITOR', 'dummy_editor') monkeypatch.setenv('EDITOR', 'dummy_editor')
cmd = Command(script=test[0], stdout=test[4], stderr=test[5]) cmd = Command(script=test[0], stdout=test[4], stderr=test[5])
settings = Settings({'fixcolcmd': '{editor} {file} +{line}:{col}'}) settings.fixcolcmd = '{editor} {file} +{line}:{col}'
if test[3]: if test[3]:
assert (get_new_command(cmd, settings) == assert (get_new_command(cmd) ==
'dummy_editor {} +{}:{} && {}'.format(test[1], test[2], test[3], test[0])) u'dummy_editor {} +{}:{} && {}'.format(test[1], test[2], test[3], test[0]))
else: else:
assert (get_new_command(cmd, settings) == assert (get_new_command(cmd) ==
'dummy_editor {} +{} && {}'.format(test[1], test[2], test[0])) u'dummy_editor {} +{} && {}'.format(test[1], test[2], test[0]))

View File

@@ -4,36 +4,28 @@ from tests.utils import Command
@pytest.fixture @pytest.fixture
def did_not_match(target, did_you_forget=True): def stderr(target):
error = ("error: pathspec '{}' did not match any " return ("error: pathspec '{}' did not match any "
"file(s) known to git.".format(target)) 'file(s) known to git.'.format(target))
if did_you_forget:
error = ("{}\nDid you forget to 'git add'?'".format(error))
return error
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('script, target', [
Command(script='git submodule update unknown', ('git submodule update unknown', 'unknown'),
stderr=did_not_match('unknown')), ('git commit unknown', 'unknown')])
Command(script='git commit unknown', def test_match(stderr, script, target):
stderr=did_not_match('unknown'))]) # Older versions of Git assert match(Command(script=script, stderr=stderr))
def test_match(command):
assert match(command, None)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('script', [
Command(script='git submodule update known', stderr=('')), 'git submodule update known', 'git commit known'])
Command(script='git commit known', stderr=('')), def test_not_match(script):
Command(script='git commit unknown', # Newer versions of Git assert not match(Command(script=script, stderr=''))
stderr=did_not_match('unknown', False))])
def test_not_match(command):
assert not match(command, None)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('script, target, new_command', [
(Command('git submodule update unknown', stderr=did_not_match('unknown')), ('git submodule update unknown', 'unknown',
'git add -- unknown && git submodule update unknown'), 'git add -- unknown && git submodule update unknown'),
(Command('git commit unknown', stderr=did_not_match('unknown')), # Old Git ('git commit unknown', 'unknown',
'git add -- unknown && git commit unknown')]) 'git add -- unknown && git commit unknown')])
def test_get_new_command(command, new_command): def test_get_new_command(stderr, script, target, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(Command(script=script, stderr=stderr)) == new_command

View File

@@ -12,11 +12,11 @@ If you are sure you want to delete it, run 'git branch -D branch'.
def test_match(stderr): def test_match(stderr):
assert match(Command('git branch -d branch', stderr=stderr), None) assert match(Command('git branch -d branch', stderr=stderr))
assert not match(Command('git branch -d branch'), None) assert not match(Command('git branch -d branch'))
assert not match(Command('ls', stderr=stderr), None) assert not match(Command('ls', stderr=stderr))
def test_get_new_command(stderr): def test_get_new_command(stderr):
assert get_new_command(Command('git branch -d branch', stderr=stderr), None)\ assert get_new_command(Command('git branch -d branch', stderr=stderr))\
== "git branch -D branch" == "git branch -D branch"

View File

@@ -0,0 +1,33 @@
import pytest
from thefuck.rules.git_branch_exists import match, get_new_command
from tests.utils import Command
@pytest.fixture
def stderr(branch_name):
return "fatal: A branch named '{}' already exists.".format(branch_name)
@pytest.fixture
def new_command(branch_name):
return [cmd.format(branch_name) for cmd in [
'git branch -d {0} && git branch {0}',
'git branch -D {0} && git branch {0}', 'git checkout {0}']]
@pytest.mark.parametrize('script, branch_name', [
('git branch foo', 'foo'),
('git branch bar', 'bar')])
def test_match(stderr, script, branch_name):
assert match(Command(script=script, stderr=stderr))
@pytest.mark.parametrize('script', ['git branch foo', 'git branch bar'])
def test_not_match(script):
assert not match(Command(script=script, stderr=''))
@pytest.mark.parametrize('script, branch_name, ', [
('git branch foo', 'foo'), ('git branch bar', 'bar')])
def test_get_new_command(stderr, new_command, script, branch_name):
assert get_new_command(Command(script=script, stderr=stderr)) == new_command

View File

@@ -1,19 +1,19 @@
from thefuck import shells
from thefuck.rules.git_branch_list import match, get_new_command from thefuck.rules.git_branch_list import match, get_new_command
from thefuck.shells import shell
from tests.utils import Command from tests.utils import Command
def test_match(): def test_match():
assert match(Command('git branch list'), None) assert match(Command('git branch list'))
def test_not_match(): def test_not_match():
assert not match(Command(), None) assert not match(Command())
assert not match(Command('git commit'), None) assert not match(Command('git commit'))
assert not match(Command('git branch'), None) assert not match(Command('git branch'))
assert not match(Command('git stash list'), None) assert not match(Command('git stash list'))
def test_get_new_command(): def test_get_new_command():
assert (get_new_command(Command('git branch list'), None) == assert (get_new_command(Command('git branch list')) ==
shells.and_('git branch --delete list', 'git branch')) shell.and_('git branch --delete list', 'git branch'))

View File

@@ -1,5 +1,6 @@
import pytest import pytest
from thefuck.rules.git_checkout import match, get_new_command from io import BytesIO
from thefuck.rules.git_checkout import match, get_branches, get_new_command
from tests.utils import Command from tests.utils import Command
@@ -13,15 +14,17 @@ def did_not_match(target, did_you_forget=False):
@pytest.fixture @pytest.fixture
def get_branches(mocker): def git_branch(mocker, branches):
return mocker.patch('thefuck.rules.git_checkout.get_branches') mock = mocker.patch('subprocess.Popen')
mock.return_value.stdout = BytesIO(branches)
return mock
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
Command(script='git checkout unknown', stderr=did_not_match('unknown')), Command(script='git checkout unknown', stderr=did_not_match('unknown')),
Command(script='git commit unknown', stderr=did_not_match('unknown'))]) Command(script='git commit unknown', stderr=did_not_match('unknown'))])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
@@ -30,24 +33,37 @@ def test_match(command):
Command(script='git checkout known', stderr=('')), Command(script='git checkout known', stderr=('')),
Command(script='git commit known', stderr=(''))]) Command(script='git commit known', stderr=(''))])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
@pytest.mark.parametrize('branches, branch_list', [
(b'', []),
(b'* master', ['master']),
(b' remotes/origin/master', ['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',
['master', 'master', 'just-another-branch'])])
def test_get_branches(branches, branch_list, git_branch):
git_branch(branches)
assert list(get_branches()) == branch_list
@pytest.mark.parametrize('branches, command, new_command', [ @pytest.mark.parametrize('branches, command, new_command', [
([], (b'',
Command(script='git checkout unknown', stderr=did_not_match('unknown')), Command(script='git checkout unknown', stderr=did_not_match('unknown')),
'git branch unknown && git checkout unknown'), 'git branch unknown && git checkout unknown'),
([], (b'',
Command('git commit unknown', stderr=did_not_match('unknown')), Command('git commit unknown', stderr=did_not_match('unknown')),
'git branch unknown && git commit unknown'), 'git branch unknown && git commit unknown'),
(['test-random-branch-123'], (b' test-random-branch-123',
Command(script='git checkout tst-rdm-brnch-123', Command(script='git checkout tst-rdm-brnch-123',
stderr=did_not_match('tst-rdm-brnch-123')), stderr=did_not_match('tst-rdm-brnch-123')),
'git checkout test-random-branch-123'), 'git checkout test-random-branch-123'),
(['test-random-branch-123'], (b' test-random-branch-123',
Command(script='git commit tst-rdm-brnch-123', Command(script='git commit tst-rdm-brnch-123',
stderr=did_not_match('tst-rdm-brnch-123')), stderr=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, get_branches): def test_get_new_command(branches, command, new_command, git_branch):
get_branches.return_value = branches git_branch(branches)
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -7,7 +7,7 @@ from tests.utils import Command
Command(script='git diff foo'), Command(script='git diff foo'),
Command(script='git diff')]) Command(script='git diff')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
@@ -16,11 +16,11 @@ def test_match(command):
Command(script='git branch'), Command(script='git branch'),
Command(script='git log')]) Command(script='git log')])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
(Command('git diff'), 'git diff --staged'), (Command('git diff'), 'git diff --staged'),
(Command('git diff foo'), 'git diff --staged foo')]) (Command('git diff foo'), 'git diff --staged foo')])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -20,7 +20,11 @@ usage: git stash list [<options>]
'git stash Some message', 'git stash Some message',
'git stash saev Some message']) 'git stash saev Some message'])
def test_match(wrong): def test_match(wrong):
assert match(Command(wrong, stderr=git_stash_err), None) assert match(Command(wrong, stderr=git_stash_err))
def test_not_match():
assert not match(Command("git", stderr=git_stash_err))
@pytest.mark.parametrize('wrong,fixed', [ @pytest.mark.parametrize('wrong,fixed', [
@@ -28,4 +32,4 @@ def test_match(wrong):
('git stash Some message', 'git stash save Some message'), ('git stash Some message', 'git stash save Some message'),
('git stash saev Some message', 'git stash save Some message')]) ('git stash saev Some message', 'git stash save Some message')])
def test_get_new_command(wrong, fixed): def test_get_new_command(wrong, fixed):
assert get_new_command(Command(wrong, stderr=git_stash_err), None) == fixed assert get_new_command(Command(wrong, stderr=git_stash_err)) == fixed

View File

@@ -0,0 +1,24 @@
import pytest
from thefuck.rules.git_help_aliased import match, get_new_command
from tests.utils import Command
@pytest.mark.parametrize('script, stdout', [
('git help st', "`git st' is aliased to `status'"),
('git help ds', "`git ds' is aliased to `diff --staged'")])
def test_match(script, stdout):
assert match(Command(script=script, stdout=stdout))
@pytest.mark.parametrize('script, stdout', [
('git help status', "GIT-STATUS(1)...Git Manual...GIT-STATUS(1)"),
('git help diff', "GIT-DIFF(1)...Git Manual...GIT-DIFF(1)")])
def test_not_match(script, stdout):
assert not match(Command(script=script, stdout=stdout))
@pytest.mark.parametrize('script, stdout, new_command', [
('git help st', "`git st' is aliased to `status'", 'git help status'),
('git help ds', "`git ds' is aliased to `diff --staged'", 'git help diff')])
def test_get_new_command(script, stdout, new_command):
assert get_new_command(Command(script=script, stdout=stdout)) == new_command

View File

@@ -41,17 +41,17 @@ def git_command():
def test_match(git_not_command, git_command, git_not_command_one_of_this): def test_match(git_not_command, git_command, git_not_command_one_of_this):
assert match(Command('git brnch', stderr=git_not_command), None) assert match(Command('git brnch', stderr=git_not_command))
assert match(Command('git st', stderr=git_not_command_one_of_this), None) assert match(Command('git st', stderr=git_not_command_one_of_this))
assert not match(Command('ls brnch', stderr=git_not_command), None) assert not match(Command('ls brnch', stderr=git_not_command))
assert not match(Command('git branch', stderr=git_command), None) assert not match(Command('git branch', stderr=git_command))
def test_get_new_command(git_not_command, git_not_command_one_of_this, def test_get_new_command(git_not_command, git_not_command_one_of_this,
git_not_command_closest): git_not_command_closest):
assert get_new_command(Command('git brnch', stderr=git_not_command), None) \ assert get_new_command(Command('git brnch', stderr=git_not_command)) \
== ['git branch'] == ['git branch']
assert get_new_command(Command('git st', stderr=git_not_command_one_of_this), assert get_new_command(Command('git st', stderr=git_not_command_one_of_this)) \
None) == ['git stats', 'git stash', 'git stage'] == ['git stats', 'git stash', 'git stage']
assert get_new_command(Command('git tags', stderr=git_not_command_closest), assert get_new_command(Command('git tags', stderr=git_not_command_closest)) \
None) == ['git tag', 'git stage'] == ['git tag', 'git stage']

View File

@@ -19,11 +19,11 @@ If you wish to set tracking information for this branch you can do so with:
def test_match(stderr): def test_match(stderr):
assert match(Command('git pull', stderr=stderr), None) assert match(Command('git pull', stderr=stderr))
assert not match(Command('git pull'), None) assert not match(Command('git pull'))
assert not match(Command('ls', stderr=stderr), None) assert not match(Command('ls', stderr=stderr))
def test_get_new_command(stderr): def test_get_new_command(stderr):
assert get_new_command(Command('git pull', stderr=stderr), None) \ assert get_new_command(Command('git pull', stderr=stderr)) \
== "git branch --set-upstream-to=origin/master master && git pull" == "git branch --set-upstream-to=origin/master master && git pull"

View File

@@ -12,10 +12,10 @@ Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
Command(script='git pull git@github.com:mcarton/thefuck.git', stderr=git_err)]) Command(script='git pull git@github.com:mcarton/thefuck.git', stderr=git_err)])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command, output', [ @pytest.mark.parametrize('command, output', [
(Command(script='git pull git@github.com:mcarton/thefuck.git', stderr=git_err), 'git clone git@github.com:mcarton/thefuck.git')]) (Command(script='git pull git@github.com:mcarton/thefuck.git', stderr=git_err), 'git clone git@github.com:mcarton/thefuck.git')])
def test_get_new_command(command, output): def test_get_new_command(command, output):
assert get_new_command(command, None) == output assert get_new_command(command) == output

View File

@@ -14,11 +14,11 @@ To push the current branch and set the remote as upstream, use
def test_match(stderr): def test_match(stderr):
assert match(Command('git push master', stderr=stderr), None) assert match(Command('git push master', stderr=stderr))
assert not match(Command('git push master'), None) assert not match(Command('git push master'))
assert not match(Command('ls', stderr=stderr), None) assert not match(Command('ls', stderr=stderr))
def test_get_new_command(stderr): def test_get_new_command(stderr):
assert get_new_command(Command('git push', stderr=stderr), None)\ assert get_new_command(Command('git push', stderr=stderr))\
== "git push --set-upstream origin master" == "git push --set-upstream origin master"

View File

@@ -30,7 +30,7 @@ To /tmp/bar
Command(script='git push nvbn', stderr=git_err), Command(script='git push nvbn', stderr=git_err),
Command(script='git push nvbn master', stderr=git_err)]) Command(script='git push nvbn master', stderr=git_err)])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
@@ -41,12 +41,12 @@ def test_match(command):
Command(script='git push nvbn', stderr=git_ok), Command(script='git push nvbn', stderr=git_ok),
Command(script='git push nvbn master', stderr=git_uptodate)]) Command(script='git push nvbn master', stderr=git_uptodate)])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
@pytest.mark.parametrize('command, output', [ @pytest.mark.parametrize('command, output', [
(Command(script='git push', stderr=git_err), 'git push --force'), (Command(script='git push', stderr=git_err), 'git push --force-with-lease'),
(Command(script='git push nvbn', stderr=git_err), 'git push --force nvbn'), (Command(script='git push nvbn', stderr=git_err), 'git push --force-with-lease nvbn'),
(Command(script='git push nvbn master', stderr=git_err), 'git push --force nvbn master')]) (Command(script='git push nvbn master', stderr=git_err), 'git push --force-with-lease nvbn master')])
def test_get_new_command(command, output): def test_get_new_command(command, output):
assert get_new_command(command, None) == output assert get_new_command(command) == output

View File

@@ -30,7 +30,7 @@ To /tmp/bar
Command(script='git push nvbn', stderr=git_err), Command(script='git push nvbn', stderr=git_err),
Command(script='git push nvbn master', stderr=git_err)]) Command(script='git push nvbn master', stderr=git_err)])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
@@ -41,7 +41,7 @@ def test_match(command):
Command(script='git push nvbn', stderr=git_ok), Command(script='git push nvbn', stderr=git_ok),
Command(script='git push nvbn master', stderr=git_uptodate)]) Command(script='git push nvbn master', stderr=git_uptodate)])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
@pytest.mark.parametrize('command, output', [ @pytest.mark.parametrize('command, output', [
@@ -51,4 +51,4 @@ def test_not_match(command):
(Command(script='git push nvbn master', stderr=git_err), (Command(script='git push nvbn master', stderr=git_err),
'git pull nvbn master && git push nvbn master')]) 'git pull nvbn master && git push nvbn master')])
def test_get_new_command(command, output): def test_get_new_command(command, output):
assert get_new_command(command, None) == output assert get_new_command(command) == output

View File

@@ -0,0 +1,26 @@
import pytest
from thefuck.rules.git_remote_seturl_add import match, get_new_command
from tests.utils import Command
@pytest.mark.parametrize('command', [
Command(script='git remote set-url origin url', stderr="fatal: No such remote")])
def test_match(command):
assert match(command)
@pytest.mark.parametrize('command', [
Command('git remote set-url origin url', stderr=""),
Command('git remote add origin url'),
Command('git remote remove origin'),
Command('git remote prune origin'),
Command('git remote set-branches origin branch')
])
def test_not_match(command):
assert not match(command)
@pytest.mark.parametrize('command, new_command', [
(Command('git remote set-url origin git@github.com:nvbn/thefuck.git'),
'git remote add origin git@github.com:nvbn/thefuck.git')])
def test_get_new_command(command, new_command):
assert get_new_command(command) == new_command

View File

@@ -0,0 +1,27 @@
import pytest
from thefuck.rules.git_rm_recursive import match, get_new_command
from tests.utils import Command
@pytest.fixture
def stderr(target):
return "fatal: not removing '{}' recursively without -r".format(target)
@pytest.mark.parametrize('script, target', [
('git rm foo', 'foo'),
('git rm foo bar', 'foo bar')])
def test_match(stderr, script, target):
assert match(Command(script=script, stderr=stderr))
@pytest.mark.parametrize('script', ['git rm foo', 'git rm foo bar'])
def test_not_match(script):
assert not match(Command(script=script, stderr=''))
@pytest.mark.parametrize('script, target, new_command', [
('git rm foo', 'foo', 'git rm -r foo'),
('git rm foo bar', 'foo bar', 'git rm -r foo bar')])
def test_get_new_command(stderr, script, target, new_command):
assert get_new_command(Command(script=script, stderr=stderr)) == new_command

View File

@@ -18,14 +18,14 @@ rebase_error = (
Command(script='git cherry-pick a1b2c3d', stderr=cherry_pick_error), Command(script='git cherry-pick a1b2c3d', stderr=cherry_pick_error),
Command(script='git rebase -i HEAD~7', stderr=rebase_error)]) Command(script='git rebase -i HEAD~7', stderr=rebase_error)])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
Command(script='git cherry-pick a1b2c3d', stderr=('')), Command(script='git cherry-pick a1b2c3d', stderr=('')),
Command(script='git rebase -i HEAD~7', stderr=(''))]) Command(script='git rebase -i HEAD~7', stderr=(''))])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
@@ -34,4 +34,4 @@ def test_not_match(command):
(Command('git rebase -i HEAD~7', stderr=rebase_error), (Command('git rebase -i HEAD~7', stderr=rebase_error),
'git stash && git rebase -i HEAD~7')]) 'git stash && git rebase -i HEAD~7')])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -0,0 +1,47 @@
import pytest
from thefuck.rules.git_two_dashes import match, get_new_command
from tests.utils import Command
@pytest.fixture
def stderr(meant):
return 'error: did you mean `%s` (with two dashes ?)' % meant
@pytest.mark.parametrize('command', [
Command(script='git add -patch', stderr=stderr('--patch')),
Command(script='git checkout -patch', stderr=stderr('--patch')),
Command(script='git commit -amend', stderr=stderr('--amend')),
Command(script='git push -tags', stderr=stderr('--tags')),
Command(script='git rebase -continue', stderr=stderr('--continue'))])
def test_match(command):
assert match(command)
@pytest.mark.parametrize('command', [
Command(script='git add --patch'),
Command(script='git checkout --patch'),
Command(script='git commit --amend'),
Command(script='git push --tags'),
Command(script='git rebase --continue')])
def test_not_match(command):
assert not match(command)
@pytest.mark.parametrize('command, output', [
(Command(script='git add -patch', stderr=stderr('--patch')),
'git add --patch'),
(Command(script='git checkout -patch', stderr=stderr('--patch')),
'git checkout --patch'),
(Command(script='git checkout -patch', stderr=stderr('--patch')),
'git checkout --patch'),
(Command(script='git init -bare', stderr=stderr('--bare')),
'git init --bare'),
(Command(script='git commit -amend', stderr=stderr('--amend')),
'git commit --amend'),
(Command(script='git push -tags', stderr=stderr('--tags')),
'git push --tags'),
(Command(script='git rebase -continue', stderr=stderr('--continue')),
'git rebase --continue')])
def test_get_new_command(command, output):
assert get_new_command(command) == output

View File

@@ -7,11 +7,11 @@ from tests.utils import Command
Command(script='go run foo'), Command(script='go run foo'),
Command(script='go run bar')]) Command(script='go run bar')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
(Command('go run foo'), 'go run foo.go'), (Command('go run foo'), 'go run foo.go'),
(Command('go run bar'), 'go run bar.go')]) (Command('go run bar'), 'go run bar.go')])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -0,0 +1,40 @@
import pytest
from thefuck.rules.grep_arguments_order import get_new_command, match
from tests.utils import Command
stderr = 'grep: {}: No such file or directory'.format
@pytest.fixture(autouse=True)
def os_path(monkeypatch):
monkeypatch.setattr('os.path.isfile', lambda x: not x.startswith('-'))
@pytest.mark.parametrize('script, file', [
('grep test.py test', 'test'),
('grep -lir . test', 'test'),
('egrep test.py test', 'test'),
('egrep -lir . test', 'test')])
def test_match(script, file):
assert match(Command(script, stderr=stderr(file)))
@pytest.mark.parametrize('script, stderr', [
('cat test.py', stderr('test')),
('grep test test.py', ''),
('grep -lir test .', ''),
('egrep test test.py', ''),
('egrep -lir test .', '')])
def test_not_match(script, stderr):
assert not match(Command(script, stderr=stderr))
@pytest.mark.parametrize('script, stderr, result', [
('grep test.py test', stderr('test'), 'grep test test.py'),
('grep -lir . test', stderr('test'), 'grep -lir test .'),
('grep . test -lir', stderr('test'), 'grep test -lir .'),
('egrep test.py test', stderr('test'), 'egrep test test.py'),
('egrep -lir . test', stderr('test'), 'egrep -lir test .'),
('egrep . test -lir', stderr('test'), 'egrep test -lir .')])
def test_get_new_command(script, stderr, result):
assert get_new_command(Command(script, stderr=stderr)) == result

View File

@@ -1,12 +1,15 @@
# -*- coding: utf-8 -*-
from thefuck.rules.grep_recursive import match, get_new_command from thefuck.rules.grep_recursive import match, get_new_command
from tests.utils import Command from tests.utils import Command
def test_match(): def test_match():
assert match(Command('grep blah .', stderr='grep: .: Is a directory'), None) assert match(Command('grep blah .', stderr='grep: .: Is a directory'))
assert not match(Command(), None) assert match(Command(u'grep café .', stderr='grep: .: Is a directory'))
assert not match(Command())
def test_get_new_command(): def test_get_new_command():
assert get_new_command( assert get_new_command(Command('grep blah .')) == 'grep -r blah .'
Command('grep blah .'), None) == 'grep -r blah .' assert get_new_command(Command(u'grep café .')) == u'grep -r café .'

View File

@@ -1,4 +1,5 @@
import pytest import pytest
from io import BytesIO
from tests.utils import Command from tests.utils import Command
from thefuck.rules.gulp_not_task import match, get_new_command from thefuck.rules.gulp_not_task import match, get_new_command
@@ -11,18 +12,18 @@ def stdout(task):
def test_match(): def test_match():
assert match(Command('gulp srve', stdout('srve')), None) assert match(Command('gulp srve', stdout('srve')))
@pytest.mark.parametrize('script, stdout', [ @pytest.mark.parametrize('script, stdout', [
('gulp serve', ''), ('gulp serve', ''),
('cat srve', stdout('srve'))]) ('cat srve', stdout('srve'))])
def test_not_march(script, stdout): def test_not_march(script, stdout):
assert not match(Command(script, stdout), None) assert not match(Command(script, stdout))
def test_get_new_command(mocker): def test_get_new_command(mocker):
mocker.patch('thefuck.rules.gulp_not_task.get_gulp_tasks', return_value=[ mock = mocker.patch('subprocess.Popen')
'serve', 'build', 'default']) mock.return_value.stdout = BytesIO(b'serve \nbuild \ndefault \n')
command = Command('gulp srve', stdout('srve')) command = Command('gulp srve', stdout('srve'))
assert get_new_command(command, None) == ['gulp serve', 'gulp default'] assert get_new_command(command) == ['gulp serve', 'gulp default']

View File

@@ -1,20 +1,18 @@
from mock import Mock, patch from mock import patch
from thefuck.rules.has_exists_script import match, get_new_command from thefuck.rules.has_exists_script import match, get_new_command
from ..utils import Command
def test_match(): def test_match():
with patch('os.path.exists', return_value=True): with patch('os.path.exists', return_value=True):
assert match(Mock(script='main', stderr='main: command not found'), assert match(Command(script='main', stderr='main: command not found'))
None) assert match(Command(script='main --help',
assert match(Mock(script='main --help', stderr='main: command not found'))
stderr='main: command not found'), assert not match(Command(script='main', stderr=''))
None)
assert not match(Mock(script='main', stderr=''), None)
with patch('os.path.exists', return_value=False): with patch('os.path.exists', return_value=False):
assert not match(Mock(script='main', stderr='main: command not found'), assert not match(Command(script='main', stderr='main: command not found'))
None)
def test_get_new_command(): def test_get_new_command():
assert get_new_command(Mock(script='main --help'), None) == './main --help' assert get_new_command(Command(script='main --help')) == './main --help'

View File

@@ -16,14 +16,14 @@ no_suggest_stderr = ''' ! `aaaaa` is not a heroku command.
@pytest.mark.parametrize('cmd', ['log', 'pge']) @pytest.mark.parametrize('cmd', ['log', 'pge'])
def test_match(cmd): def test_match(cmd):
assert match( assert match(
Command('heroku {}'.format(cmd), stderr=suggest_stderr(cmd)), None) Command('heroku {}'.format(cmd), stderr=suggest_stderr(cmd)))
@pytest.mark.parametrize('script, stderr', [ @pytest.mark.parametrize('script, stderr', [
('cat log', suggest_stderr('log')), ('cat log', suggest_stderr('log')),
('heroku aaa', no_suggest_stderr)]) ('heroku aaa', no_suggest_stderr)])
def test_not_match(script, stderr): def test_not_match(script, stderr):
assert not match(Command(script, stderr=stderr), None) assert not match(Command(script, stderr=stderr))
@pytest.mark.parametrize('cmd, result', [ @pytest.mark.parametrize('cmd, result', [
@@ -31,4 +31,4 @@ def test_not_match(script, stderr):
('pge', ['heroku pg', 'heroku logs'])]) ('pge', ['heroku pg', 'heroku logs'])])
def test_get_new_command(cmd, result): def test_get_new_command(cmd, result):
command = Command('heroku {}'.format(cmd), stderr=suggest_stderr(cmd)) command = Command('heroku {}'.format(cmd), stderr=suggest_stderr(cmd))
assert get_new_command(command, None) == result assert get_new_command(command) == result

View File

@@ -3,40 +3,25 @@ from thefuck.rules.history import match, get_new_command
from tests.utils import Command from tests.utils import Command
@pytest.fixture @pytest.fixture(autouse=True)
def history(mocker): def history_without_current(mocker):
return mocker.patch('thefuck.rules.history.get_history', return mocker.patch(
return_value=['le cat', 'fuck', 'ls cat', 'thefuck.rules.history.get_valid_history_without_current',
'diff x', 'nocommand x']) return_value=['ls cat', 'diff x'])
@pytest.fixture
def alias(mocker):
return mocker.patch('thefuck.rules.history.thefuck_alias',
return_value='fuck')
@pytest.fixture
def callables(mocker):
return mocker.patch('thefuck.rules.history.get_all_executables',
return_value=['diff', 'ls'])
@pytest.mark.usefixtures('history', 'callables', 'no_memoize', 'alias')
@pytest.mark.parametrize('script', ['ls cet', 'daff x']) @pytest.mark.parametrize('script', ['ls cet', 'daff x'])
def test_match(script): def test_match(script):
assert match(Command(script=script), None) assert match(Command(script=script))
@pytest.mark.usefixtures('history', 'callables', 'no_memoize', 'alias')
@pytest.mark.parametrize('script', ['apt-get', 'nocommand y']) @pytest.mark.parametrize('script', ['apt-get', 'nocommand y'])
def test_not_match(script): def test_not_match(script):
assert not match(Command(script=script), None) assert not match(Command(script=script))
@pytest.mark.usefixtures('history', 'callables', 'no_memoize', 'alias')
@pytest.mark.parametrize('script, result', [ @pytest.mark.parametrize('script, result', [
('ls cet', 'ls cat'), ('ls cet', 'ls cat'),
('daff x', 'diff x')]) ('daff x', 'diff x')])
def test_get_new_command(script, result): def test_get_new_command(script, result):
assert get_new_command(Command(script), None) == result assert get_new_command(Command(script)) == result

View File

@@ -7,11 +7,11 @@ from tests.utils import Command
Command(script='java foo.java'), Command(script='java foo.java'),
Command(script='java bar.java')]) Command(script='java bar.java')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
(Command('java foo.java'), 'java foo'), (Command('java foo.java'), 'java foo'),
(Command('java bar.java'), 'java bar')]) (Command('java bar.java'), 'java bar')])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -7,11 +7,11 @@ from tests.utils import Command
Command(script='javac foo'), Command(script='javac foo'),
Command(script='javac bar')]) Command(script='javac bar')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
(Command('javac foo'), 'javac foo.java'), (Command('javac foo'), 'javac foo.java'),
(Command('javac bar'), 'javac bar.java')]) (Command('javac bar'), 'javac bar.java')])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -14,10 +14,10 @@ Did you mean this?
def test_match(is_not_task): def test_match(is_not_task):
assert match(Command(script='lein rpl', stderr=is_not_task), None) assert match(Command(script='lein rpl', stderr=is_not_task))
assert not match(Command(script='ls', stderr=is_not_task), None) assert not match(Command(script='ls', stderr=is_not_task))
def test_get_new_command(is_not_task): def test_get_new_command(is_not_task):
assert get_new_command(Command(script='lein rpl --help', stderr=is_not_task), assert get_new_command(Command(script='lein rpl --help', stderr=is_not_task)) \
None) == ['lein repl --help', 'lein jar --help'] == ['lein repl --help', 'lein jar --help']

View File

@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
import pytest
from thefuck.rules.ln_no_hard_link import match, get_new_command
from tests.utils import Command
error = "hard link not allowed for directory"
@pytest.mark.parametrize('script, stderr', [
("ln barDir barLink", "ln: barDir: {}"),
("sudo ln a b", "ln: a: {}"),
("sudo ln -nbi a b", "ln: a: {}")])
def test_match(script, stderr):
command = Command(script, stderr=stderr.format(error))
assert match(command)
@pytest.mark.parametrize('script, stderr', [
('', ''),
("ln a b", "... hard link"),
("sudo ln a b", "... hard link"),
("a b", error)])
def test_assert_not_match(script, stderr):
command = Command(script, stderr=stderr)
assert not match(command)
@pytest.mark.parametrize('script, result', [
("ln barDir barLink", "ln -s barDir barLink"),
("sudo ln barDir barLink", "sudo ln -s barDir barLink"),
("sudo ln -nbi a b", "sudo ln -s -nbi a b"),
("ln -nbi a b && ls", "ln -s -nbi a b && ls"),
("ln a ln", "ln -s a ln"),
("sudo ln a ln", "sudo ln -s a ln")])
def test_get_new_command(script, result):
command = Command(script)
assert get_new_command(command) == result

View File

@@ -3,14 +3,14 @@ from tests.utils import Command
def test_match(): def test_match():
assert match(Command(script='ls'), None) assert match(Command(script='ls'))
assert match(Command(script='ls file.py'), None) assert match(Command(script='ls file.py'))
assert match(Command(script='ls /opt'), None) assert match(Command(script='ls /opt'))
assert not match(Command(script='ls -lah /opt'), None) assert not match(Command(script='ls -lah /opt'))
assert not match(Command(script='pacman -S binutils'), None) assert not match(Command(script='pacman -S binutils'))
assert not match(Command(script='lsof'), None) assert not match(Command(script='lsof'))
def test_get_new_command(): def test_get_new_command():
assert get_new_command(Command(script='ls file.py'), None) == 'ls -lah file.py' assert get_new_command(Command(script='ls file.py')) == 'ls -lah file.py'
assert get_new_command(Command(script='ls'), None) == 'ls -lah' assert get_new_command(Command(script='ls')) == 'ls -lah'

View File

@@ -12,14 +12,14 @@ from tests.utils import Command
Command('man -s 2 read'), Command('man -s 2 read'),
Command('man -s 3 read')]) Command('man -s 3 read')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
Command('man'), Command('man'),
Command('man ')]) Command('man ')])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
@@ -31,4 +31,4 @@ def test_not_match(command):
(Command('man -s 2 read'), 'man -s 3 read'), (Command('man -s 2 read'), 'man -s 3 read'),
(Command('man -s 3 read'), 'man -s 2 read')]) (Command('man -s 3 read'), 'man -s 2 read')])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -3,10 +3,10 @@ from tests.utils import Command
def test_match(): def test_match():
assert match(Command('mandiff', stderr='mandiff: command not found'), None) assert match(Command('mandiff', stderr='mandiff: command not found'))
assert not match(Command(), None) assert not match(Command())
def test_get_new_command(): def test_get_new_command():
assert get_new_command( assert get_new_command(
Command('mandiff'), None) == 'man diff' Command('mandiff')) == 'man diff'

View File

@@ -37,7 +37,7 @@ from thefuck.rules.mercurial import (
)), )),
]) ])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
@@ -63,7 +63,7 @@ def test_match(command):
)), )),
]) ])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
@pytest.mark.parametrize('command, possibilities', [ @pytest.mark.parametrize('command, possibilities', [
@@ -131,4 +131,4 @@ def test_extract_possibilities(command, possibilities):
)), 'hg rebase re'), )), 'hg rebase re'),
]) ])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -7,9 +7,9 @@ from tests.utils import Command
Command('mkdir foo/bar/baz', stderr='mkdir: foo/bar: No such file or directory'), Command('mkdir foo/bar/baz', stderr='mkdir: foo/bar: No such file or directory'),
Command('./bin/hdfs dfs -mkdir foo/bar/baz', stderr='mkdir: `foo/bar/baz\': No such file or directory'), Command('./bin/hdfs dfs -mkdir foo/bar/baz', stderr='mkdir: `foo/bar/baz\': No such file or directory'),
Command('hdfs dfs -mkdir foo/bar/baz', stderr='mkdir: `foo/bar/baz\': No such file or directory') Command('hdfs dfs -mkdir foo/bar/baz', stderr='mkdir: `foo/bar/baz\': No such file or directory')
]) ])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
@@ -17,15 +17,16 @@ def test_match(command):
Command('mkdir foo/bar/baz', stderr='foo bar baz'), Command('mkdir foo/bar/baz', stderr='foo bar baz'),
Command('hdfs dfs -mkdir foo/bar/baz'), Command('hdfs dfs -mkdir foo/bar/baz'),
Command('./bin/hdfs dfs -mkdir foo/bar/baz'), Command('./bin/hdfs dfs -mkdir foo/bar/baz'),
Command()]) Command(),
])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
(Command('mkdir foo/bar/baz'), 'mkdir -p foo/bar/baz'), (Command('mkdir foo/bar/baz'), 'mkdir -p foo/bar/baz'),
(Command('hdfs dfs -mkdir foo/bar/baz'), 'hdfs dfs -mkdir -p foo/bar/baz'), (Command('hdfs dfs -mkdir foo/bar/baz'), 'hdfs dfs -mkdir -p foo/bar/baz'),
(Command('./bin/hdfs dfs -mkdir foo/bar/baz'), './bin/hdfs dfs -mkdir -p foo/bar/baz')]) (Command('./bin/hdfs dfs -mkdir foo/bar/baz'), './bin/hdfs dfs -mkdir -p foo/bar/baz'),
])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -6,7 +6,7 @@ from tests.utils import Command
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
Command(script='mvn', stdout='[ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]')]) Command(script='mvn', stdout='[ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
@@ -30,11 +30,11 @@ def test_match(command):
Command(script='mvn -v') Command(script='mvn -v')
]) ])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
(Command(script='mvn', stdout='[ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]'), ['mvn clean package', 'mvn clean install']), (Command(script='mvn', stdout='[ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]'), ['mvn clean package', 'mvn clean install']),
(Command(script='mvn -N', stdout='[ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]'), ['mvn -N clean package', 'mvn -N clean install'])]) (Command(script='mvn -N', stdout='[ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]'), ['mvn -N clean package', 'mvn -N clean install'])])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -6,7 +6,7 @@ from tests.utils import Command
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
Command(script='mvn cle', stdout='[ERROR] Unknown lifecycle phase "cle". You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]')]) Command(script='mvn cle', stdout='[ERROR] Unknown lifecycle phase "cle". You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
@@ -30,11 +30,11 @@ def test_match(command):
Command(script='mvn -v') Command(script='mvn -v')
]) ])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
(Command(script='mvn cle', stdout='[ERROR] Unknown lifecycle phase "cle". You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]'), ['mvn clean', 'mvn compile']), (Command(script='mvn cle', stdout='[ERROR] Unknown lifecycle phase "cle". You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]'), ['mvn clean', 'mvn compile']),
(Command(script='mvn claen package', stdout='[ERROR] Unknown lifecycle phase "claen". You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]'), ['mvn clean package'])]) (Command(script='mvn claen package', stdout='[ERROR] Unknown lifecycle phase "claen". You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]'), ['mvn clean package'])])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -6,24 +6,37 @@ from tests.utils import Command
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def get_all_executables(mocker): def get_all_executables(mocker):
mocker.patch('thefuck.rules.no_command.get_all_executables', mocker.patch('thefuck.rules.no_command.get_all_executables',
return_value=['vim', 'apt-get', 'fsck']) return_value=['vim', 'fsck', 'git', 'go'])
@pytest.fixture(autouse=True)
def history_without_current(mocker):
return mocker.patch(
'thefuck.rules.no_command.get_valid_history_without_current',
return_value=['git commit'])
@pytest.mark.usefixtures('no_memoize') @pytest.mark.usefixtures('no_memoize')
def test_match(): @pytest.mark.parametrize('script, stderr', [
assert match(Command(stderr='vom: not found', script='vom file.py'), None) ('vom file.py', 'vom: not found'),
assert match(Command(stderr='fucck: not found', script='fucck'), None) ('fucck', 'fucck: not found'),
assert not match(Command(stderr='qweqwe: not found', script='qweqwe'), None) ('got commit', 'got: command not found')])
assert not match(Command(stderr='some text', script='vom file.py'), None) def test_match(script, stderr):
assert match(Command(script, stderr=stderr))
@pytest.mark.usefixtures('no_memoize') @pytest.mark.usefixtures('no_memoize')
def test_get_new_command(): @pytest.mark.parametrize('script, stderr', [
assert get_new_command( ('qweqwe', 'qweqwe: not found'),
Command(stderr='vom: not found', ('vom file.py', 'some text')])
script='vom file.py'), def test_not_match(script, stderr):
None) == ['vim file.py'] assert not match(Command(script, stderr=stderr))
assert get_new_command(
Command(stderr='fucck: not found',
script='fucck'), @pytest.mark.usefixtures('no_memoize')
Command) == ['fsck'] @pytest.mark.parametrize('script, result', [
('vom file.py', ['vim file.py']),
('fucck', ['fsck']),
('got commit', ['git commit', 'go commit'])])
def test_get_new_command(script, result):
assert get_new_command(Command(script)) == result

View File

@@ -6,22 +6,22 @@ from tests.utils import Command
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
Command(script='mv foo bar/foo', stderr="mv: cannot move 'foo' to 'bar/foo': No such file or directory"), Command(script='mv foo bar/foo', stderr="mv: cannot move 'foo' to 'bar/foo': No such file or directory"),
Command(script='mv foo bar/', stderr="mv: cannot move 'foo' to 'bar/': No such file or directory"), Command(script='mv foo bar/', stderr="mv: cannot move 'foo' to 'bar/': No such file or directory"),
]) ])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
Command(script='mv foo bar/', stderr=""), Command(script='mv foo bar/', stderr=""),
Command(script='mv foo bar/foo', stderr="mv: permission denied"), Command(script='mv foo bar/foo', stderr="mv: permission denied"),
]) ])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
(Command(script='mv foo bar/foo', stderr="mv: cannot move 'foo' to 'bar/foo': No such file or directory"), 'mkdir -p bar && mv foo bar/foo'), (Command(script='mv foo bar/foo', stderr="mv: cannot move 'foo' to 'bar/foo': No such file or directory"), 'mkdir -p bar && mv foo bar/foo'),
(Command(script='mv foo bar/', stderr="mv: cannot move 'foo' to 'bar/': No such file or directory"), 'mkdir -p bar && mv foo bar/'), (Command(script='mv foo bar/', stderr="mv: cannot move 'foo' to 'bar/': No such file or directory"), 'mkdir -p bar && mv foo bar/'),
]) ])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -0,0 +1,58 @@
import pytest
from thefuck.rules.npm_wrong_command import match, get_new_command
from tests.utils import Command
stdout = '''
Usage: npm <command>
where <command> is one of:
access, add-user, adduser, apihelp, author, bin, bugs, c,
cache, completion, config, ddp, dedupe, deprecate, dist-tag,
dist-tags, docs, edit, explore, faq, find, find-dupes, get,
help, help-search, home, i, info, init, install, issues, la,
link, list, ll, ln, login, logout, ls, outdated, owner,
pack, ping, prefix, prune, publish, r, rb, rebuild, remove,
repo, restart, rm, root, run-script, s, se, search, set,
show, shrinkwrap, star, stars, start, stop, t, tag, team,
test, tst, un, uninstall, unlink, unpublish, unstar, up,
update, upgrade, v, verison, version, view, whoami
npm <cmd> -h quick help on <cmd>
npm -l display full usage info
npm faq commonly asked questions
npm help <term> search for help on <term>
npm help npm involved overview
Specify configs in the ini-formatted file:
/home/nvbn/.npmrc
or on the command line via: npm <command> --key value
Config info can be viewed via: npm help config
npm@2.14.7 /opt/node/lib/node_modules/npm
'''
@pytest.mark.parametrize('script', [
'npm urgrdae',
'npm urgrade -g',
'npm -f urgrade -g',
'npm urg'])
def test_match(script):
assert match(Command(script, stdout))
@pytest.mark.parametrize('script, stdout', [
('npm urgrade', ''),
('npm', stdout),
('test urgrade', stdout),
('npm -e', stdout)])
def test_not_match(script, stdout):
assert not match(Command(script, stdout))
@pytest.mark.parametrize('script, result', [
('npm urgrade', 'npm upgrade'),
('npm -g isntall gulp', 'npm -g install gulp'),
('npm isntall -g gulp', 'npm install -g gulp')])
def test_get_new_command(script, result):
assert get_new_command(Command(script, stdout)) == result

View File

@@ -14,7 +14,7 @@ from tests.utils import Command
Command(script='gnome-open foo.com'), Command(script='gnome-open foo.com'),
Command(script='kde-open foo.com')]) Command(script='kde-open foo.com')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
@@ -28,4 +28,4 @@ def test_match(command):
(Command('gnome-open foo.io'), 'gnome-open http://foo.io'), (Command('gnome-open foo.io'), 'gnome-open http://foo.io'),
(Command('kde-open foo.io'), 'kde-open http://foo.io')]) (Command('kde-open foo.io'), 'kde-open http://foo.io')])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -23,7 +23,7 @@ extra/vim-python3 7.4.712-1 \t/usr/bin/vim'''
Command(script='vim', stderr='vim: command not found'), Command(script='vim', stderr='vim: command not found'),
Command(script='sudo vim', stderr='sudo: vim: command not found')]) Command(script='sudo vim', stderr='sudo: vim: command not found')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command, return_value', [ @pytest.mark.parametrize('command, return_value', [
@@ -33,14 +33,14 @@ def test_match(command):
@patch.multiple(pacman, create=True, pacman=pacman_cmd) @patch.multiple(pacman, create=True, pacman=pacman_cmd)
def test_match_mocked(subp_mock, command, return_value): def test_match_mocked(subp_mock, command, return_value):
subp_mock.check_output.return_value = return_value subp_mock.check_output.return_value = return_value
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
Command(script='vim', stderr=''), Command(), Command(script='vim', stderr=''), Command(),
Command(script='sudo vim', stderr=''), Command()]) Command(script='sudo vim', stderr=''), Command()])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
sudo_vim_possibilities = ['{} -S extra/gvim && sudo vim', sudo_vim_possibilities = ['{} -S extra/gvim && sudo vim',
@@ -66,7 +66,7 @@ vim_possibilities = [s.format(pacman_cmd) for s in vim_possibilities]
(Command('convert'), ['{} -S extra/imagemagick && convert'.format(pacman_cmd)]), (Command('convert'), ['{} -S extra/imagemagick && convert'.format(pacman_cmd)]),
(Command('sudo convert'), ['{} -S extra/imagemagick && sudo convert'.format(pacman_cmd)])]) (Command('sudo convert'), ['{} -S extra/imagemagick && sudo convert'.format(pacman_cmd)])])
def test_get_new_command(command, new_command, mocker): def test_get_new_command(command, new_command, mocker):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command
@pytest.mark.parametrize('command, new_command, return_value', [ @pytest.mark.parametrize('command, new_command, return_value', [
@@ -79,4 +79,4 @@ def test_get_new_command(command, new_command, mocker):
@patch.multiple(pacman, create=True, pacman=pacman_cmd) @patch.multiple(pacman, create=True, pacman=pacman_cmd)
def test_get_new_command_mocked(subp_mock, command, new_command, return_value): def test_get_new_command_mocked(subp_mock, command, new_command, return_value):
subp_mock.check_output.return_value = return_value subp_mock.check_output.return_value = return_value
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -15,7 +15,7 @@ extra/llvm35 3.5.2-13/usr/bin/llc'''
Command(script='pacman llc', stderr='error: target not found: llc'), Command(script='pacman llc', stderr='error: target not found: llc'),
Command(script='sudo pacman llc', stderr='error: target not found: llc')]) Command(script='sudo pacman llc', stderr='error: target not found: llc')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
@@ -25,7 +25,7 @@ def test_match(command):
@patch('thefuck.specific.archlinux.subprocess') @patch('thefuck.specific.archlinux.subprocess')
def test_match_mocked(subp_mock, command): def test_match_mocked(subp_mock, command):
subp_mock.check_output.return_value = PKGFILE_OUTPUT_LLC subp_mock.check_output.return_value = PKGFILE_OUTPUT_LLC
assert match(command, None) assert match(command)
@pytest.mark.skipif(not getattr(pacman_not_found, 'enabled_by_default', True), @pytest.mark.skipif(not getattr(pacman_not_found, 'enabled_by_default', True),
@@ -35,7 +35,7 @@ def test_match_mocked(subp_mock, command):
(Command(script='pacman -S llc', stderr='error: target not found: llc'), ['pacman -S extra/llvm', 'pacman -S extra/llvm35']), (Command(script='pacman -S llc', stderr='error: target not found: llc'), ['pacman -S extra/llvm', 'pacman -S extra/llvm35']),
(Command(script='sudo pacman -S llc', stderr='error: target not found: llc'), ['sudo pacman -S extra/llvm', 'sudo pacman -S extra/llvm35'])]) (Command(script='sudo pacman -S llc', stderr='error: target not found: llc'), ['sudo pacman -S extra/llvm', 'sudo pacman -S extra/llvm35'])])
def test_get_new_command(command, fixed): def test_get_new_command(command, fixed):
assert get_new_command(command, None) == fixed assert get_new_command(command) == fixed
@pytest.mark.parametrize('command, fixed', [ @pytest.mark.parametrize('command, fixed', [
@@ -45,4 +45,4 @@ def test_get_new_command(command, fixed):
@patch('thefuck.specific.archlinux.subprocess') @patch('thefuck.specific.archlinux.subprocess')
def test_get_new_command_mocked(subp_mock, command, fixed): def test_get_new_command_mocked(subp_mock, command, fixed):
subp_mock.check_output.return_value = PKGFILE_OUTPUT_LLC subp_mock.check_output.return_value = PKGFILE_OUTPUT_LLC
assert get_new_command(command, None) == fixed assert get_new_command(command) == fixed

View File

@@ -14,12 +14,11 @@ def pip_unknown_cmd_without_recommend():
def test_match(pip_unknown_cmd, pip_unknown_cmd_without_recommend): def test_match(pip_unknown_cmd, pip_unknown_cmd_without_recommend):
assert match(Command('pip instatl', stderr=pip_unknown_cmd), None) assert match(Command('pip instatl', stderr=pip_unknown_cmd))
assert not match(Command('pip i', assert not match(Command('pip i',
stderr=pip_unknown_cmd_without_recommend), stderr=pip_unknown_cmd_without_recommend))
None)
def test_get_new_command(pip_unknown_cmd): def test_get_new_command(pip_unknown_cmd):
assert get_new_command(Command('pip instatl', stderr=pip_unknown_cmd), assert get_new_command(Command('pip instatl',
None) == 'pip install' stderr=pip_unknown_cmd)) == 'pip install'

View File

@@ -3,10 +3,10 @@ from tests.utils import Command
def test_match(): def test_match():
assert match(Command('temp.py', stderr='Permission denied'), None) assert match(Command('temp.py', stderr='Permission denied'))
assert not match(Command(), None) assert not match(Command())
def test_get_new_command(): def test_get_new_command():
assert get_new_command(Command('./test_sudo.py'), None)\ assert get_new_command(Command('./test_sudo.py'))\
== 'python ./test_sudo.py' == 'python ./test_sudo.py'

View File

@@ -7,11 +7,11 @@ from tests.utils import Command
Command(script='python foo'), Command(script='python foo'),
Command(script='python bar')]) Command(script='python bar')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
(Command('python foo'), 'python foo.py'), (Command('python foo'), 'python foo.py'),
(Command('python bar'), 'python bar.py')]) (Command('python bar'), 'python bar.py')])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -8,7 +8,7 @@ from tests.utils import Command
Command(script="git commit -am \"Mismatched Quotation Marks\'"), Command(script="git commit -am \"Mismatched Quotation Marks\'"),
Command(script="echo \"hello\'")]) Command(script="echo \"hello\'")])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
@@ -16,4 +16,4 @@ def test_match(command):
(Command("git commit -am \"Mismatched Quotation Marks\'"), "git commit -am \"Mismatched Quotation Marks\""), (Command("git commit -am \"Mismatched Quotation Marks\'"), "git commit -am \"Mismatched Quotation Marks\""),
(Command("echo \"hello\'"), "echo \"hello\"")]) (Command("echo \"hello\'"), "echo \"hello\"")])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -7,25 +7,25 @@ from tests.utils import Command
Command('rm foo', stderr='rm: foo: is a directory'), Command('rm foo', stderr='rm: foo: is a directory'),
Command('rm foo', stderr='rm: foo: Is a directory'), Command('rm foo', stderr='rm: foo: Is a directory'),
Command('hdfs dfs -rm foo', stderr='rm: `foo`: Is a directory'), Command('hdfs dfs -rm foo', stderr='rm: `foo`: Is a directory'),
Command('./bin/hdfs dfs -rm foo', stderr='rm: `foo`: Is a directory') Command('./bin/hdfs dfs -rm foo', stderr='rm: `foo`: Is a directory'),
]) ])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
Command('rm foo'), Command('rm foo'),
Command('hdfs dfs -rm foo'), Command('hdfs dfs -rm foo'),
Command('./bin/hdfs dfs -rm foo'), Command('./bin/hdfs dfs -rm foo'),
Command()]) Command(),
])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
(Command('rm foo'), 'rm -rf foo'), (Command('rm foo'), 'rm -rf foo'),
(Command('hdfs dfs -rm foo'), 'hdfs dfs -rm -r foo')]) (Command('hdfs dfs -rm foo'), 'hdfs dfs -rm -r foo'),
])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -5,7 +5,7 @@ from tests.utils import Command
def test_match(): def test_match():
assert match(Command(script='rm -rf /', assert match(Command(script='rm -rf /',
stderr='add --no-preserve-root'), None) stderr='add --no-preserve-root'))
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
@@ -13,9 +13,9 @@ def test_match():
Command(script='rm --no-preserve-root /', stderr='add --no-preserve-root'), Command(script='rm --no-preserve-root /', stderr='add --no-preserve-root'),
Command(script='rm -rf /', stderr='')]) Command(script='rm -rf /', stderr='')])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
def test_get_new_command(): def test_get_new_command():
assert get_new_command(Command(script='rm -rf /'), None) \ assert get_new_command(Command(script='rm -rf /')) \
== 'rm -rf / --no-preserve-root' == 'rm -rf / --no-preserve-root'

View File

@@ -9,20 +9,20 @@ def sed_unterminated_s():
def test_match(sed_unterminated_s): def test_match(sed_unterminated_s):
assert match(Command('sed -e s/foo/bar', stderr=sed_unterminated_s), None) assert match(Command('sed -e s/foo/bar', stderr=sed_unterminated_s))
assert match(Command('sed -es/foo/bar', stderr=sed_unterminated_s), None) assert match(Command('sed -es/foo/bar', stderr=sed_unterminated_s))
assert match(Command('sed -e s/foo/bar -e s/baz/quz', stderr=sed_unterminated_s), None) assert match(Command('sed -e s/foo/bar -e s/baz/quz', stderr=sed_unterminated_s))
assert not match(Command('sed -e s/foo/bar'), None) assert not match(Command('sed -e s/foo/bar'))
assert not match(Command('sed -es/foo/bar'), None) assert not match(Command('sed -es/foo/bar'))
assert not match(Command('sed -e s/foo/bar -e s/baz/quz'), None) assert not match(Command('sed -e s/foo/bar -e s/baz/quz'))
def test_get_new_command(sed_unterminated_s): def test_get_new_command(sed_unterminated_s):
assert get_new_command(Command('sed -e s/foo/bar', stderr=sed_unterminated_s), None) \ assert get_new_command(Command('sed -e s/foo/bar', stderr=sed_unterminated_s)) \
== 'sed -e s/foo/bar/' == 'sed -e s/foo/bar/'
assert get_new_command(Command('sed -es/foo/bar', stderr=sed_unterminated_s), None) \ assert get_new_command(Command('sed -es/foo/bar', stderr=sed_unterminated_s)) \
== 'sed -es/foo/bar/' == 'sed -es/foo/bar/'
assert get_new_command(Command(r"sed -e 's/\/foo/bar'", stderr=sed_unterminated_s), None) \ assert get_new_command(Command(r"sed -e 's/\/foo/bar'", stderr=sed_unterminated_s)) \
== r"sed -e 's/\/foo/bar/'" == r"sed -e 's/\/foo/bar/'"
assert get_new_command(Command(r"sed -e s/foo/bar -es/baz/quz", stderr=sed_unterminated_s), None) \ assert get_new_command(Command(r"sed -e s/foo/bar -es/baz/quz", stderr=sed_unterminated_s)) \
== r"sed -e s/foo/bar/ -es/baz/quz/" == r"sed -e s/foo/bar/ -es/baz/quz/"

View File

@@ -4,9 +4,9 @@ from tests.utils import Command
def test_match(): def test_match():
assert match(Command('sl'), None) assert match(Command('sl'))
assert not match(Command('ls'), None) assert not match(Command('ls'))
def test_get_new_command(): def test_get_new_command():
assert get_new_command(Command('sl'), None) == 'ls' assert get_new_command(Command('sl')) == 'ls'

View File

@@ -1,6 +1,5 @@
import os import os
import pytest import pytest
from mock import Mock
from thefuck.rules.ssh_known_hosts import match, get_new_command,\ from thefuck.rules.ssh_known_hosts import match, get_new_command,\
side_effect side_effect
from tests.utils import Command from tests.utils import Command
@@ -44,23 +43,24 @@ Host key verification failed.""".format(path, '98.765.432.321')
def test_match(ssh_error): def test_match(ssh_error):
errormsg, _, _, _ = ssh_error errormsg, _, _, _ = ssh_error
assert match(Command('ssh', stderr=errormsg), None) assert match(Command('ssh', stderr=errormsg))
assert match(Command('ssh', stderr=errormsg), None) assert match(Command('ssh', stderr=errormsg))
assert match(Command('scp something something', stderr=errormsg), None) assert match(Command('scp something something', stderr=errormsg))
assert match(Command('scp something something', stderr=errormsg), None) assert match(Command('scp something something', stderr=errormsg))
assert not match(Command(stderr=errormsg), None) assert not match(Command(stderr=errormsg))
assert not match(Command('notssh', stderr=errormsg), None) assert not match(Command('notssh', stderr=errormsg))
assert not match(Command('ssh'), None) assert not match(Command('ssh'))
@pytest.mark.skipif(os.name == 'nt', reason='Skip if testing on Windows')
def test_side_effect(ssh_error): def test_side_effect(ssh_error):
errormsg, path, reset, known_hosts = ssh_error errormsg, path, reset, known_hosts = ssh_error
command = Command('ssh user@host', stderr=errormsg) command = Command('ssh user@host', stderr=errormsg)
side_effect(command, None, None) side_effect(command, None)
expected = ['123.234.567.890 asdjkasjdakjsd\n', '111.222.333.444 qwepoiwqepoiss\n'] expected = ['123.234.567.890 asdjkasjdakjsd\n', '111.222.333.444 qwepoiwqepoiss\n']
assert known_hosts(path) == expected assert known_hosts(path) == expected
def test_get_new_command(ssh_error, monkeypatch): def test_get_new_command(ssh_error, monkeypatch):
errormsg, _, _, _ = ssh_error errormsg, _, _, _ = ssh_error
assert get_new_command(Command('ssh user@host', stderr=errormsg), None) == 'ssh user@host' assert get_new_command(Command('ssh user@host', stderr=errormsg)) == 'ssh user@host'

View File

@@ -14,16 +14,18 @@ from tests.utils import Command
('You don\'t have access to the history DB.', ''), ('You don\'t have access to the history DB.', ''),
('', "error: [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/ipaddr.py'")]) ('', "error: [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/ipaddr.py'")])
def test_match(stderr, stdout): def test_match(stderr, stdout):
assert match(Command(stderr=stderr, stdout=stdout), None) assert match(Command(stderr=stderr, stdout=stdout))
def test_not_match(): def test_not_match():
assert not match(Command(), None) assert not match(Command())
assert not match(Command(script='sudo ls', stderr='Permission denied'))
@pytest.mark.parametrize('before, after', [ @pytest.mark.parametrize('before, after', [
('ls', 'sudo ls'), ('ls', 'sudo ls'),
('echo a > b', 'sudo sh -c "echo a > b"'), ('echo a > b', 'sudo sh -c "echo a > b"'),
('echo "a" >> b', 'sudo sh -c "echo \\"a\\" >> b"')]) ('echo "a" >> b', 'sudo sh -c "echo \\"a\\" >> b"'),
('mkdir && touch a', 'sudo sh -c "mkdir && touch a"')])
def test_get_new_command(before, after): def test_get_new_command(before, after):
assert get_new_command(Command(before), None) == after assert get_new_command(Command(before)) == after

View File

@@ -9,7 +9,7 @@ from tests.utils import Command
Command(stderr='command not found: фзе-пуе', script=u'фзе-пуе'), Command(stderr='command not found: фзе-пуе', script=u'фзе-пуе'),
Command(stderr='command not found: λσ', script=u'λσ')]) Command(stderr='command not found: λσ', script=u'λσ')])
def test_match(command): def test_match(command):
assert switch_lang.match(command, None) assert switch_lang.match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
@@ -18,11 +18,11 @@ def test_match(command):
Command(stderr='command not found: агсл', script=u'агсл'), Command(stderr='command not found: агсл', script=u'агсл'),
Command(stderr='some info', script=u'фзе-пуе')]) Command(stderr='some info', script=u'фзе-пуе')])
def test_not_match(command): def test_not_match(command):
assert not switch_lang.match(command, None) assert not switch_lang.match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
(Command(u'фзе-пуе штыефдд мшь'), 'apt-get install vim'), (Command(u'фзе-пуе штыефдд мшь'), 'apt-get install vim'),
(Command(u'λσ -λα'), 'ls -la')]) (Command(u'λσ -λα'), 'ls -la')])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert switch_lang.get_new_command(command, None) == new_command assert switch_lang.get_new_command(command) == new_command

View File

@@ -1,18 +1,17 @@
import pytest
from thefuck.rules.systemctl import match, get_new_command from thefuck.rules.systemctl import match, get_new_command
from tests.utils import Command from tests.utils import Command
def test_match(): def test_match():
assert match(Command('systemctl nginx start', stderr='Unknown operation \'nginx\'.'), None) assert match(Command('systemctl nginx start', stderr='Unknown operation \'nginx\'.'))
assert match(Command('sudo systemctl nginx start', stderr='Unknown operation \'nginx\'.'), None) assert match(Command('sudo systemctl nginx start', stderr='Unknown operation \'nginx\'.'))
assert not match(Command('systemctl start nginx'), None) assert not match(Command('systemctl start nginx'))
assert not match(Command('systemctl start nginx'), None) assert not match(Command('systemctl start nginx'))
assert not match(Command('sudo systemctl nginx', stderr='Unknown operation \'nginx\'.'), None) assert not match(Command('sudo systemctl nginx', stderr='Unknown operation \'nginx\'.'))
assert not match(Command('systemctl nginx', stderr='Unknown operation \'nginx\'.'), None) assert not match(Command('systemctl nginx', stderr='Unknown operation \'nginx\'.'))
assert not match(Command('systemctl start wtf', stderr='Failed to start wtf.service: Unit wtf.service failed to load: No such file or directory.'), None) assert not match(Command('systemctl start wtf', stderr='Failed to start wtf.service: Unit wtf.service failed to load: No such file or directory.'))
def test_get_new_command(): def test_get_new_command():
assert get_new_command(Command('systemctl nginx start'), None) == "systemctl start nginx" assert get_new_command(Command('systemctl nginx start')) == "systemctl start nginx"
assert get_new_command(Command('sudo systemctl nginx start'), None) == "sudo systemctl start nginx" assert get_new_command(Command('sudo systemctl nginx start')) == "sudo systemctl start nginx"

View File

@@ -11,9 +11,9 @@ def tmux_ambiguous():
def test_match(tmux_ambiguous): def test_match(tmux_ambiguous):
assert match(Command('tmux list', stderr=tmux_ambiguous), None) assert match(Command('tmux list', stderr=tmux_ambiguous))
def test_get_new_command(tmux_ambiguous): def test_get_new_command(tmux_ambiguous):
assert get_new_command(Command('tmux list', stderr=tmux_ambiguous), None)\ assert get_new_command(Command('tmux list', stderr=tmux_ambiguous))\
== ['tmux list-keys', 'tmux list-panes', 'tmux list-windows'] == ['tmux list-keys', 'tmux list-panes', 'tmux list-windows']

29
tests/rules/test_touch.py Normal file
View File

@@ -0,0 +1,29 @@
import pytest
from thefuck.rules.touch import match, get_new_command
from tests.utils import Command
@pytest.fixture
def stderr():
return "touch: cannot touch '/a/b/c':" \
" No such file or directory"
def test_match(stderr):
command = Command(
'touch /a/b/c', stderr=stderr)
assert match(command)
@pytest.mark.parametrize('command', [
Command('touch /a/b/c'),
Command('touch /a/b/c', stdout=stderr()),
Command('ls /a/b/c', stderr=stderr())])
def test_not_match(command):
assert not match(command)
def test_get_new_command(stderr):
command = Command('touch /a/b/c', stderr=stderr)
fixed_command = get_new_command(command)
assert fixed_command == 'mkdir -p /a/b && touch /a/b/c'

View File

@@ -15,7 +15,7 @@ error_msg = (
Command(script='tsuru app-log -f', stderr=error_msg[1]), Command(script='tsuru app-log -f', stderr=error_msg[1]),
]) ])
def test_match(command): def test_match(command):
assert match(command, {}) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
@@ -24,7 +24,7 @@ def test_match(command):
Command(script='tsuru app-log -f', stderr=('Error: unparseable data')), Command(script='tsuru app-log -f', stderr=('Error: unparseable data')),
]) ])
def test_not_match(command): def test_not_match(command):
assert not match(command, {}) assert not match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
@@ -34,4 +34,4 @@ def test_not_match(command):
'tsuru login && tsuru app-log -f'), 'tsuru login && tsuru app-log -f'),
]) ])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, {}) == new_command assert get_new_command(command) == new_command

View File

@@ -30,7 +30,7 @@ from thefuck.rules.tsuru_not_command import match, get_new_command
)), )),
]) ])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
@@ -58,7 +58,7 @@ def test_match(command):
Command('tsuru env-get', stderr='Error: App thefuck not found.'), Command('tsuru env-get', stderr='Error: App thefuck not found.'),
]) ])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
@pytest.mark.parametrize('command, new_commands', [ @pytest.mark.parametrize('command, new_commands', [
@@ -87,4 +87,4 @@ def test_not_match(command):
)), ['tsuru target-list']), )), ['tsuru target-list']),
]) ])
def test_get_new_command(command, new_commands): def test_get_new_command(command, new_commands):
assert get_new_command(command, None) == new_commands assert get_new_command(command) == new_commands

View File

@@ -9,16 +9,16 @@ from tests.utils import Command
stderr='ls: Unknown command\nDid you mean -ls? This command begins with a dash.'), stderr='ls: Unknown command\nDid you mean -ls? This command begins with a dash.'),
Command(script='hdfs dfs ls /foo/bar', stderr='ls: Unknown command\nDid you mean -ls? This command begins with a dash.')]) Command(script='hdfs dfs ls /foo/bar', stderr='ls: Unknown command\nDid you mean -ls? This command begins with a dash.')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
Command(script='./bin/hdfs dfs -ls', stderr=''), Command(script='./bin/hdfs dfs -ls', stderr=''),
Command(script='./bin/hdfs dfs -ls /foo/bar', stderr=''), Command(script='./bin/hdfs dfs -ls /foo/bar', stderr=''),
Command(script='hdfs dfs -ls -R /foo/bar', stderr=''), Command(script='hdfs dfs -ls -R /foo/bar', stderr=''),
Command()]) Command()])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
@@ -31,5 +31,4 @@ def test_not_match(command):
(Command('./bin/hdfs dfs -Dtest=fred ls -R /foo/bar', (Command('./bin/hdfs dfs -Dtest=fred ls -R /foo/bar',
stderr='ls: Unknown command\nDid you mean -ls? This command begins with a dash.'), ['./bin/hdfs dfs -Dtest=fred -ls -R /foo/bar'])]) stderr='ls: Unknown command\nDid you mean -ls? This command begins with a dash.'), ['./bin/hdfs dfs -Dtest=fred -ls -R /foo/bar'])])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -11,16 +11,16 @@ from tests.utils import Command
Command(script='vagrant rdp devbox', Command(script='vagrant rdp devbox',
stderr='VM must be created before running this command. Run `vagrant up` first.')]) stderr='VM must be created before running this command. Run `vagrant up` first.')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
@pytest.mark.parametrize('command', [ @pytest.mark.parametrize('command', [
Command(script='vagrant ssh', stderr=''), Command(script='vagrant ssh', stderr=''),
Command(script='vagrant ssh jeff', stderr='The machine with the name \'jeff\' was not found configured for this Vagrant environment.'), Command(script='vagrant ssh jeff', stderr='The machine with the name \'jeff\' was not found configured for this Vagrant environment.'),
Command(script='vagrant ssh', stderr='A Vagrant environment or target machine is required to run this command. Run `vagrant init` to create a new Vagrant environment. Or, get an ID of a target machine from `vagrant global-status` to run this command on. A final option is to change to a directory with a Vagrantfile and to try again.'), Command(script='vagrant ssh', stderr='A Vagrant environment or target machine is required to run this command. Run `vagrant init` to create a new Vagrant environment. Or, get an ID of a target machine from `vagrant global-status` to run this command on. A final option is to change to a directory with a Vagrantfile and to try again.'),
Command()]) Command()])
def test_not_match(command): def test_not_match(command):
assert not match(command, None) assert not match(command)
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
@@ -31,5 +31,4 @@ def test_not_match(command):
(Command(script='vagrant rdp devbox', (Command(script='vagrant rdp devbox',
stderr='VM must be created before running this command. Run `vagrant up` first.'), ['vagrant up devbox && vagrant rdp devbox', 'vagrant up && vagrant rdp devbox'])]) stderr='VM must be created before running this command. Run `vagrant up` first.'), ['vagrant up devbox && vagrant rdp devbox', 'vagrant up && vagrant rdp devbox'])])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

View File

@@ -8,11 +8,11 @@ from tests.utils import Command
Command(script='whois https://en.wikipedia.org/'), Command(script='whois https://en.wikipedia.org/'),
Command(script='whois meta.unix.stackexchange.com')]) Command(script='whois meta.unix.stackexchange.com')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command)
def test_not_match(): def test_not_match():
assert not match(Command(script='whois'), None) assert not match(Command(script='whois'))
# `whois com` actually makes sense # `whois com` actually makes sense
@@ -23,4 +23,4 @@ def test_not_match():
'whois stackexchange.com', 'whois stackexchange.com',
'whois com'])]) 'whois com'])])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command) == new_command

0
tests/shells/__init__.py Normal file
View File

22
tests/shells/conftest.py Normal file
View File

@@ -0,0 +1,22 @@
import pytest
@pytest.fixture
def builtins_open(mocker):
return mocker.patch('six.moves.builtins.open')
@pytest.fixture
def isfile(mocker):
return mocker.patch('os.path.isfile', return_value=True)
@pytest.fixture
@pytest.mark.usefixtures('isfile')
def history_lines(mocker):
def aux(lines):
mock = mocker.patch('io.open')
mock.return_value.__enter__ \
.return_value.readlines.return_value = lines
return aux

58
tests/shells/test_bash.py Normal file
View File

@@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
import os
import pytest
from thefuck.shells import Bash
@pytest.mark.usefixtures('isfile', 'no_memoize', 'no_cache')
class TestBash(object):
@pytest.fixture
def shell(self):
return Bash()
@pytest.fixture(autouse=True)
def shell_aliases(self):
os.environ['TF_SHELL_ALIASES'] = (
'alias fuck=\'eval $(thefuck $(fc -ln -1))\'\n'
'alias l=\'ls -CF\'\n'
'alias la=\'ls -A\'\n'
'alias ll=\'ls -alF\'')
@pytest.mark.parametrize('before, after', [
('pwd', 'pwd'),
('fuck', 'eval $(thefuck $(fc -ln -1))'),
('awk', 'awk'),
('ll', 'ls -alF')])
def test_from_shell(self, before, after, shell):
assert shell.from_shell(before) == after
def test_to_shell(self, shell):
assert shell.to_shell('pwd') == 'pwd'
def test_and_(self, shell):
assert shell.and_('ls', 'cd') == 'ls && cd'
def test_get_aliases(self, shell):
assert shell.get_aliases() == {'fuck': 'eval $(thefuck $(fc -ln -1))',
'l': 'ls -CF',
'la': 'ls -A',
'll': 'ls -alF'}
def test_app_alias(self, shell):
assert 'alias fuck' in shell.app_alias('fuck')
assert 'alias FUCK' in shell.app_alias('FUCK')
assert 'thefuck' in shell.app_alias('fuck')
assert 'TF_ALIAS=fuck' in shell.app_alias('fuck')
assert 'PYTHONIOENCODING=utf-8' in shell.app_alias('fuck')
def test_app_alias_variables_correctly_set(self, shell):
alias = shell.app_alias('fuck')
assert "alias fuck='TF_CMD=$(TF_ALIAS" in alias
assert '$(TF_ALIAS=fuck PYTHONIOENCODING' in alias
assert 'PYTHONIOENCODING=utf-8 TF_SHELL_ALIASES' in alias
assert 'ALIASES=$(alias) thefuck' in alias
def test_get_history(self, history_lines, shell):
history_lines(['ls', 'rm'])
assert list(shell.get_history()) == ['ls', 'rm']

Some files were not shown because too many files have changed in this diff Show More