Skip to content

Commit fd5a5a7

Browse files
bharath21gitmate-bot
authored andcommitted
vcs/git: Add GitIgnoreBear
Closes #2610
1 parent 822c2ed commit fd5a5a7

File tree

2 files changed

+169
-0
lines changed

2 files changed

+169
-0
lines changed

bears/vcs/git/GitIgnoreBear.py

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import shutil
2+
3+
from coalib.bears.GlobalBear import GlobalBear
4+
from coalib.misc.Shell import run_shell_command
5+
6+
7+
class GitIgnoreBear(GlobalBear):
8+
AUTHORS = {'The coala developers'}
9+
AUTHORS_EMAILS = {'[email protected]'}
10+
LICENSE = 'AGPL-3.0'
11+
CAN_DETECT = {'Formatting'}
12+
LANGUAGES = {'Git'}
13+
14+
@classmethod
15+
def check_prerequisites(cls):
16+
if shutil.which('git') is None:
17+
return 'git is not installed.'
18+
else:
19+
return True
20+
21+
@staticmethod
22+
def get_ignored_files():
23+
"""
24+
This function checks for the files that are being tracked
25+
but are ignored in .gitignore file.
26+
Visit https://github.com/coala/coala-bears/issues/2610
27+
for more details.
28+
29+
:return:
30+
A list of details of tracked files that are
31+
ignored in .gitignore file.
32+
"""
33+
files, _ = run_shell_command('git ls-files')
34+
files = files.strip().split('\n')
35+
ignored = list(map(
36+
lambda file: run_shell_command(
37+
'git check-ignore --no-index -v {}'.format(file))[0].strip(),
38+
files
39+
))
40+
return list(filter(lambda f: f != '', ignored))
41+
42+
def run(self):
43+
for line in GitIgnoreBear.get_ignored_files():
44+
pattern, filename = line.split('\t')
45+
ignore_filename, line_number, ignore_regex = pattern.split(':')
46+
yield self.new_result(
47+
message='File {} is being tracked which was ignored in line '
48+
'number {} in file {}.'.format(
49+
filename, line_number, ignore_filename),
50+
file=filename)

tests/vcs/git/GitIgnoreBearTest.py

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import os
2+
import platform
3+
import shutil
4+
import stat
5+
import unittest
6+
import unittest.mock
7+
from queue import Queue
8+
from tempfile import mkdtemp
9+
10+
from bears.vcs.git.GitIgnoreBear import GitIgnoreBear
11+
from coalib.testing.BearTestHelper import generate_skip_decorator
12+
from coalib.misc.Shell import run_shell_command
13+
from coalib.settings.Section import Section
14+
15+
16+
@generate_skip_decorator(GitIgnoreBear)
17+
class GitIgnoreBearTest(unittest.TestCase):
18+
19+
@staticmethod
20+
def run_git_command(*args, stdin=None):
21+
run_shell_command(' '.join(('git',) + args), stdin)
22+
23+
def run_uut(self, *args, **kwargs):
24+
"""
25+
Runs the unit-under-test (via `self.uut.run()`) and collects the
26+
messages of the yielded results as a list.
27+
28+
:param args: Positional arguments to forward to the run function.
29+
:param kwargs: Keyword arguments to forward to the run function.
30+
:return: A list of the message strings.
31+
"""
32+
return list(result.message for result in self.uut.run(*args, **kwargs))
33+
34+
def assert_no_msgs(self):
35+
"""
36+
Assert that there are no messages in the message queue of the bear, and
37+
show the messages in the failure message if it is not empty.
38+
"""
39+
self.assertTrue(
40+
self.msg_queue.empty(),
41+
'Expected no messages in bear message queue, but got: ' +
42+
str(list(str(i) for i in self.msg_queue.queue)))
43+
44+
def setUp(self):
45+
self.msg_queue = Queue()
46+
self.section = Section('')
47+
self.uut = GitIgnoreBear(None, self.section, self.msg_queue)
48+
49+
self._old_cwd = os.getcwd()
50+
self.gitdir = mkdtemp()
51+
os.chdir(self.gitdir)
52+
self.run_git_command('init')
53+
self.run_git_command('config', 'user.email [email protected]')
54+
self.run_git_command('config', 'user.name coala')
55+
56+
@staticmethod
57+
def _windows_rmtree_remove_readonly(func, path, excinfo):
58+
os.chmod(path, stat.S_IWRITE)
59+
func(path)
60+
61+
def tearDown(self):
62+
os.chdir(self._old_cwd)
63+
if platform.system() == 'Windows':
64+
onerror = self._windows_rmtree_remove_readonly
65+
else:
66+
onerror = None
67+
shutil.rmtree(self.gitdir, onerror=onerror)
68+
69+
def test_check_prerequisites(self):
70+
_shutil_which = shutil.which
71+
try:
72+
shutil.which = lambda *args, **kwargs: None
73+
self.assertEqual(GitIgnoreBear.check_prerequisites(),
74+
'git is not installed.')
75+
76+
shutil.which = lambda *args, **kwargs: 'path/to/git'
77+
self.assertTrue(GitIgnoreBear.check_prerequisites())
78+
finally:
79+
shutil.which = _shutil_which
80+
81+
def test_no_tracked_files(self):
82+
self.assertEqual(self.run_uut(), [])
83+
self.assert_no_msgs()
84+
85+
def test_no_gitignore_file(self):
86+
file = open('test_file.txt', 'w')
87+
file.close()
88+
self.run_git_command('add', 'test_file.txt')
89+
90+
self.assertEqual(self.run_uut(), [])
91+
self.assert_no_msgs()
92+
93+
def test_already_tracked_file(self):
94+
file = open('test_file.txt', 'w')
95+
file.close()
96+
self.run_git_command('add', 'test_file.txt')
97+
98+
file = open('.gitignore', 'w')
99+
file.write('test_file.txt')
100+
file.close()
101+
102+
self.run_git_command('add', '.gitignore')
103+
self.assertEqual(self.run_uut(), [
104+
'File test_file.txt is being tracked which was ignored in line'
105+
' number 1 in file .gitignore.'
106+
])
107+
self.assert_no_msgs()
108+
109+
def test_untracked_file(self):
110+
file = open('test_file.txt', 'w')
111+
file.close()
112+
113+
file = open('.gitignore', 'w')
114+
file.write('test_file.txt')
115+
file.close()
116+
117+
self.run_git_command('add', '.gitignore')
118+
self.assertEqual(self.run_uut(), [])
119+
self.assert_no_msgs()

0 commit comments

Comments
 (0)