diff --git a/cycode/cli/files_collector/walk_ignore.py b/cycode/cli/files_collector/walk_ignore.py index 76d04366..93286c87 100644 --- a/cycode/cli/files_collector/walk_ignore.py +++ b/cycode/cli/files_collector/walk_ignore.py @@ -24,7 +24,8 @@ def _walk_to_top(path: str) -> Iterable[str]: def _collect_top_level_ignore_files(path: str) -> List[str]: ignore_files = [] - for dir_path in _walk_to_top(path): + top_paths = reversed(list(_walk_to_top(path))) # we must reverse it to make top levels more prioritized + for dir_path in top_paths: for ignore_file in _SUPPORTED_IGNORE_PATTERN_FILES: ignore_file_path = os.path.join(dir_path, ignore_file) if os.path.exists(ignore_file_path): diff --git a/cycode/cli/utils/ignore_utils.py b/cycode/cli/utils/ignore_utils.py index 329fa055..f44b6024 100644 --- a/cycode/cli/utils/ignore_utils.py +++ b/cycode/cli/utils/ignore_utils.py @@ -396,12 +396,10 @@ def walk(self, **kwargs) -> Generator[Tuple[str, List[str], List[str]], None, No # decrease recursion depth of os.walk() by ignoring subdirectories because of topdown=True # slicing ([:]) is mandatory to change dict in-place! - dirnames[:] = [ - dirname for dirname in dirnames if not self.is_ignored(os.path.join(rel_dirpath, dirname, '')) - ] + dirnames[:] = [d for d in dirnames if not self.is_ignored(os.path.join(rel_dirpath, d))] # remove ignored files - filenames = [os.path.basename(f) for f in filenames if not self.is_ignored(os.path.join(rel_dirpath, f))] + filenames = [f for f in filenames if not self.is_ignored(os.path.join(rel_dirpath, f))] yield dirpath, dirnames, filenames diff --git a/tests/cli/files_collector/test_walk_ignore.py b/tests/cli/files_collector/test_walk_ignore.py index fd2612d5..b771cdf9 100644 --- a/tests/cli/files_collector/test_walk_ignore.py +++ b/tests/cli/files_collector/test_walk_ignore.py @@ -140,3 +140,20 @@ def test_walk_ignore(fs: 'FakeFilesystem') -> None: assert normpath('/home/user/project/subproject/ignored.pyc') not in result # presented: assert normpath('/home/user/project/subproject/presented.py') in result + + +def test_walk_ignore_top_level_ignores_order(fs: 'FakeFilesystem') -> None: + fs.create_file('/home/user/.gitignore', contents='*.log') + fs.create_file('/home/user/project/.gitignore', contents='!*.log') # rollback *.log ignore for project + fs.create_dir('/home/user/project/subproject') + + fs.create_file('/home/user/ignored.log') + fs.create_file('/home/user/project/presented.log') + fs.create_file('/home/user/project/subproject/presented.log') + + path = normpath('/home/user/project') + result = _collect_walk_ignore_files(path) + assert len(result) == 3 + assert normpath('/home/user/ignored.log') not in result + assert normpath('/home/user/project/presented.log') in result + assert normpath('/home/user/project/subproject/presented.log') in result