1
0
mirror of https://github.com/openSUSE/osc.git synced 2025-11-26 14:39:50 +01:00

Move clone_or_update() from 'git-obs pr dump' command to gitea_api.Repo

This commit is contained in:
2025-10-15 14:28:31 +02:00
parent 08ad0319c6
commit 089ad90fae
2 changed files with 61 additions and 59 deletions

View File

@@ -40,62 +40,6 @@ class PullRequestDumpCommand(osc.commandline_git.GitObsCommand):
help="Pull request ID in <owner>/<repo>#<number> format", help="Pull request ID in <owner>/<repo>#<number> format",
).completer = complete_checkout_pr ).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): def run(self, args):
import json import json
import shutil import shutil
@@ -278,11 +222,11 @@ class PullRequestDumpCommand(osc.commandline_git.GitObsCommand):
base_dir = os.path.join(path, "base") 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 # 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") head_dir = os.path.join(path, "head")
self.clone_or_update( gitea_api.Repo.clone_or_update(
owner, repo, pr_number=pr_obj.number, commit=pr_obj.head_commit, directory=head_dir, reference=base_dir 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: with open(os.path.join(metadata_dir, "submodules-base.json"), "w", encoding="utf-8") as f:

View File

@@ -196,6 +196,64 @@ class Repo(GiteaModel):
return directory_abspath 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 @classmethod
def list_org_repos(cls, conn: Connection, owner: str) -> List["Repo"]: def list_org_repos(cls, conn: Connection, owner: str) -> List["Repo"]:
""" """