Look in lower directory ignore files first.
authorJelmer Vernooij <jelmer@jelmer.uk>
Thu, 13 Jul 2017 01:23:58 +0000 (01:23 +0000)
committerJelmer Vernooij <jelmer@jelmer.uk>
Thu, 13 Jul 2017 01:23:58 +0000 (01:23 +0000)
dulwich/ignore.py
dulwich/tests/test_ignore.py

index f9caf1400477ddcad3650bab048c5a6a0cc69420..f24790361750c527fab0e034d953a66b7055f3dd 100644 (file)
@@ -226,7 +226,7 @@ class IgnoreFilterManager(object):
         except KeyError:
             pass
 
-        p = os.path.join(path, '.gitignore')
+        p = os.path.join(self._top_path, path, '.gitignore')
         try:
             self._path_filters[path] = IgnoreFilter.from_path(p)
         except IOError:
@@ -240,22 +240,20 @@ class IgnoreFilterManager(object):
         :return: None if the file is not mentioned, True if it is included,
             False if it is explicitly excluded.
         """
-        if not os.path.isabs(path):
-            path = os.path.join(self._top_path, path)
-        dirname = path
-        while dirname not in (self._top_path, '/'):
-            dirname = os.path.dirname(dirname)
-            ignore_filter = self._load_path(dirname)
-            if ignore_filter is not None:
-                relpath = os.path.relpath(path, dirname)
-                status = ignore_filter.is_ignored(relpath)
+        if os.path.isabs(path):
+            path = os.path.relpath(path, self._top_path)
+        filters = [(0, f) for f in self._global_filters]
+        parts = path.split(os.path.sep)
+        for i in range(len(parts)+1):
+            dirname = os.path.sep.join(parts[:i])
+            for s, f in filters:
+                relpath = os.path.sep.join(parts[s:i])
+                status = f.is_ignored(relpath)
                 if status is not None:
                     return status
-        for ignore_filter in self._global_filters:
-            relpath = os.path.relpath(path, self._top_path)
-            status = ignore_filter.is_ignored(relpath)
-            if status is not None:
-                return status
+            ignore_filter = self._load_path(dirname)
+            if ignore_filter is not None:
+                filters.insert(0, (i, ignore_filter))
         return None
 
     @classmethod
index 5fb8bbc80c3201dfc7672d0c70367ea518021a1c..34f76992d68aa1f414ceac4b4077bbfd4247547f 100644 (file)
@@ -167,6 +167,7 @@ class IgnoreFilterManagerTests(TestCase):
         repo = Repo.init(tmp_dir)
         with open(os.path.join(repo.path, '.gitignore'), 'wb') as f:
             f.write(b'/foo/bar\n')
+            f.write(b'/dir2\n')
         os.mkdir(os.path.join(repo.path, 'dir'))
         with open(os.path.join(repo.path, 'dir', '.gitignore'), 'wb') as f:
             f.write(b'/blie\n')
@@ -176,9 +177,11 @@ class IgnoreFilterManagerTests(TestCase):
         with open(p, 'wb') as f:
             f.write(b'/excluded\n')
         m = IgnoreFilterManager.from_repo(repo)
-        self.assertTrue(m.is_ignored(os.path.join(repo.path, 'dir', 'blie')))
+        self.assertTrue(m.is_ignored(os.path.join('dir', 'blie')))
         self.assertIs(None,
                       m.is_ignored(os.path.join(repo.path, 'dir', 'bloe')))
         self.assertIs(None, m.is_ignored(os.path.join(repo.path, 'dir')))
         self.assertTrue(m.is_ignored(os.path.join(repo.path, 'foo', 'bar')))
         self.assertTrue(m.is_ignored(os.path.join(repo.path, 'excluded')))
+        self.assertTrue(m.is_ignored(os.path.join(
+            repo.path, 'dir2', 'fileinignoreddir')))