1
0
mirror of https://github.com/openSUSE/osc.git synced 2024-11-12 23:56:13 +01:00

Add 'fork' command for forking packages managed in Git

Requires [apiurl]/gitea_auth_token config option.
This commit is contained in:
Daniel Mach 2024-05-14 14:26:14 +02:00
parent 3e1e5e366a
commit 0969d99c46
2 changed files with 90 additions and 0 deletions

63
osc/commands/fork.py Normal file
View File

@ -0,0 +1,63 @@
import osc.commandline
class ForkCommand(osc.commandline.OscCommand):
"""
Fork a package that is managed in Git
"""
name = "fork"
def init_arguments(self):
self.add_argument(
"project",
help="Name of the project",
)
self.add_argument(
"package",
help="Name of the package",
)
def run(self, args):
import urllib.parse
from osc import conf as osc_conf
from osc import gitea_api
from osc import obs_api
from osc.output import print_msg
auth_token = osc_conf.config.api_host_options[args.apiurl].get("gitea_auth_token", None)
if not auth_token:
raise RuntimeError(f"Option 'gitea_auth_token' is not configured for apiurl '{args.apiurl}'")
package = obs_api.Package.from_api(args.apiurl, args.project, args.package)
if not package.scmsync:
raise RuntimeError("Forking is possibly only with packages managed in Git (the <scmsync> element must be set in the package meta)")
parsed_scmsync_url = urllib.parse.urlparse(package.scmsync, scheme="https")
url = urllib.parse.urlunparse((parsed_scmsync_url.scheme, parsed_scmsync_url.netloc, "", "", "", ""))
owner, repo = parsed_scmsync_url.path.strip("/").split("/")
branch = parsed_scmsync_url.fragment or None
gitea = gitea_api.GiteaConnection(url, auth_token=auth_token)
try:
_, reply = gitea.fork(owner, repo)
fork_owner = reply["owner"]["name"]
fork_repo = reply["name"]
except gitea_api.GiteaForkExists as e:
fork_owner = e.owner
fork_repo = e.repo
print_msg(f"Re-using an existing fork: {fork_owner}/{fork_repo}", print_to="debug")
# TODO: branch package if `branch` is set?
# or just print a message?
# if the package was forked a long time ago, the branches might be outdated and we need the user to set a remote and branch the right contents
# TODO: use urlunparse()
scmsync = f"{url}/{fork_owner}/{fork_repo}"
if branch:
scmsync += "#" + branch
obs_api.Package.cmd_fork(args.apiurl, args.project, args.package, scmsync=scmsync)

View File

@ -86,6 +86,33 @@ class Package(XmlModel):
response = self.xml_request("PUT", apiurl, url_path, url_query, data=self.to_string())
return Status.from_file(response, apiurl=apiurl)
@classmethod
def cmd_fork(
cls,
apiurl: str,
project: str,
package: str,
*,
scmsync: str,
):
"""
POST /source/{project}/{package}?cmd=fork&scmsync={scmsync}
For a package managed in Git.
:param apiurl: Full apiurl or its alias.
:param project: Project name.
:param package: Package name.
:param scmsync: Checkout Git URL. Example: https://src.example.com/owner/repo#branch
"""
url_path = ["source", project, package]
url_query = {
"cmd": "fork",
"scmsync": scmsync,
}
response = cls.xml_request("POST", apiurl, url_path, url_query)
return Status.from_file(response, apiurl=apiurl)
@classmethod
def cmd_release(
cls,