diff --git a/README.md b/README.md index 2ff554fa..36bf881f 100644 --- a/README.md +++ b/README.md @@ -178,6 +178,7 @@ using the matched rule and runs it. Rules enabled by default are as follows: * `java` – removes `.java` extension when running Java programs; * `javac` – appends missing `.java` when compiling Java files; * `lein_not_task` – fixes wrong `lein` tasks like `lein rpl`; +* `ln_no_hard_link` – catches hard link creation on directories, suggest symbolic link; * `ls_lah` – adds `-lah` to `ls`; * `man` – changes manual section; * `man_no_space` – fixes man commands without spaces, for example `mandiff`; diff --git a/tests/rules/test_ln_no_hard_link.py b/tests/rules/test_ln_no_hard_link.py new file mode 100644 index 00000000..ca212790 --- /dev/null +++ b/tests/rules/test_ln_no_hard_link.py @@ -0,0 +1,45 @@ +from thefuck.rules.ln_no_hard_link import match, get_new_command +from tests.utils import Command + + +def test_match(): + err = "hard link not allowed for directory" + assert not match(Command()) + + cmd1 = Command("ln barDir barLink", stderr="ln: ‘barDir’: {}".format(err)) + assert match(cmd1) + + cmd2 = Command("sudo ln a b", stderr="ln: ‘a’: {}".format(err)) + assert match(cmd2) + + cmd3 = Command("ln a b", stderr="... hard link") + assert not match(cmd3) + + cmd4 = Command("sudo ln a b", stderr="... hard link") + assert not match(cmd4) + + cmd5 = Command("a b", stderr=err) + assert not match(cmd5) + + cmd6 = Command("sudo ln -nbi a b", stderr="ln: ‘a’: {}".format(err)) + assert match(cmd6) + + +def test_get_new_command(): + cmd1 = Command("ln barDir barLink") + assert get_new_command(cmd1) == "ln -s barDir barLink" + + cmd2 = Command("sudo ln barDir barLink") + assert get_new_command(cmd2) == "sudo ln -s barDir barLink" + + cmd3 = Command("sudo ln -nbi a b") + assert get_new_command(cmd3) == "sudo ln -s -nbi a b" + + cmd4 = Command("ln -nbi a b && ls") + assert get_new_command(cmd4) == "ln -s -nbi a b && ls" + + cmd5 = Command("ln a ln") + assert get_new_command(cmd5) == "ln -s a ln" + + cmd6 = Command("sudo ln a ln") + assert get_new_command(cmd6) == "sudo ln -s a ln" diff --git a/thefuck/rules/ln_no_hard_link.py b/thefuck/rules/ln_no_hard_link.py new file mode 100644 index 00000000..422f4ed3 --- /dev/null +++ b/thefuck/rules/ln_no_hard_link.py @@ -0,0 +1,24 @@ +"""Suggest creating symbolic link if hard link is not allowed. + +Example: +> ln barDir barLink +ln: ‘barDir’: hard link not allowed for directory + +--> ln -s barDir barLink +""" + +import re +from thefuck.utils import for_app +from thefuck.specific.sudo import sudo_support + + +@sudo_support +@for_app('ln') +def match(command): + return (command.stderr.endswith("hard link not allowed for directory") and + command.script.startswith("ln ")) + + +@sudo_support +def get_new_command(command): + return re.sub(r'^ln ', 'ln -s ', command.script)