Skip to content

Commit

Permalink
frontend: move repo functions to a separate file
Browse files Browse the repository at this point in the history
To avoid circular dependencies when we introduce some database queries
to them.
  • Loading branch information
FrostyX committed Oct 15, 2024
1 parent 05511d9 commit c8ff8d3
Show file tree
Hide file tree
Showing 8 changed files with 277 additions and 242 deletions.
133 changes: 1 addition & 132 deletions frontend/coprs_frontend/coprs/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
import random
import string
import json
import posixpath
import re
from os.path import normpath
from urllib.parse import urlparse, parse_qs, urlunparse, urlencode
from urllib.parse import urlparse, urlencode

import html5_parser

Expand Down Expand Up @@ -337,32 +336,6 @@ def parse_package_name(pkg):
return pkg


def generate_repo_url(mock_chroot, url, arch=None):
""" Generates url with build results for .repo file.
No checks if copr or mock_chroot exists.
"""
os_version = mock_chroot.os_version

if mock_chroot.os_release == "fedora":
os_version = "$releasever"

if mock_chroot.os_release == "centos-stream":
os_version = "$releasever"

if mock_chroot.os_release == "opensuse-leap":
os_version = "$releasever"

if mock_chroot.os_release == "mageia":
if mock_chroot.os_version != "cauldron":
os_version = "$releasever"

url = posixpath.join(
url, "{0}-{1}-{2}/".format(mock_chroot.os_release,
os_version, arch or '$basearch'))

return url


def fix_protocol_for_backend(url):
"""
Ensure that url either has http or https protocol according to the
Expand Down Expand Up @@ -585,70 +558,6 @@ def stream_template(template_name, **context):
return rv


def generate_repo_name(repo_url):
""" based on url, generate repo name """
repo_url = re.sub("[^a-zA-Z0-9]", '_', repo_url)
repo_url = re.sub("(__*)", '_', repo_url)
repo_url = re.sub("(_*$)|^_*", '', repo_url)
return repo_url


def is_copr_repo(repo_url):
return copr_repo_fullname(repo_url) is not None


def copr_repo_fullname(repo_url):
parsed_url = urlparse(repo_url)
query = parse_qs(parsed_url.query)
if parsed_url.scheme != "copr":
return None
return parsed_url.netloc + parsed_url.path


def pre_process_repo_url(chroot, repo_url):
"""
Expands variables and sanitize repo url to be used for mock config
"""
parsed_url = urlparse(repo_url)
query = parse_qs(parsed_url.query)

if parsed_url.scheme == "copr":
user = parsed_url.netloc
prj = parsed_url.path.split("/")[1]
repo_url = "/".join([
flask.current_app.config["BACKEND_BASE_URL"],
"results", user, prj, chroot
]) + "/"

elif "priority" in query:
query.pop("priority")
query_string = urlencode(query, doseq=True)
parsed_url = parsed_url._replace(query=query_string)
repo_url = urlunparse(parsed_url)

repo_url = repo_url.replace("$chroot", chroot)
repo_url = repo_url.replace("$distname", chroot.rsplit("-", 2)[0])
return repo_url


def parse_repo_params(repo, supported_keys=None):
"""
:param repo: str repo from Copr/CoprChroot/Build/...
:param supported_keys list of supported optional parameters
:return: dict of optional parameters parsed from the repo URL
"""
supported_keys = supported_keys or ["priority"]
params = {}
qs = parse_qs(urlparse(repo).query)
for k, v in qs.items():
if k in supported_keys:
# parse_qs returns values as lists, but we allow setting the param only once,
# so we can take just first value from it
value = int(v[0]) if v[0].isnumeric() else v[0]
params[k] = value
return params


def trim_git_url(url):
if not url:
return None
Expand Down Expand Up @@ -891,43 +800,3 @@ def being_server_admin(user, copr):
return False

return True


def generate_repo_id_and_name(copr, copr_dir_name, multilib=False, dep_idx=None,
dependent=None):
"""
Return (repo_id, repo_name) for a given copr. If multilib is True, the
rpeo_id has a specific suffix, if the repo is dependency of the dependend,
the repo_id has a specific prefix.
"""
repo_id = "{0}:{1}:{2}:{3}{4}".format(
"coprdep" if dep_idx else "copr",
app.config["PUBLIC_COPR_HOSTNAME"].split(":")[0],
copr.owner_name.replace("@", "group_"),
copr_dir_name,
":ml" if multilib else ""
)

if dep_idx and dependent:
name = "Copr {0}/{1}/{2} runtime dependency #{3} - {4}/{5}".format(
app.config["PUBLIC_COPR_HOSTNAME"].split(":")[0],
dependent.owner_name, dependent.name, dep_idx,
copr.owner_name, copr_dir_name
)
else:
name = "Copr repo for {0} owned by {1}".format(copr_dir_name,
copr.owner_name)
return repo_id, name

def generate_repo_id_and_name_ext(dependent, url, dep_idx):
"""
Return (repo_id, repo_name) pair according to the repo URL and what
DEPENDENT repository we depend on.
"""
repo_id = "coprdep:{0}".format(generate_repo_name(url))
name = "Copr {0}/{1}/{2} external runtime dependency #{3} - {4}".format(
app.config["PUBLIC_COPR_HOSTNAME"].split(":")[0],
dependent.owner_name, dependent.name, dep_idx,
generate_repo_name(url),
)
return repo_id, name
16 changes: 11 additions & 5 deletions frontend/coprs_frontend/coprs/logic/complex_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
from coprs import cache
from coprs.constants import DEFAULT_COPR_REPO_PRIORITY
from coprs.exceptions import ObjectNotFound
from coprs.repos import (
copr_repo_fullname,
parse_repo_params,
generate_repo_name,
pre_process_repo_url,
)
from coprs.logic.builds_logic import BuildsLogic
from coprs.logic.batches_logic import BatchesLogic
from coprs.logic.packages_logic import PackagesLogic
Expand Down Expand Up @@ -247,7 +253,7 @@ def get_copr_by_repo(repo_url):
ObjectNotFound to the API if no such Copr (group) result was found
in database.
"""
copr_repo = helpers.copr_repo_fullname(repo_url)
copr_repo = copr_repo_fullname(repo_url)
if not copr_repo:
return None
try:
Expand Down Expand Up @@ -667,11 +673,11 @@ def get_build_isolation(cls, build_config, build):
def get_additional_repo_views(cls, repos_list, chroot_id):
repos = []
for repo in repos_list:
params = helpers.parse_repo_params(repo)
params = parse_repo_params(repo)
repo_view = {
"id": helpers.generate_repo_name(repo),
"baseurl": helpers.pre_process_repo_url(chroot_id, repo),
"name": "Additional repo " + helpers.generate_repo_name(repo),
"id": generate_repo_name(repo),
"baseurl": pre_process_repo_url(chroot_id, repo),
"name": "Additional repo " + generate_repo_name(repo),
}

# We ask get_copr_by_repo() here only to resolve the
Expand Down
146 changes: 146 additions & 0 deletions frontend/coprs_frontend/coprs/repos.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
"""
External repositories helper functions
"""


import re
import posixpath
from urllib.parse import urlparse, parse_qs, urlunparse, urlencode
import flask
from coprs import app


def generate_repo_url(mock_chroot, url, arch=None):
""" Generates url with build results for .repo file.
No checks if copr or mock_chroot exists.
"""
os_version = mock_chroot.os_version

if mock_chroot.os_release == "fedora":
os_version = "$releasever"

if mock_chroot.os_release == "centos-stream":
os_version = "$releasever"

if mock_chroot.os_release == "opensuse-leap":
os_version = "$releasever"

if mock_chroot.os_release == "mageia":
if mock_chroot.os_version != "cauldron":
os_version = "$releasever"

url = posixpath.join(
url, "{0}-{1}-{2}/".format(mock_chroot.os_release,
os_version, arch or '$basearch'))

return url


def generate_repo_name(repo_url):
""" based on url, generate repo name """
repo_url = re.sub("[^a-zA-Z0-9]", '_', repo_url)
repo_url = re.sub("(__*)", '_', repo_url)
repo_url = re.sub("(_*$)|^_*", '', repo_url)
return repo_url


def is_copr_repo(repo_url):
"""
Is the repository in the copr://foo/bar format?
"""
return copr_repo_fullname(repo_url) is not None


def copr_repo_fullname(repo_url):
"""
For a copr://foo/bar repository, return foo/bar
"""
parsed_url = urlparse(repo_url)
if parsed_url.scheme != "copr":
return None
return parsed_url.netloc + parsed_url.path


def pre_process_repo_url(chroot, repo_url):
"""
Expands variables and sanitize repo url to be used for mock config
"""
parsed_url = urlparse(repo_url)
query = parse_qs(parsed_url.query)

if parsed_url.scheme == "copr":
user = parsed_url.netloc
prj = parsed_url.path.split("/")[1]
repo_url = "/".join([
flask.current_app.config["BACKEND_BASE_URL"],
"results", user, prj, chroot
]) + "/"

elif "priority" in query:
query.pop("priority")
query_string = urlencode(query, doseq=True)
parsed_url = parsed_url._replace(query=query_string)
repo_url = urlunparse(parsed_url)

repo_url = repo_url.replace("$chroot", chroot)
repo_url = repo_url.replace("$distname", chroot.rsplit("-", 2)[0])
return repo_url


def parse_repo_params(repo, supported_keys=None):
"""
:param repo: str repo from Copr/CoprChroot/Build/...
:param supported_keys list of supported optional parameters
:return: dict of optional parameters parsed from the repo URL
"""
supported_keys = supported_keys or ["priority"]
params = {}
qs = parse_qs(urlparse(repo).query)
for k, v in qs.items():
if k in supported_keys:
# parse_qs returns values as lists, but we allow setting the param only once,
# so we can take just first value from it
value = int(v[0]) if v[0].isnumeric() else v[0]
params[k] = value
return params


def generate_repo_id_and_name(copr, copr_dir_name, multilib=False, dep_idx=None,
dependent=None):
"""
Return (repo_id, repo_name) for a given copr. If multilib is True, the
rpeo_id has a specific suffix, if the repo is dependency of the dependend,
the repo_id has a specific prefix.
"""
repo_id = "{0}:{1}:{2}:{3}{4}".format(
"coprdep" if dep_idx else "copr",
app.config["PUBLIC_COPR_HOSTNAME"].split(":")[0],
copr.owner_name.replace("@", "group_"),
copr_dir_name,
":ml" if multilib else ""
)

if dep_idx and dependent:
name = "Copr {0}/{1}/{2} runtime dependency #{3} - {4}/{5}".format(
app.config["PUBLIC_COPR_HOSTNAME"].split(":")[0],
dependent.owner_name, dependent.name, dep_idx,
copr.owner_name, copr_dir_name
)
else:
name = "Copr repo for {0} owned by {1}".format(copr_dir_name,
copr.owner_name)
return repo_id, name


def generate_repo_id_and_name_ext(dependent, url, dep_idx):
"""
Return (repo_id, repo_name) pair according to the repo URL and what
DEPENDENT repository we depend on.
"""
repo_id = "coprdep:{0}".format(generate_repo_name(url))
name = "Copr {0}/{1}/{2} external runtime dependency #{3} - {4}".format(
app.config["PUBLIC_COPR_HOSTNAME"].split(":")[0],
dependent.owner_name, dependent.name, dep_idx,
generate_repo_name(url),
)
return repo_id, name
6 changes: 4 additions & 2 deletions frontend/coprs_frontend/coprs/views/apiv3_ns/apiv3_rpmrepo.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@
from coprs.logic.complex_logic import ReposLogic
from coprs.logic.stat_logic import CounterStatLogic
from coprs.helpers import (
generate_repo_id_and_name,
generate_repo_id_and_name_ext,
get_stat_name,
CounterStatType,
)
from coprs.repos import (
generate_repo_id_and_name,
generate_repo_id_and_name_ext,
)


apiv3_rpmrepo_ns = Namespace("rpmrepo", description="RPM Repo")
Expand Down
Loading

0 comments on commit c8ff8d3

Please sign in to comment.