From 28df74b7c9ce9d104fa803032322d4bb10bda7dc Mon Sep 17 00:00:00 2001 From: Ilya Kulakov Date: Fri, 4 Dec 2020 18:33:51 +0600 Subject: [PATCH] Use git to get list of submodules Parsing .gitmodules may yield paths that are ignored by git. Refs #85 --- git_archive_all.py | 55 ++++++++++++++++++++++++++++----------------- git_archive_all.pyi | 5 ++++- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/git_archive_all.py b/git_archive_all.py index 5ace362..8e58744 100755 --- a/git_archive_all.py +++ b/git_archive_all.py @@ -345,30 +345,19 @@ def walk_git_files(self, repo_path=fspath('')): self.run_git_shell('git submodule init', repo_abspath) self.run_git_shell('git submodule update', repo_abspath) - try: - repo_gitmodules_abspath = path.join(repo_abspath, fspath(".gitmodules")) - - with open(repo_gitmodules_abspath) as f: - lines = f.readlines() - - for l in lines: - m = re.match("^\\s*path\\s*=\\s*(.*)\\s*$", l) + for repo_submodule_path in self.list_repo_submodules(repo_abspath): # relative to repo_path + if self.is_file_excluded(repo_abspath, repo_submodule_path): + continue - if m: - repo_submodule_path = fspath(m.group(1)) # relative to repo_path - main_repo_submodule_path = path.join(repo_path, repo_submodule_path) # relative to main_repo_abspath + main_repo_submodule_path = path.join(repo_path, repo_submodule_path) # relative to main_repo_abspath - if self.is_file_excluded(repo_abspath, repo_submodule_path): - continue + for main_repo_submodule_file_path in self.walk_git_files(main_repo_submodule_path): + repo_submodule_file_path = path.relpath(main_repo_submodule_file_path, repo_path) # relative to repo_path - for main_repo_submodule_file_path in self.walk_git_files(main_repo_submodule_path): - repo_submodule_file_path = path.relpath(main_repo_submodule_file_path, repo_path) # relative to repo_path - if self.is_file_excluded(repo_abspath, repo_submodule_file_path): - continue + if self.is_file_excluded(repo_abspath, repo_submodule_file_path): + continue - yield main_repo_submodule_file_path - except IOError: - pass + yield main_repo_submodule_file_path finally: self._check_attr_gens[repo_abspath].close() del self._check_attr_gens[repo_abspath] @@ -538,6 +527,9 @@ def get_git_version(cls): @classmethod def list_repo_files(cls, repo_abspath): + """ + Return a list of all files as seen by git in a given repo. + """ repo_file_paths = cls.run_git_shell( 'git ls-files -z --cached --full-name --no-empty-directory', cwd=repo_abspath @@ -551,6 +543,29 @@ def list_repo_files(cls, repo_abspath): return repo_file_paths + @classmethod + def list_repo_submodules(cls, repo_abspath): + """ + Return a list of all direct submodules as seen by git in a given repo. + """ + if sys.platform.startswith('win32'): + shell_command = 'git submodule foreach --quiet "\\"{0}\\" -c \\"from __future__ import print_function; print(\'"$sm_path"\', end=chr(0))\\""' + else: + shell_command = 'git submodule foreach --quiet \'"{0}" -c "from __future__ import print_function; print(\\"$sm_path\\", end=chr(0))"\'' + + python_exe = sys.executable or 'python' + shell_command = shell_command.format(python_exe) + + repo_submodule_paths = cls.run_git_shell(shell_command, cwd=repo_abspath) + repo_submodule_paths = repo_submodule_paths.split(b'\0')[:-1] + + if sys.platform.startswith('win32'): + repo_submodule_paths = (git_fspath(p.replace(b'/', b'\\')) for p in repo_submodule_paths) + else: + repo_submodule_paths = map(git_fspath, repo_submodule_paths) + + return repo_submodule_paths + def main(argv=None): if argv is None: diff --git a/git_archive_all.pyi b/git_archive_all.pyi index 28733b9..710c1ea 100644 --- a/git_archive_all.pyi +++ b/git_archive_all.pyi @@ -64,4 +64,7 @@ class GitArchiver(object): def get_git_version(cls) -> Optional[Tuple[int]]: ... @classmethod - def list_repo_files(cls, repo_abspath: PathStr) -> Generator[PathStr, None, None]: ... \ No newline at end of file + def list_repo_files(cls, repo_abspath: PathStr) -> Generator[PathStr, None, None]: ... + + @classmethod + def list_repo_submodules(cls, repo_abspath: PathStr) -> Generator[PathStr, None, None]: ...