def resolve_rev(self, rev): from git.exc import BadName, GitCommandError from contextlib import suppress def _resolve_rev(name): with suppress(BadName, GitCommandError): try: # Try python implementation of rev-parse first, it's faster return self.repo.rev_parse(name).hexsha except NotImplementedError: # Fall back to `git rev-parse` for advanced features return self.repo.git.rev_parse(name) # Resolve across local names sha = _resolve_rev(rev) if sha: return sha # Try all the remotes and if it resolves unambiguously then take it if not Git.is_sha(rev): shas = { _resolve_rev("{}/{}".format(remote.name, rev)) for remote in self.repo.remotes } - {None} if len(shas) > 1: raise RevError("ambiguous Git revision '{}'".format(rev)) if len(shas) == 1: return shas.pop() raise RevError("unknown Git revision '{}'".format(rev))
def checkout( self, branch: str, create_new: Optional[bool] = False, force: bool = False, **kwargs, ): from pygit2 import GIT_CHECKOUT_FORCE, GitError checkout_strategy = GIT_CHECKOUT_FORCE if force else None if create_new: commit = self.repo.revparse_single("HEAD") new_branch = self.repo.branches.local.create(branch, commit) self.repo.checkout(new_branch, strategy=checkout_strategy) else: if branch == "-": branch = "@{-1}" try: commit, ref = self.repo.resolve_refish(branch) except (KeyError, GitError): raise RevError(f"unknown Git revision '{branch}'") self.repo.checkout_tree(commit, strategy=checkout_strategy) detach = kwargs.get("detach", False) if ref and not detach: self.repo.set_head(ref.name) else: self.repo.set_head(commit.id)
def resolve_rev(self, rev): from git.exc import GitCommandError try: return self.repo.git.rev_parse(rev) except GitCommandError: raise RevError("unknown Git revision '{}'".format(rev))
def _resolve_rev(name): with suppress(BadName, GitCommandError): try: # Try python implementation of rev-parse first, it's faster return self.repo.rev_parse(name).hexsha except NotImplementedError: # Fall back to `git rev-parse` for advanced features return self.repo.git.rev_parse(name) except ValueError: raise RevError(f"unknown Git revision '{name}'")
def resolve_rev(self, rev: str) -> str: from pygit2 import GitError try: commit, _ref = self.repo.resolve_refish(rev) return str(commit.id) except (KeyError, GitError): pass # Look for single exact match in remote refs shas = { self.get_ref(f"refs/remotes/{remote.name}/{rev}") for remote in self.repo.remotes } - {None} if len(shas) > 1: raise RevError(f"ambiguous Git revision '{rev}'") if len(shas) == 1: return shas.pop() # type: ignore raise RevError(f"unknown Git revision '{rev}'")
def clone( url: str, to_path: str, rev: Optional[str] = None, shallow_branch: Optional[str] = None, ): import git ld_key = "LD_LIBRARY_PATH" env = fix_env(None) if is_binary() and ld_key not in env.keys(): # In fix_env, we delete LD_LIBRARY_PATH key if it was empty before # PyInstaller modified it. GitPython, in git.Repo.clone_from, uses # env to update its own internal state. When there is no key in # env, this value is not updated and GitPython re-uses # LD_LIBRARY_PATH that has been set by PyInstaller. # See [1] for more info. # [1] https://github.com/gitpython-developers/GitPython/issues/924 env[ld_key] = "" try: if shallow_branch is not None and os.path.exists(url): # git disables --depth for local clones unless file:// url # scheme is used url = f"file://{url}" with TqdmGit(desc="Cloning", unit="obj") as pbar: clone_from = partial( git.Repo.clone_from, url, to_path, env=env, # needed before we can fix it in __init__ no_single_branch=True, progress=pbar.update_git, ) if shallow_branch is None: tmp_repo = clone_from() else: tmp_repo = clone_from(branch=shallow_branch, depth=1) tmp_repo.close() except git.exc.GitCommandError as exc: # pylint: disable=no-member raise CloneError(url, to_path) from exc # NOTE: using our wrapper to make sure that env is fixed in __init__ repo = GitPythonBackend(to_path) if rev: try: repo.checkout(rev) except git.exc.GitCommandError as exc: # pylint: disable=no-member raise RevError( "failed to access revision '{}' for repo '{}'".format( rev, url ) ) from exc
def resolve_rev(self, rev: str) -> str: from dvc.repo.experiments.utils import exp_refs_by_name try: return self._resolve_rev(rev) except RevError: # backends will only resolve git branch and tag names, # if rev is not a sha it may be an abbreviated experiment name if not self.is_sha(rev) and not rev.startswith("refs/"): ref_infos = list(exp_refs_by_name(self, rev)) if len(ref_infos) == 1: return self.get_ref(str(ref_infos[0])) if len(ref_infos) > 1: raise RevError(f"ambiguous Git revision '{rev}'") raise
def clone(url, to_path, rev=None): import git ld_key = "LD_LIBRARY_PATH" env = fix_env(None) if is_binary() and ld_key not in env.keys(): # In fix_env, we delete LD_LIBRARY_PATH key if it was empty before # PyInstaller modified it. GitPython, in git.Repo.clone_from, uses # env to update its own internal state. When there is no key in # env, this value is not updated and GitPython re-uses # LD_LIBRARY_PATH that has been set by PyInstaller. # See [1] for more info. # [1] https://github.com/gitpython-developers/GitPython/issues/924 env[ld_key] = "" try: with TqdmGit(desc="Cloning", unit="obj") as pbar: tmp_repo = git.Repo.clone_from( url, to_path, env=env, # needed before we can fix it in __init__ no_single_branch=True, progress=pbar.update_git, ) tmp_repo.close() except git.exc.GitCommandError as exc: # pylint: disable=no-member raise CloneError(url, to_path) from exc # NOTE: using our wrapper to make sure that env is fixed in __init__ repo = Git(to_path) if rev: try: repo.checkout(rev) except git.exc.GitCommandError as exc: # pylint: disable=no-member raise RevError( "failed to access revision '{}' for repo '{}'".format( rev, url ) ) from exc return repo
def clone(url, to_path, rev=None): import git ld_key = "LD_LIBRARY_PATH" env = fix_env(None) if is_binary() and ld_key not in env.keys(): # In fix_env, we delete LD_LIBRARY_PATH key if it was empty before # PyInstaller modified it. GitPython, in git.Repo.clone_from, uses # env to update its own internal state. When there is no key in # env, this value is not updated and GitPython re-uses # LD_LIBRARY_PATH that has been set by PyInstaller. # See [1] for more info. # [1] https://github.com/gitpython-developers/GitPython/issues/924 env[cast_bytes_py2(ld_key)] = "" try: tmp_repo = git.Repo.clone_from( url, to_path, env=env, # needed before we can fix it in __init__ no_single_branch=True, ) tmp_repo.close() except git.exc.GitCommandError as exc: raise CloneError(url, to_path, exc) # NOTE: using our wrapper to make sure that env is fixed in __init__ repo = Git(to_path) if rev: try: repo.checkout(rev) except git.exc.GitCommandError as exc: raise RevError(url, rev, exc) return repo
def clone(url, to_path, rev=None): import git try: tmp_repo = git.Repo.clone_from( url, to_path, env=fix_env(None), # needed before we can fix it in __init__ no_single_branch=True, ) tmp_repo.close() except git.exc.GitCommandError as exc: raise CloneError(url, to_path, exc) # NOTE: using our wrapper to make sure that env is fixed in __init__ repo = Git(to_path) if rev: try: repo.checkout(rev) except git.exc.GitCommandError as exc: raise RevError(url, rev, exc) return repo