From e9cc2fb4373cae8c24bab5043f24c019829ceb99 Mon Sep 17 00:00:00 2001 From: Christian Heusel Date: Fri, 2 Jun 2023 16:19:44 +0200 Subject: [PATCH] change: only require .SRCINFO in the latest revision This is done in order to relax the constraints so that dropping packages from the official repos can be done with preserving their history. Its sufficient to also have this present in the latest commit of a push. Signed-off-by: Christian Heusel --- aurweb/git/update.py | 163 +++++++++++++++++++--------------------- test/t1300-git-update.t | 4 +- 2 files changed, 80 insertions(+), 87 deletions(-) diff --git a/aurweb/git/update.py b/aurweb/git/update.py index b1256fdb..467b540f 100755 --- a/aurweb/git/update.py +++ b/aurweb/git/update.py @@ -258,6 +258,63 @@ def die_commit(msg, commit): exit(1) +def validate_metadata(metadata, commit): # noqa: C901 + try: + metadata_pkgbase = metadata["pkgbase"] + except KeyError: + die_commit( + "invalid .SRCINFO, does not contain a pkgbase (is the file empty?)", + str(commit.id), + ) + if not re.match(repo_regex, metadata_pkgbase): + die_commit("invalid pkgbase: {:s}".format(metadata_pkgbase), str(commit.id)) + + if not metadata["packages"]: + die_commit("missing pkgname entry", str(commit.id)) + + for pkgname in set(metadata["packages"].keys()): + pkginfo = srcinfo.utils.get_merged_package(pkgname, metadata) + + for field in ("pkgver", "pkgrel", "pkgname"): + if field not in pkginfo: + die_commit( + "missing mandatory field: {:s}".format(field), str(commit.id) + ) + + if "epoch" in pkginfo and not pkginfo["epoch"].isdigit(): + die_commit("invalid epoch: {:s}".format(pkginfo["epoch"]), str(commit.id)) + + if not re.match(r"[a-z0-9][a-z0-9\.+_-]*$", pkginfo["pkgname"]): + die_commit( + "invalid package name: {:s}".format(pkginfo["pkgname"]), + str(commit.id), + ) + + max_len = {"pkgname": 255, "pkgdesc": 255, "url": 8000} + for field in max_len.keys(): + if field in pkginfo and len(pkginfo[field]) > max_len[field]: + die_commit( + "{:s} field too long: {:s}".format(field, pkginfo[field]), + str(commit.id), + ) + + for field in ("install", "changelog"): + if field in pkginfo and not pkginfo[field] in commit.tree: + die_commit( + "missing {:s} file: {:s}".format(field, pkginfo[field]), + str(commit.id), + ) + + for field in extract_arch_fields(pkginfo, "source"): + fname = field["value"] + if len(fname) > 8000: + die_commit("source entry too long: {:s}".format(fname), str(commit.id)) + if "://" in fname or "lp:" in fname: + continue + if fname not in commit.tree: + die_commit("missing source file: {:s}".format(fname), str(commit.id)) + + def main(): # noqa: C901 repo = pygit2.Repository(repo_path) @@ -295,12 +352,30 @@ def main(): # noqa: C901 if sha1_old != "0" * 40: walker.hide(sha1_old) + head_commit = repo[sha1_new] + if ".SRCINFO" not in head_commit.tree: + die_commit("missing .SRCINFO", str(head_commit.id)) + + # Read .SRCINFO from the HEAD commit. + metadata_raw = repo[head_commit.tree[".SRCINFO"].id].data.decode() + (metadata, errors) = srcinfo.parse.parse_srcinfo(metadata_raw) + if errors: + sys.stderr.write( + "error: The following errors occurred " "when parsing .SRCINFO in commit\n" + ) + sys.stderr.write("error: {:s}:\n".format(str(head_commit.id))) + for error in errors: + for err in error["error"]: + sys.stderr.write("error: line {:d}: {:s}\n".format(error["line"], err)) + exit(1) + + # check if there is a correct .SRCINFO file in the latest revision + validate_metadata(metadata, head_commit) + # Validate all new commits. for commit in walker: - for fname in (".SRCINFO", "PKGBUILD"): - if fname not in commit.tree: - die_commit("missing {:s}".format(fname), str(commit.id)) - + if "PKGBUILD" not in commit.tree: + die_commit("missing PKGBUILD", str(commit.id)) for treeobj in commit.tree: blob = repo[treeobj.id] @@ -320,82 +395,6 @@ def main(): # noqa: C901 str(commit.id), ) - metadata_raw = repo[commit.tree[".SRCINFO"].id].data.decode() - (metadata, errors) = srcinfo.parse.parse_srcinfo(metadata_raw) - if errors: - sys.stderr.write( - "error: The following errors occurred " - "when parsing .SRCINFO in commit\n" - ) - sys.stderr.write("error: {:s}:\n".format(str(commit.id))) - for error in errors: - for err in error["error"]: - sys.stderr.write( - "error: line {:d}: {:s}\n".format(error["line"], err) - ) - exit(1) - - try: - metadata_pkgbase = metadata["pkgbase"] - except KeyError: - die_commit( - "invalid .SRCINFO, does not contain a pkgbase (is the file empty?)", - str(commit.id), - ) - if not re.match(repo_regex, metadata_pkgbase): - die_commit("invalid pkgbase: {:s}".format(metadata_pkgbase), str(commit.id)) - - if not metadata["packages"]: - die_commit("missing pkgname entry", str(commit.id)) - - for pkgname in set(metadata["packages"].keys()): - pkginfo = srcinfo.utils.get_merged_package(pkgname, metadata) - - for field in ("pkgver", "pkgrel", "pkgname"): - if field not in pkginfo: - die_commit( - "missing mandatory field: {:s}".format(field), str(commit.id) - ) - - if "epoch" in pkginfo and not pkginfo["epoch"].isdigit(): - die_commit( - "invalid epoch: {:s}".format(pkginfo["epoch"]), str(commit.id) - ) - - if not re.match(r"[a-z0-9][a-z0-9\.+_-]*$", pkginfo["pkgname"]): - die_commit( - "invalid package name: {:s}".format(pkginfo["pkgname"]), - str(commit.id), - ) - - max_len = {"pkgname": 255, "pkgdesc": 255, "url": 8000} - for field in max_len.keys(): - if field in pkginfo and len(pkginfo[field]) > max_len[field]: - die_commit( - "{:s} field too long: {:s}".format(field, pkginfo[field]), - str(commit.id), - ) - - for field in ("install", "changelog"): - if field in pkginfo and not pkginfo[field] in commit.tree: - die_commit( - "missing {:s} file: {:s}".format(field, pkginfo[field]), - str(commit.id), - ) - - for field in extract_arch_fields(pkginfo, "source"): - fname = field["value"] - if len(fname) > 8000: - die_commit( - "source entry too long: {:s}".format(fname), str(commit.id) - ) - if "://" in fname or "lp:" in fname: - continue - if fname not in commit.tree: - die_commit( - "missing source file: {:s}".format(fname), str(commit.id) - ) - # Display a warning if .SRCINFO is unchanged. if sha1_old not in ("0000000000000000000000000000000000000000", sha1_new): srcinfo_id_old = repo[sha1_old].tree[".SRCINFO"].id @@ -403,10 +402,6 @@ def main(): # noqa: C901 if srcinfo_id_old == srcinfo_id_new: warn(".SRCINFO unchanged. " "The package database will not be updated!") - # Read .SRCINFO from the HEAD commit. - metadata_raw = repo[repo[sha1_new].tree[".SRCINFO"].id].data.decode() - (metadata, errors) = srcinfo.parse.parse_srcinfo(metadata_raw) - # Ensure that the package base name matches the repository name. metadata_pkgbase = metadata["pkgbase"] if metadata_pkgbase != pkgbase: diff --git a/test/t1300-git-update.t b/test/t1300-git-update.t index e9d943c0..a8ea5cab 100755 --- a/test/t1300-git-update.t +++ b/test/t1300-git-update.t @@ -175,10 +175,8 @@ test_expect_success 'Removing .SRCINFO with a follow-up fix.' ' git -C aur.git commit -q -m "Remove .SRCINFO" && git -C aur.git revert --no-edit HEAD && new=$(git -C aur.git rev-parse HEAD) && - test_must_fail \ env AUR_USER=user AUR_PKGBASE=foobar AUR_PRIVILEGED=0 \ - cover "$GIT_UPDATE" refs/heads/master "$old" "$new" >actual 2>&1 && - grep -q "^error: missing .SRCINFO$" actual + cover "$GIT_UPDATE" refs/heads/master "$old" "$new" 2>&1 ' test_expect_success 'Removing PKGBUILD.' '