Skip to content

Commit 09559c0

Browse files
committed
GitPkgCommitsCheck: catch SRC_URI mistakes
Resolves: #493 Signed-off-by: Arthur Zamarin <arthurzam@gentoo.org>
1 parent 086e4eb commit 09559c0

2 files changed

Lines changed: 120 additions & 2 deletions

File tree

src/pkgcheck/checks/git.py

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313

1414
from pkgcore.ebuild.misc import sort_keywords
1515
from pkgcore.ebuild.repository import UnconfiguredTree
16+
from pkgcore.fetch import fetchable
1617
from snakeoil import klass
1718
from snakeoil.mappings import ImmutableDict
1819
from snakeoil.osutils import pjoin
20+
from snakeoil.sequences import iflatten_instance
1921
from snakeoil.strings import pluralism
2022

2123
from .. import base, results, sources
@@ -169,6 +171,38 @@ def desc(self):
169171
return f"renamed package: {self.old} -> {self.new}"
170172

171173

174+
class SrcUriChecksumChange(results.PackageResult, results.Error):
175+
"""SRC_URI changing checksum without distfile rename."""
176+
177+
def __init__(self, filename, **kwargs):
178+
super().__init__(**kwargs)
179+
self.filename = filename
180+
181+
@property
182+
def desc(self):
183+
return f"{self.filename!r} has different checksums across commits"
184+
185+
186+
class SuspiciousSrcUriChange(results.PackageResult, results.Warning):
187+
"""Suspicious SRC_URI changing URI without distfile rename."""
188+
189+
def __init__(self, old_uri, new_uri, filename, **kwargs):
190+
super().__init__(**kwargs)
191+
if isinstance(old_uri, tuple):
192+
self.old_uri = f"mirror://{old_uri[0].mirror_name}/{old_uri[1]}"
193+
else:
194+
self.old_uri = str(old_uri)
195+
if isinstance(new_uri, tuple):
196+
self.new_uri = f"mirror://{new_uri[0].mirror_name}/{new_uri[1]}"
197+
else:
198+
self.new_uri = str(new_uri)
199+
self.filename = filename
200+
201+
@property
202+
def desc(self):
203+
return f"{self.filename!r} has changed SRC_URI from {self.old_uri!r} to {self.new_uri!r}"
204+
205+
172206
class _RemovalRepo(UnconfiguredTree):
173207
"""Repository of removed packages stored in a temporary directory."""
174208

@@ -235,6 +269,8 @@ class GitPkgCommitsCheck(GentooRepoCheck, GitCommitsCheck):
235269
DroppedUnstableKeywords,
236270
MissingSlotmove,
237271
MissingMove,
272+
SrcUriChecksumChange,
273+
SuspiciousSrcUriChange,
238274
]
239275
)
240276

@@ -345,7 +381,34 @@ def modified_checks(self, pkgs):
345381
else:
346382
yield MissingSlotmove(old_slot, new_slot, pkg=new_pkg)
347383

348-
def feed(self, pkgset):
384+
def src_uri_changes(self, pkgset):
385+
pkg = pkgset[0].unversioned_atom
386+
387+
try:
388+
new_checksums = {
389+
fetch.filename: (fetch.chksums, tuple(fetch.uri._uri_source))
390+
for pkg in self.repo.match(pkg)
391+
for fetch in iflatten_instance(pkg.fetchables, fetchable)
392+
}
393+
394+
old_checksums = {
395+
fetch.filename: (fetch.chksums, tuple(fetch.uri._uri_source))
396+
for pkg in self.modified_repo(pkgset).match(pkg)
397+
for fetch in iflatten_instance(pkg.fetchables, fetchable)
398+
}
399+
except (IndexError, FileNotFoundError, tarfile.ReadError):
400+
# ignore broken ebuild
401+
return
402+
403+
for filename in old_checksums.keys() & new_checksums.keys():
404+
old_checksum, old_uri = old_checksums[filename]
405+
new_checksum, new_uri = new_checksums[filename]
406+
if old_checksum != new_checksum:
407+
yield SrcUriChecksumChange(filename, pkg=pkg)
408+
elif old_uri != new_uri:
409+
yield SuspiciousSrcUriChange(old_uri[0], new_uri[0], filename, pkg=pkg)
410+
411+
def feed(self, pkgset: list[git.GitPkgChange]):
349412
# Mapping of commit types to pkgs, available commit types can be seen
350413
# under the --diff-filter option in git log parsing support and are
351414
# disambiguated as follows:
@@ -407,6 +470,8 @@ def feed(self, pkgset):
407470
if not pkg.maintainers and newly_added:
408471
yield DirectNoMaintainer(pkg=pkg)
409472

473+
yield from self.src_uri_changes(pkgset)
474+
410475

411476
class MissingSignOff(results.CommitResult, results.Error):
412477
"""Local commit with missing sign offs.

tests/checks/test_git.py

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from pkgcheck.base import PkgcheckUserException
88
from pkgcheck.checks import git as git_mod
99
from pkgcheck.addons.git import GitCommit
10-
from pkgcore.ebuild.cpv import VersionedCPV as CPV
10+
from pkgcore.ebuild.cpv import VersionedCPV as CPV, UnversionedCPV as CP
1111
from pkgcore.test.misc import FakeRepo
1212
from snakeoil.cli import arghparse
1313
from snakeoil.fileutils import touch
@@ -650,6 +650,59 @@ def test_revision_move(self):
650650
self.init_check()
651651
self.assertNoReport(self.check, self.source)
652652

653+
def test_checksum_change(self):
654+
distfile = [
655+
"DIST",
656+
"pkgcheck-1.tar.gz",
657+
"549746",
658+
"BLAKE2B",
659+
"72ed97d93674ffd311978d03ad3738494a752bf1b02bea5eaaaf1b066c48e8c9ec5f82b79baeeabf3e56e618c76614ee6179b7115d1d875364ac6e3fbc3c6028",
660+
"SHA512",
661+
"6a8c135ca44ccbfe15548bd396aba9448c29f60147920b18b8be5aa5fcd1200e0b75bc5de50fc7892ad5460ddad1e7d28a7e44025bdc581a518d136eda8b0df2",
662+
]
663+
with open(pjoin(self.parent_repo.path, "profiles/thirdpartymirrors"), "a") as f:
664+
f.write("gentoo https://gentoo.org/distfiles\n")
665+
self.parent_repo.create_ebuild("cat/pkg-1", src_uri=f"mirror://gentoo/{distfile[1]}")
666+
with open(pjoin(self.parent_repo.path, "cat/pkg/Manifest"), "w") as f:
667+
f.write(" ".join(distfile) + "\n")
668+
self.parent_git_repo.add_all("cat/pkg: add 1", signoff=True)
669+
# pull changes and change checksum in child repo
670+
self.child_git_repo.run(["git", "pull", "origin", "main"])
671+
self.child_repo.create_ebuild("cat/pkg-1-r1", src_uri=f"mirror://gentoo/{distfile[1]}")
672+
distfile[-1] = distfile[-1][:-1] + "0"
673+
with open(pjoin(self.child_repo.path, "cat/pkg/Manifest"), "w") as f:
674+
f.write(" ".join(distfile) + "\n")
675+
self.child_git_repo.add_all("cat/pkg: revbump", signoff=True)
676+
self.init_check()
677+
r = self.assertReport(self.check, self.source)
678+
assert r == git_mod.SrcUriChecksumChange(distfile[1], pkg=CP("cat/pkg"))
679+
680+
def test_src_uri_change(self):
681+
distfile = [
682+
"DIST",
683+
"pkgcheck-1.tar.gz",
684+
"549746",
685+
"BLAKE2B",
686+
"72ed97d93674ffd311978d03ad3738494a752bf1b02bea5eaaaf1b066c48e8c9ec5f82b79baeeabf3e56e618c76614ee6179b7115d1d875364ac6e3fbc3c6028",
687+
"SHA512",
688+
"6a8c135ca44ccbfe15548bd396aba9448c29f60147920b18b8be5aa5fcd1200e0b75bc5de50fc7892ad5460ddad1e7d28a7e44025bdc581a518d136eda8b0df2",
689+
]
690+
old_url = f"mirror://gentoo/{distfile[1]}"
691+
new_url = f"https://pkgcore.github.io/pkgcheck/{distfile[1]}"
692+
with open(pjoin(self.parent_repo.path, "profiles/thirdpartymirrors"), "a") as f:
693+
f.write("gentoo https://gentoo.org/distfiles\n")
694+
self.parent_repo.create_ebuild("cat/pkg-1", src_uri=old_url)
695+
with open(pjoin(self.parent_repo.path, "cat/pkg/Manifest"), "w") as f:
696+
f.write(" ".join(distfile) + "\n")
697+
self.parent_git_repo.add_all("cat/pkg: add 1", signoff=True)
698+
# pull changes and change checksum in child repo
699+
self.child_git_repo.run(["git", "pull", "origin", "main"])
700+
self.child_repo.create_ebuild("cat/pkg-1", src_uri=new_url)
701+
self.child_git_repo.add_all("cat/pkg: change SRC_URI", signoff=True)
702+
self.init_check()
703+
r = self.assertReport(self.check, self.source)
704+
assert r == git_mod.SuspiciousSrcUriChange(old_url, new_url, distfile[1], pkg=CP("cat/pkg"))
705+
653706

654707
class TestGitEclassCommitsCheck(ReportTestCase):
655708

0 commit comments

Comments
 (0)