Skip to content

Commit

Permalink
Refs #78. Fix handling of export-ignore for directories
Browse files Browse the repository at this point in the history
Files contained by ignored directories should be ignored as well
unless export-ignore is explicitly unset either for the file itself
or for any preceding directory.
  • Loading branch information
Kentzo committed Feb 10, 2020
1 parent ed50459 commit 43f0728
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 4 deletions.
24 changes: 21 additions & 3 deletions git_archive_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ def __init__(self, prefix='', exclude=True, force_sub=False, extra=None, main_re
If None, tries to resolve via Git's CLI.
"""
self._check_attr_gens = {}
self._ignored_paths_cache = {}

if git_version is None:
git_version = self.get_git_version()
Expand Down Expand Up @@ -271,9 +272,26 @@ def is_file_excluded(self, repo_abspath, repo_file_path):
@return: True if file should be excluded. Otherwise False.
"""
next(self._check_attr_gens[repo_abspath])
attrs = self._check_attr_gens[repo_abspath].send(repo_file_path)
return attrs['export-ignore'] == b'set'
cache = self._ignored_paths_cache.setdefault(repo_abspath, {})

if repo_file_path not in cache:
next(self._check_attr_gens[repo_abspath])
attrs = self._check_attr_gens[repo_abspath].send(repo_file_path)
export_ignore_attr = attrs['export-ignore']

if export_ignore_attr == b'set':
cache[repo_file_path] = True
elif export_ignore_attr == b'unset':
cache[repo_file_path] = False
else:
repo_file_dir_path = path.dirname(repo_file_path)

if repo_file_dir_path:
cache[repo_file_path] = self.is_file_excluded(repo_abspath, repo_file_dir_path)
else:
cache[repo_file_path] = False

return cache[repo_file_path]

def archive_all_files(self, archiver):
"""
Expand Down
2 changes: 2 additions & 0 deletions git_archive_all.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class GitArchiver(object):
LOG: ClassVar[logging.Logger]

_check_attr_gens: Dict[str, CheckGitAttrGen]
_ignored_paths_cache: Dict[PathStr, Dict[PathStr, bool]]

git_version: Optional[Tuple[int]]
main_repo_abspath: PathStr
prefix: PathStr
Expand Down
13 changes: 12 additions & 1 deletion test_git_archive_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,16 @@ def make_actual_tree(tar_file):
b'\"\\\xc2.dat\"': FileRecord('Although practicality beats purity.')
})

ignore_dir = {
'.gitattributes': FileRecord('.gitattributes export-ignore\n**/src export-ignore\ndata/src/__main__.py -export-ignore', excluded=True),
'__init__.py': FileRecord('#Beautiful is better than ugly.'),
'data': DirRecord({
'src': DirRecord({
'__init__.py': FileRecord('#Explicit is better than implicit.', excluded=True),
'__main__.py': FileRecord('#Simple is better than complex.')
})
})
}

skipif_file_darwin = pytest.mark.skipif(sys.platform.startswith('darwin'), reason='Invalid macOS filename.')
skipif_file_win32 = pytest.mark.skipif(sys.platform.startswith('win32'), reason="Invalid Windows filename.")
Expand All @@ -349,7 +359,8 @@ def make_actual_tree(tar_file):
pytest.param(backslash_base, id='Backslash', marks=skipif_file_win32),
pytest.param(backslash_quoted, id='Backslash (Quoted)', marks=skipif_file_win32),
pytest.param(non_unicode_backslash_base, id='Non-Unicode Backslash', marks=[skipif_file_win32, skipif_file_darwin]),
pytest.param(non_unicode_backslash_quoted, id='Non-Unicode Backslash (Quoted)', marks=[skipif_file_win32, skipif_file_darwin])
pytest.param(non_unicode_backslash_quoted, id='Non-Unicode Backslash (Quoted)', marks=[skipif_file_win32, skipif_file_darwin]),
pytest.param(ignore_dir, id='Ignore Directory')
])
def test_ignore(contents, tmpdir, git_env, monkeypatch):
"""
Expand Down

0 comments on commit 43f0728

Please sign in to comment.