diff --git a/osc/commands_git/pr_dump.py b/osc/commands_git/pr_dump.py index 039b550a..d44216ec 100644 --- a/osc/commands_git/pr_dump.py +++ b/osc/commands_git/pr_dump.py @@ -40,62 +40,6 @@ class PullRequestDumpCommand(osc.commandline_git.GitObsCommand): help="Pull request ID in /# format", ).completer = complete_checkout_pr - def clone_or_update( - self, - owner: str, - repo: str, - *, - pr_number: Optional[int] = None, - branch: Optional[str] = None, - commit: str, - directory: str, - reference: Optional[str] = None, - ): - from osc import gitea_api - - if not pr_number and not branch: - raise ValueError("Either 'pr_number' or 'branch' must be specified") - - if not os.path.exists(os.path.join(directory, ".git")): - gitea_api.Repo.clone( - self.gitea_conn, - owner, - repo, - directory=directory, - add_remotes=True, - reference=reference, - ) - - git = gitea_api.Git(directory) - git_owner, git_repo = git.get_owner_repo() - assert git_owner.lower() == owner.lower(), f"owner does not match: {git_owner} != {owner}" - assert git_repo.lower() == repo.lower(), f"repo does not match: {git_repo} != {repo}" - - if pr_number: - # ``git reset`` is required for fetching the pull request into an existing branch correctly - # without it, ``git submodule status`` is broken and returns old data - git.reset() - # checkout the pull request and check if HEAD matches head/sha from Gitea - pr_branch = git.fetch_pull_request(pr_number, commit=commit, force=True) - git.switch(pr_branch) - head_commit = git.get_branch_head() - assert ( - head_commit == commit - ), f"HEAD of the current branch '{pr_branch}' is '{head_commit}' but the Gitea pull request points to '{commit}'" - elif branch: - git.switch(branch) - - # run 'git fetch' only when the branch head is different to the expected commit - head_commit = git.get_branch_head() - if head_commit != commit: - git.fetch() - - if not git.branch_contains_commit(commit=commit, remote="origin"): - raise RuntimeError(f"Branch '{branch}' doesn't contain commit '{commit}'") - git.reset(commit, hard=True) - else: - raise ValueError("Either 'pr_number' or 'branch' must be specified") - def run(self, args): import json import shutil @@ -278,11 +222,11 @@ class PullRequestDumpCommand(osc.commandline_git.GitObsCommand): base_dir = os.path.join(path, "base") # we must use the `merge_base` instead of `head_commit`, because the latter changes after merging the PR and the `base` directory would contain incorrect data - self.clone_or_update(owner, repo, branch=pr_obj.base_branch, commit=pr_obj.merge_base, directory=base_dir) + gitea_api.Repo.clone_or_update(self.gitea_conn, owner, repo, branch=pr_obj.base_branch, commit=pr_obj.merge_base, directory=base_dir) head_dir = os.path.join(path, "head") - self.clone_or_update( - owner, repo, pr_number=pr_obj.number, commit=pr_obj.head_commit, directory=head_dir, reference=base_dir + gitea_api.Repo.clone_or_update( + self.gitea_conn, owner, repo, pr_number=pr_obj.number, commit=pr_obj.head_commit, directory=head_dir, reference=base_dir ) with open(os.path.join(metadata_dir, "submodules-base.json"), "w", encoding="utf-8") as f: diff --git a/osc/gitea_api/repo.py b/osc/gitea_api/repo.py index 5aec9f82..fef1d9ff 100644 --- a/osc/gitea_api/repo.py +++ b/osc/gitea_api/repo.py @@ -196,6 +196,64 @@ class Repo(GiteaModel): return directory_abspath + @classmethod + def clone_or_update( + cls, + conn: Connection, + owner: str, + repo: str, + *, + pr_number: Optional[int] = None, + branch: Optional[str] = None, + commit: str, + directory: str, + reference: Optional[str] = None, + ): + from osc import gitea_api + + if not pr_number and not branch: + raise ValueError("Either 'pr_number' or 'branch' must be specified") + + if not os.path.exists(os.path.join(directory, ".git")): + gitea_api.Repo.clone( + conn, + owner, + repo, + directory=directory, + add_remotes=True, + reference=reference, + ) + + git = gitea_api.Git(directory) + git_owner, git_repo = git.get_owner_repo() + assert git_owner.lower() == owner.lower(), f"owner does not match: {git_owner} != {owner}" + assert git_repo.lower() == repo.lower(), f"repo does not match: {git_repo} != {repo}" + + if pr_number: + # ``git reset`` is required for fetching the pull request into an existing branch correctly + # without it, ``git submodule status`` is broken and returns old data + git.reset() + # checkout the pull request and check if HEAD matches head/sha from Gitea + pr_branch = git.fetch_pull_request(pr_number, commit=commit, force=True) + git.switch(pr_branch) + head_commit = git.get_branch_head() + assert ( + head_commit == commit + ), f"HEAD of the current branch '{pr_branch}' is '{head_commit}' but the Gitea pull request points to '{commit}'" + elif branch: + git.switch(branch) + + # run 'git fetch' only when the branch head is different to the expected commit + head_commit = git.get_branch_head() + if head_commit != commit: + git.fetch() + + if not git.branch_contains_commit(commit=commit, remote="origin"): + raise RuntimeError(f"Branch '{branch}' doesn't contain commit '{commit}'") + git.reset(commit, hard=True) + else: + raise ValueError("Either 'pr_number' or 'branch' must be specified") + @classmethod def list_org_repos(cls, conn: Connection, owner: str) -> List["Repo"]: """