diff --git a/acbs/base.py b/acbs/base.py index 0a20c47..a534434 100644 --- a/acbs/base.py +++ b/acbs/base.py @@ -6,7 +6,7 @@ class ACBSSourceInfo(object): - def __init__(self, type: str, url: str, revision=None, branch=None, depth=None) -> None: + def __init__(self, type: str, url: str, revision=None, branch=None, depth=None, no_gix=False) -> None: self.type = type self.url = url self.revision: Optional[str] = revision @@ -21,9 +21,10 @@ def __init__(self, type: str, url: str, revision=None, branch=None, depth=None) self.copy_repo: bool = False # this is a tristate: 0 - off; 1 - on (non-recursive); 2 - recursive self.submodule: int = 2 + self.no_gix: bool = no_gix def __repr__(self) -> str: - return ''.format(type=self.type, url=self.url, branch=self.branch, revision=self.revision, checksum=self.chksum) + return ''.format(type=self.type, url=self.url, branch=self.branch, revision=self.revision, checksum=self.chksum, no_gix=self.no_gix) class ACBSPackageInfo(object): diff --git a/acbs/fetch.py b/acbs/fetch.py index 4c14adb..53b4ede 100644 --- a/acbs/fetch.py +++ b/acbs/fetch.py @@ -119,14 +119,62 @@ def blob_processor(package: ACBSPackageInfo, index: int, source_name: str) -> No return tarball_processor_innner(package, index, source_name, False) -def git_fetch(info: ACBSSourceInfo, source_location: str, name: str) -> Optional[ACBSSourceInfo]: +def git_fetch_fallback(info: ACBSSourceInfo, source_location: str, name: str) -> Optional[ACBSSourceInfo]: + if info.no_gix: + return git_fetch(info, source_location, name) + else: + try: + # Try use gix + return gix_fetch(info, source_location, name) + except: + # Fallback to git + return git_fetch(info, source_location, name) + + +def git_fetch(info, source_location, name): full_path = os.path.join(source_location, name) if not os.path.exists(full_path): subprocess.check_call(['git', 'clone', '--bare', info.url, full_path]) else: logging.info('Updating repository...') subprocess.check_call( - ['git', 'fetch', 'origin', '+refs/heads/*:refs/heads/*', '--prune'], cwd=full_path) + ['git', 'fetch', 'origin', '+refs/heads/*:refs/heads/*', '--prune'], cwd=full_path) + info.source_location = full_path + return info + + +def gix_hack(path: str): + # FIXME: reset HEAD to the first valid branch to fix gix can't second fetch src issue. + subprocess.check_call( + ['git', 'symbolic-ref', 'HEAD', 'refs/heads/HEAD'], cwd=path) + valid_branches = subprocess.check_output( + ['git', 'branch'], cwd=path, encoding='utf-8').splitlines() + invalid: bool = True + for word in valid_branches: + word = word.strip() + if len(word) > 0: + branch: str = word + invalid = False + break + if invalid: + logging.warn( + 'No valid branches found. Falling back to traditional git.') + raise ValueError('No valid branches found') + subprocess.check_call( + ['git', 'symbolic-ref', 'HEAD', 'refs/heads/' + branch], cwd=path) + os.remove(os.path.join(path, "index")) + + +def gix_fetch(info: ACBSSourceInfo, source_location: str, name: str) -> Optional[ACBSSourceInfo]: + full_path = os.path.join(source_location, name) + if not os.path.exists(full_path): + subprocess.check_call(['gix', 'clone', '--bare', info.url, full_path]) + else: + logging.info('Updating repository with gix...') + # gix doesn't have the --prune option yet. + gix_hack(full_path) + subprocess.check_call( + ['gix', 'fetch', 'origin', '+refs/heads/*:refs/heads/*'], cwd=full_path) info.source_location = full_path return info @@ -293,7 +341,7 @@ def fossil_processor(package: ACBSPackageInfo, index: int, source_name: str) -> handlers: Dict[str, pair_signature] = { - 'GIT': (git_fetch, git_processor), + 'GIT': (git_fetch_fallback, git_processor), 'SVN': (svn_fetch, svn_processor), 'BZR': (bzr_fetch, bzr_processor), 'HG': (hg_fetch, hg_processor), diff --git a/acbs/parser.py b/acbs/parser.py index 7b58e90..46a3f4b 100644 --- a/acbs/parser.py +++ b/acbs/parser.py @@ -75,6 +75,9 @@ def parse_fetch_options(options: str, acbs_source_info: ACBSSourceInfo): if translated is None: raise ValueError(f'Invalid submodule directive: {v}') acbs_source_info.submodule = translated + elif k == 'nogix': + acbs_source_info.no_gix = v.strip() == 'true' + return acbs_source_info