From 189462259cc18e2764364b4d55ecdf153c8356db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Pi=C3=A9dallu?= Date: Fri, 16 Feb 2024 19:36:52 +0100 Subject: [PATCH] Fix autoupdater for forges allowing for non-domain-root install and multiple levels of projects --- autoupdate_app_sources/rest_api.py | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/autoupdate_app_sources/rest_api.py b/autoupdate_app_sources/rest_api.py index e780302..611544f 100644 --- a/autoupdate_app_sources/rest_api.py +++ b/autoupdate_app_sources/rest_api.py @@ -52,12 +52,19 @@ class GithubAPI: class GitlabAPI: def __init__(self, upstream: str): - split = re.search("(?Phttps?://.+)/(?P[^/]+)/(?P[^/]+)/?$", upstream) - assert split is not None - self.forge_root = split.group("host") - self.project_path = f"{split.group('group')}/{split.group('project')}" + # Find gitlab api root... + self.forge_root = self.get_forge_root(upstream) + self.project_path = upstream.replace(self.forge_root, "").lstrip("/") self.project_id = self.find_project_id(self.project_path) + def get_forge_root(self, project_url: str) -> str: + """A small heuristic based on the content of the html page...""" + r = requests.get(project_url) + r.raise_for_status() + match = re.search(r"const url = `(.*)/api/graphql`", r.text) + assert match is not None + return match.group(1) + def find_project_id(self, project: str) -> int: project = self.internal_api(f"projects/{project.replace('/', '%2F')}") assert isinstance(project, dict) @@ -119,10 +126,17 @@ class GitlabAPI: class GiteaForgejoAPI: def __init__(self, upstream: str): - split = re.search("(?Phttps?://.+)/(?P[^/]+)/(?P[^/]+)/?$", upstream) - assert split is not None - self.forge_root = split.group("host") - self.project_path = f"{split.group('group')}/{split.group('project')}" + # Find gitea/forgejo api root... + self.forge_root = self.get_forge_root(upstream) + self.project_path = upstream.replace(self.forge_root, "").lstrip("/") + + def get_forge_root(self, project_url: str) -> str: + """A small heuristic based on the content of the html page...""" + r = requests.get(project_url) + r.raise_for_status() + match = re.search(r"appUrl: '([^']*)',", r.text) + assert match is not None + return match.group(1).replace("\\", "") def internal_api(self, uri: str): url = f"{self.forge_root}/api/v1/{uri}"