Skip to content

Commit

Permalink
vcs/git: Add GitIgnoreBear
Browse files Browse the repository at this point in the history
Closes #2610
  • Loading branch information
bharath21 authored and gitmate-bot committed Feb 19, 2019
1 parent 822c2ed commit fd5a5a7
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 0 deletions.
50 changes: 50 additions & 0 deletions bears/vcs/git/GitIgnoreBear.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import shutil

from coalib.bears.GlobalBear import GlobalBear
from coalib.misc.Shell import run_shell_command


class GitIgnoreBear(GlobalBear):
AUTHORS = {'The coala developers'}
AUTHORS_EMAILS = {'[email protected]'}
LICENSE = 'AGPL-3.0'
CAN_DETECT = {'Formatting'}
LANGUAGES = {'Git'}

@classmethod
def check_prerequisites(cls):
if shutil.which('git') is None:
return 'git is not installed.'
else:
return True

@staticmethod
def get_ignored_files():
"""
This function checks for the files that are being tracked
but are ignored in .gitignore file.
Visit https://github.com/coala/coala-bears/issues/2610
for more details.
:return:
A list of details of tracked files that are
ignored in .gitignore file.
"""
files, _ = run_shell_command('git ls-files')
files = files.strip().split('\n')
ignored = list(map(
lambda file: run_shell_command(
'git check-ignore --no-index -v {}'.format(file))[0].strip(),
files
))
return list(filter(lambda f: f != '', ignored))

def run(self):
for line in GitIgnoreBear.get_ignored_files():
pattern, filename = line.split('\t')
ignore_filename, line_number, ignore_regex = pattern.split(':')
yield self.new_result(
message='File {} is being tracked which was ignored in line '
'number {} in file {}.'.format(
filename, line_number, ignore_filename),
file=filename)
119 changes: 119 additions & 0 deletions tests/vcs/git/GitIgnoreBearTest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import os
import platform
import shutil
import stat
import unittest
import unittest.mock
from queue import Queue
from tempfile import mkdtemp

from bears.vcs.git.GitIgnoreBear import GitIgnoreBear
from coalib.testing.BearTestHelper import generate_skip_decorator
from coalib.misc.Shell import run_shell_command
from coalib.settings.Section import Section


@generate_skip_decorator(GitIgnoreBear)
class GitIgnoreBearTest(unittest.TestCase):

@staticmethod
def run_git_command(*args, stdin=None):
run_shell_command(' '.join(('git',) + args), stdin)

def run_uut(self, *args, **kwargs):
"""
Runs the unit-under-test (via `self.uut.run()`) and collects the
messages of the yielded results as a list.
:param args: Positional arguments to forward to the run function.
:param kwargs: Keyword arguments to forward to the run function.
:return: A list of the message strings.
"""
return list(result.message for result in self.uut.run(*args, **kwargs))

def assert_no_msgs(self):
"""
Assert that there are no messages in the message queue of the bear, and
show the messages in the failure message if it is not empty.
"""
self.assertTrue(
self.msg_queue.empty(),
'Expected no messages in bear message queue, but got: ' +
str(list(str(i) for i in self.msg_queue.queue)))

def setUp(self):
self.msg_queue = Queue()
self.section = Section('')
self.uut = GitIgnoreBear(None, self.section, self.msg_queue)

self._old_cwd = os.getcwd()
self.gitdir = mkdtemp()
os.chdir(self.gitdir)
self.run_git_command('init')
self.run_git_command('config', 'user.email [email protected]')
self.run_git_command('config', 'user.name coala')

@staticmethod
def _windows_rmtree_remove_readonly(func, path, excinfo):
os.chmod(path, stat.S_IWRITE)
func(path)

def tearDown(self):
os.chdir(self._old_cwd)
if platform.system() == 'Windows':
onerror = self._windows_rmtree_remove_readonly
else:
onerror = None
shutil.rmtree(self.gitdir, onerror=onerror)

def test_check_prerequisites(self):
_shutil_which = shutil.which
try:
shutil.which = lambda *args, **kwargs: None
self.assertEqual(GitIgnoreBear.check_prerequisites(),
'git is not installed.')

shutil.which = lambda *args, **kwargs: 'path/to/git'
self.assertTrue(GitIgnoreBear.check_prerequisites())
finally:
shutil.which = _shutil_which

def test_no_tracked_files(self):
self.assertEqual(self.run_uut(), [])
self.assert_no_msgs()

def test_no_gitignore_file(self):
file = open('test_file.txt', 'w')
file.close()
self.run_git_command('add', 'test_file.txt')

self.assertEqual(self.run_uut(), [])
self.assert_no_msgs()

def test_already_tracked_file(self):
file = open('test_file.txt', 'w')
file.close()
self.run_git_command('add', 'test_file.txt')

file = open('.gitignore', 'w')
file.write('test_file.txt')
file.close()

self.run_git_command('add', '.gitignore')
self.assertEqual(self.run_uut(), [
'File test_file.txt is being tracked which was ignored in line'
' number 1 in file .gitignore.'
])
self.assert_no_msgs()

def test_untracked_file(self):
file = open('test_file.txt', 'w')
file.close()

file = open('.gitignore', 'w')
file.write('test_file.txt')
file.close()

self.run_git_command('add', '.gitignore')
self.assertEqual(self.run_uut(), [])
self.assert_no_msgs()

0 comments on commit fd5a5a7

Please sign in to comment.