1
0
mirror of https://github.com/nvbn/thefuck.git synced 2025-01-31 02:01:13 +00:00

completed changes for makefile rule

This commit is contained in:
hustona 2022-04-19 19:00:40 -04:00
parent cf1beb6b89
commit dcef21e778
3 changed files with 191 additions and 0 deletions

View File

@ -288,6 +288,7 @@ following rules are enabled by default:
* `ln_s_order` – fixes `ln -s` arguments order;
* `ls_all` – adds `-A` to `ls` when output is empty;
* `ls_lah` – adds `-lah` to `ls`;
* `makefile` – fixes wrong `make` commands;
* `man` – changes manual section;
* `man_no_space` – fixes man commands without spaces, for example `mandiff`;
* `mercurial` – fixes wrong `hg` commands;

View File

@ -0,0 +1,129 @@
import pytest
import os
from thefuck.rules.makefile import match, get_new_command
from thefuck.types import Command
@pytest.mark.parametrize('command,expected', [
(Command('make fo', "make: *** No rule to make target 'fo'. Stop."), True),
(Command('make ba', "make: *** No rule to make target 'ba'. Stop."), True),
(Command('mak foo', "mak: command not found"), True),
(Command('mak oo', "mak: command not found"), True),
(Command('meak foo', "meak: command not found"), True),
(Command('maek bar', "maek: command not found"), True),
(Command('maek br', "maek: command not found"), True),
(Command('amke foo', "amke: command not found"), True),
(Command('make foo', "make: command not found"), False),
(Command('cd foo', 'cd: foo: No such file or directory'), False),
(Command('java foo.java', 'error message'), False),
(Command('make partone parttwo', "make: *** No rule to make target 'partone parttwo'. Stop."), True)
])
def test_match(command,expected):
"""
Tests the match function with inputs such as misspelled makes,
misspelled targets, irrelevant commands, and correctly formatted commands.
Tests with makefiles named Makefile, makefile, and GNUmakefile
"""
with open("Makefile", "w") as openfile:
# Creates Temporary makefile for testing
openfile.write("foo:\n")
openfile.write("bar:\n")
result = match(command)
os.remove("Makefile") # Removes Temporary Makefile
assert result == expected
with open("makefile", "w") as openfile:
# Creates Temporary makefile for testing
openfile.write("foo:\n")
openfile.write("bar:\n")
result = match(command)
os.remove("makefile") # Removes Temporary Makefile
assert result == expected
with open("GNUmakefile", "w") as openfile:
# Creates Temporary makefile for testing
openfile.write("foo:\n")
openfile.write("bar:\n")
result = match(command)
os.remove("GNUmakefile") # Removes Temporary Makefile
assert result == expected
@pytest.mark.parametrize('command,expected', [
(Command('make foo', "no error"), False),
(Command('make fo', "make: *** No rule to make target 'fo'. Stop."), False),
(Command('maek bar', "maek: command not found"), False),
(Command('cd foo', 'cd: foo: No such file or directory'), False)
])
def test_match_no_makefile(command,expected):
"""
Tests the match function with no available makefile
"""
result = match(command)
assert result == expected
@pytest.mark.parametrize('command,expected', [
(Command('make fo', "make: *** No rule to make target 'fo'. Stop."), "make foo"),
(Command('make ba', "make: *** No rule to make target 'ba'. Stop."), "make bar"),
(Command('make for', "make: *** No rule to make target 'for'. Stop."), "make foo"),
(Command('mak foo', "mak: command not found"), "make foo"),
(Command('mak oo', "mak: command not found"), "make foo"),
(Command('meak foo', "meak: command not found"), "make foo"),
(Command('maek bar', "maek: command not found"), "make bar"),
(Command('maek br', "maek: command not found"), "make bar"),
(Command('amke foo', "amke: command not found"), "make foo"),
(Command('amke qwe', "amke: command not found"), "make foo"),
])
def test_get_new_command(command,expected):
"""
Test the correct functionality of generating the new command.
Tests with makefiles named Makefile, makefile, and GNUmakefile
"""
with open("Makefile", "w") as openfile:
# Creates Temporary makefile for testing
openfile.write("foo:\n")
openfile.write("\tg++ testfoo.cpp\n")
openfile.write("bar:\n")
openfile.write("\tg++ testbar.cpp\n")
result = get_new_command(command)
os.remove("Makefile") # Removes Temporary Makefile
assert result == expected
with open("makefile", "w") as openfile:
# Creates Temporary makefile for testing
openfile.write("foo:\n")
openfile.write("\tg++ testfoo.cpp\n")
openfile.write("bar:\n")
openfile.write("\tg++ testbar.cpp\n")
result = get_new_command(command)
os.remove("makefile") # Removes Temporary Makefile
assert result == expected
with open("GNUmakefile", "w") as openfile:
# Creates Temporary makefile for testing
openfile.write("foo:\n")
openfile.write("\tg++ testfoo.cpp\n")
openfile.write("bar:\n")
openfile.write("\tg++ testbar.cpp\n")
result = get_new_command(command)
os.remove("GNUmakefile") # Removes Temporary Makefile
assert result == expected
@pytest.mark.parametrize('command,expected', [
(Command('make fo', "make: *** No rule to make target 'fo'. Stop."), "make foo"),
(Command('make foodo', "make: *** No rule to make target 'foodo'. Stop."), "make food"),
(Command('make dfoo', "make: *** No rule to make target 'dfoo'. Stop."), "make foo"),
])
def test_get_new_command_2(command,expected):
with open("Makefile", "w") as openfile:
# Creates Temporary makefile for testing
openfile.write("foo:\n")
openfile.write("\tg++ testfoo.cpp\n")
openfile.write("food:\n")
openfile.write("\tg++ testfood.cpp\n")
result = get_new_command(command)
os.remove("Makefile") # Removes Temporary Makefile
assert result == expected

61
thefuck/rules/makefile.py Normal file
View File

@ -0,0 +1,61 @@
import os
from os.path import isfile, join
from thefuck.utils import get_closest
TOLERANCE = 0.6
COMMON_MISSPELLINGS = ['mke', 'maek', 'amke', 'meak', 'mkae', 'ake', 'mae', 'mak', 'makee', 'mmake', 'nake', 'makr', 'mske']
def makefile_in_directory():
"""
Returns the name of the Makefile in the current directory.
Will return a blank string if no makefile found.
"""
name_of_makefile = ""
file_list = [f for f in os.listdir(os.getcwd()) if isfile(join(os.getcwd(), f))]
if 'GNUmakefile' in file_list:
name_of_makefile = 'GNUmakefile'
elif 'makefile' in file_list:
name_of_makefile = 'makefile'
elif 'Makefile' in file_list:
name_of_makefile = 'Makefile'
return name_of_makefile
def match(command):
"""Match function that determines if this rule could fix this command"""
if len(makefile_in_directory()) == 0:
# This would mean there is no makefile in the directory, we do not have a match
return False
first_word = command.script_parts[0].lower()
if first_word in COMMON_MISSPELLINGS:
# There is a Makefile and the first word of the command was a misspelling of 'make'
return True
if 'no rule to make target' in command.output.lower():
# The target passed into the make command was misspelled or did not exist
return True
return False
def get_new_command(command):
"""
Attempt to rebuild the make command by spellchecking the targets.
If it fails (i.e. no targets are a close enough match), then it
defaults to first make target in the file.
Change sensitivity by changing TOLERANCE. Default value is 0.6
"""
# Get possible targets from makefile and find the most similar.
name_of_makefile = makefile_in_directory()
possible_targets = []
with open(name_of_makefile, 'r') as openfile:
lines = openfile.readlines()
for line in lines: # Loop through the makefile lines and find all targets
line = line.strip()
parts = line.split(':')
if len(parts) > 1: # If there is a colon
if parts[0][0] != '.': # If it is a valid target
possible_targets.append(parts[0])
new_target = get_closest(' '.join(command.script_parts[1:]), possible_targets, cutoff=TOLERANCE)
return "make " + new_target