From 9abb716e48d133fcd63320699abac79ca7382e82 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 21 Nov 2025 21:41:16 +0100 Subject: [PATCH] lint: check git/srclib Repo URLs for proper format --- fdroidserver/lint.py | 20 +++++++++++++++- tests/test_lint.py | 57 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/fdroidserver/lint.py b/fdroidserver/lint.py index c775f342..853bab52 100644 --- a/fdroidserver/lint.py +++ b/fdroidserver/lint.py @@ -142,7 +142,6 @@ http_checks = ( regex_checks = { 'WebSite': http_checks, 'SourceCode': http_checks, - 'Repo': https_enforcings, 'UpdateCheckMode': https_enforcings, 'IssueTracker': http_checks + [ @@ -821,6 +820,24 @@ def check_certificate_pinned_binaries(app): return +REPO_GIT_URL = re.compile(r'^https://.*') +REPO_SRCLIB_URL = re.compile(r'^[^/@]+$') + + +def check_repo(app): + """Check Repo: has acceptable URLs.""" + repo = app['Repo'] + if app['RepoType'] == 'git' and not REPO_GIT_URL.match(repo): + yield _('Repo: git URLs must use https://') + if app['RepoType'] == 'srclib': + m = REPO_SRCLIB_URL.match(repo) + if not m: + yield _('Repo: srclib URLs must be only a srclib name, not a path or URL.') + srclib = f'srclibs/{repo}.yml' + if not Path(srclib).exists(): + yield _('Repo: srclib URLs must be the name of an existing srclib!') + + def lint_config(arg): path = Path(arg) passed = True @@ -1062,6 +1079,7 @@ def lint_metadata(options): check_updates_expected, check_updates_ucm_http_aum_pattern, check_certificate_pinned_binaries, + check_repo, ] for check_func in app_check_funcs: diff --git a/tests/test_lint.py b/tests/test_lint.py index bc947ee2..a3535feb 100755 --- a/tests/test_lint.py +++ b/tests/test_lint.py @@ -123,6 +123,63 @@ class LintTest(SetUpTearDownMixin, unittest.TestCase): logging.debug(warn) self.assertTrue(anywarns, url + " does not fail lint!") + def test_check_repo_git_good(self): + app = {'RepoType': 'git'} + good_git_urls = [ + 'https://github.com/Matteljay/mastermindy-android', + 'https://gitlab.com/origin/master.git', + 'https://gitlab.com/group/subgroup/masterthing', + 'https://git.ieval.ro/?p=fonbot.git;a=blob;f=Changes;hb=HEAD', + ] + + anywarns = False + for url in good_git_urls: + app['Repo'] = url + for warn in fdroidserver.lint.check_repo(app): + anywarns = True + logging.debug(warn) + self.assertFalse(anywarns) + + def test_check_repo_git_bad(self): + app = {'RepoType': 'git'} + bad_urls = ['github.com/my/proj', 'http://github.com/not/secure'] + for url in bad_urls: + anywarns = False + app['Repo'] = url + for warn in fdroidserver.lint.check_repo(app): + anywarns = True + self.assertTrue(anywarns, url + " does not fail lint!") + + def test_check_repo_srclib_good(self): + os.chdir(self.testdir) + testname = 'wireguard-tools' + testfile = Path(f'srclibs/{testname}.yml') + testfile.parent.mkdir() + testfile.write_text('test') + app = {'RepoType': 'srclib', 'Repo': testname} + anywarns = False + for warn in fdroidserver.lint.check_repo(app): + anywarns = True + logging.debug(warn) + self.assertFalse(anywarns) + + def test_check_repo_srclib_file_missing(self): + os.chdir(self.testdir) + app = {'RepoType': 'srclib', 'Repo': 'nosrclibsymlfile'} + for warn in fdroidserver.lint.check_repo(app): + anywarns = True + self.assertTrue(anywarns) + + def test_check_repo_srclib_bad(self): + bad_urls = ['github.com/my/proj', 'https://github.com/not/secure'] + for url in bad_urls: + anywarns = False + app = {'RepoType': 'srclib', 'Repo': url} + for warn in fdroidserver.lint.check_repo(app): + anywarns = True + logging.debug(warn) + self.assertTrue(anywarns, f"{url} does not fail lint!") + def test_check_app_field_types(self): config = dict() fdroidserver.common.fill_config_defaults(config)