[gentoo-commits] proj/pkgcore/pkgcheck:master commit in: src/pkgcheck/checks/, tests/checks/

2024-03-07 Thread Arthur Zamarin
commit: 2ed2a36a62f3bb9801c187c053ec67ec6bb47565
Author: Arthur Zamarin  gentoo  org>
AuthorDate: Sat Mar  2 07:13:16 2024 +
Commit: Arthur Zamarin  gentoo  org>
CommitDate: Sat Mar  2 07:15:06 2024 +
URL:
https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=2ed2a36a

NewerEAPIAvailable: committing new ebuilds with old EAPI

Catch cases where new ebuilds are committed with old EAPIs. This is
checked during `--commits` stage.

Resolves: https://github.com/pkgcore/pkgcheck/issues/666
Signed-off-by: Arthur Zamarin  gentoo.org>

 src/pkgcheck/checks/git.py | 45 +++--
 tests/checks/test_git.py   |  2 +-
 2 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/src/pkgcheck/checks/git.py b/src/pkgcheck/checks/git.py
index 31f1dc69..a2619491 100644
--- a/src/pkgcheck/checks/git.py
+++ b/src/pkgcheck/checks/git.py
@@ -236,6 +236,23 @@ class OldPythonCompat(results.VersionResult, 
results.Warning):
 return f"old PYTHON_COMPAT target{s} listed: [ {targets} ]"
 
 
+class NewerEAPIAvailable(results.VersionResult, results.Warning):
+"""Package is eligible for a newer EAPI.
+
+A new package version was added, using an older EAPI, than all supported by
+inherited eclasses. You should consider bumping the EAPI to the suggested
+value.
+"""
+
+def __init__(self, eapi: int, **kwargs):
+super().__init__(**kwargs)
+self.eapi = eapi
+
+@property
+def desc(self):
+return f"ebuild eligible for newer EAPI={self.eapi}"
+
+
 class _RemovalRepo(UnconfiguredTree):
 """Repository of removed packages stored in a temporary directory."""
 
@@ -295,7 +312,7 @@ class GitPkgCommitsCheck(GentooRepoCheck, GitCommitsCheck):
 """Check unpushed git package commits for various issues."""
 
 _source = (sources.PackageRepoSource, (), (("source", 
GitCommitsRepoSource),))
-required_addons = (git.GitAddon,)
+required_addons = (git.GitAddon, sources.EclassAddon)
 known_results = frozenset(
 {
 DirectStableKeywords,
@@ -311,6 +328,7 @@ class GitPkgCommitsCheck(GentooRepoCheck, GitCommitsCheck):
 PythonPEP517WithoutRevbump,
 EAPIChangeWithoutRevbump,
 OldPythonCompat,
+NewerEAPIAvailable,
 }
 )
 
@@ -321,12 +339,13 @@ class GitPkgCommitsCheck(GentooRepoCheck, 
GitCommitsCheck):
 # package categories that are committed with stable keywords
 allowed_direct_stable = frozenset(["acct-user", "acct-group"])
 
-def __init__(self, *args, git_addon: git.GitAddon):
+def __init__(self, *args, git_addon: git.GitAddon, eclass_addon: 
sources.EclassAddon):
 super().__init__(*args)
 self.today = datetime.today()
 self.repo = self.options.target_repo
 self.valid_arches: frozenset[str] = 
self.options.target_repo.known_arches
 self._git_addon = git_addon
+self.eclass_cache = eclass_addon.eclasses
 self._cleanup = []
 self.valid_python_targets = {
 use.removeprefix("python_targets_")
@@ -354,6 +373,25 @@ class GitPkgCommitsCheck(GentooRepoCheck, GitCommitsCheck):
 """Create/load cached repo of packages added to git."""
 return self._git_addon.cached_repo(git.GitAddedRepo)
 
+def addition_checks(self, pkgs):
+"""Check for issues due to package additions."""
+pkg = pkgs[0]
+try:
+new_pkg = self.repo.match(pkg.versioned_atom)[0]
+except IndexError:
+# ignore missing ebuild
+return
+
+if new_pkg.inherit:
+eclass_eapis = (
+frozenset(map(int, self.eclass_cache[eclass].supported_eapis))
+for eclass in new_pkg.inherit
+)
+current_eapi = int(str(new_pkg.eapi))
+common_max_eapi = max(frozenset.intersection(*eclass_eapis))
+if common_max_eapi > current_eapi:
+yield NewerEAPIAvailable(common_max_eapi, pkg=new_pkg)
+
 def removal_checks(self, pkgs):
 """Check for issues due to package removals."""
 pkg = pkgs[0]
@@ -526,6 +564,9 @@ class GitPkgCommitsCheck(GentooRepoCheck, GitCommitsCheck):
 pkg_map["A"].add(pkg)
 pkg_map["D"].add(pkg.old_pkg())
 
+# run added package checks
+if pkg_map["A"]:
+yield from self.addition_checks(list(pkg_map["A"]))
 # run removed package checks
 if pkg_map["D"]:
 yield from self.removal_checks(list(pkg_map["D"]))

diff --git a/tests/checks/test_git.py b/tests/checks/test_git.py
index ab6efee2..12c5e4f0 100644
--- a/tests/checks/test_git.py
+++ b/tests/checks/test_git.py
@@ -38,7 +38,7 @@ class TestGitCommitMessageCheck(ReportTestCase):
 check = git_mod.GitCommitMessageCheck(options)
 
 def test_sign_offs(self):
-# assert that it checks for both author and comitter
+# assert that it 

[gentoo-commits] proj/pkgcore/pkgcheck:master commit in: src/pkgcheck/checks/, tests/checks/

2023-07-15 Thread Arthur Zamarin
commit: 59cfd9b5e53577b59fd513b1cdd9e0cda184ed13
Author: Arthur Zamarin  gentoo  org>
AuthorDate: Sun Jul  2 19:24:58 2023 +
Commit: Arthur Zamarin  gentoo  org>
CommitDate: Sat Jul 15 08:36:00 2023 +
URL:
https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=59cfd9b5

PerlCheck: check versioned virtual perl dependencies

Resolves: https://github.com/pkgcore/pkgcheck/issues/593
Signed-off-by: Arthur Zamarin  gentoo.org>

 src/pkgcheck/checks/perl.py | 66 -
 tests/checks/test_perl.py   | 36 +
 2 files changed, 90 insertions(+), 12 deletions(-)

diff --git a/src/pkgcheck/checks/perl.py b/src/pkgcheck/checks/perl.py
index f2c3bd25..2774f990 100644
--- a/src/pkgcheck/checks/perl.py
+++ b/src/pkgcheck/checks/perl.py
@@ -2,8 +2,11 @@ import multiprocessing
 import re
 import subprocess
 
+from pkgcore.ebuild.atom import atom as atom_cls
 from pkgcore.restrictions import packages, values
+from pkgcore.package.errors import MetadataException
 from snakeoil.osutils import pjoin
+from snakeoil.sequences import iflatten_instance
 
 from .. import const, results, sources
 from . import OptionalCheck, SkipCheck
@@ -22,6 +25,24 @@ class MismatchedPerlVersion(results.VersionResult, 
results.Warning):
 return f"DIST_VERSION={self.dist_version} normalizes to 
{self.normalized}"
 
 
+class MissingVersionedVirtualPerlDependency(results.VersionResult, 
results.Warning):
+"""Missing version restriction for virtual perl dependency.
+
+The virtuals ``virtual/perl-*`` stand for packages that have releases both
+as part of ``dev-lang/perl`` and standalone in ``perl-core/*``. Apart from
+rare special cases, if you require "any" version of such a virtual, this
+will always be fulfilled by ``dev-lang/perl``.
+"""
+
+def __init__(self, atom, **kwargs):
+super().__init__(**kwargs)
+self.atom = atom
+
+@property
+def desc(self):
+return f"missing version restriction for virtual perl: {self.atom!r}"
+
+
 class _PerlException(Exception):
 """Generic error during perl script initialization."""
 
@@ -70,12 +91,13 @@ class _PerlConnection:
 class PerlCheck(OptionalCheck):
 """Perl ebuild related checks."""
 
-_restricted_source = (
-sources.RestrictionRepoSource,
-(packages.PackageRestriction("inherited", 
values.ContainmentMatch2("perl-module")),),
+_source = sources.EbuildFileRepoSource
+known_results = frozenset(
+{
+MismatchedPerlVersion,
+MissingVersionedVirtualPerlDependency,
+}
 )
-_source = (sources.EbuildFileRepoSource, (), (("source", 
_restricted_source),))
-known_results = frozenset([MismatchedPerlVersion])
 
 def __init__(self, *args):
 super().__init__(*args)
@@ -86,12 +108,32 @@ class PerlCheck(OptionalCheck):
 # it easier to disable this check if required perl deps are missing.
 try:
 self.perl = _PerlConnection(self.options)
-except _PerlException as e:
-raise SkipCheck(self, str(e))
+except _PerlException as exc:
+raise SkipCheck(self, str(exc))
 
 def feed(self, pkg):
-if mo := self.dist_version_re.search("".join(pkg.lines)):
-dist_version = mo.group("dist_version")
-normalized = self.perl.normalize(dist_version)
-if normalized != pkg.version:
-yield MismatchedPerlVersion(dist_version, normalized, pkg=pkg)
+if "perl-module" in pkg.inherited:
+if mo := self.dist_version_re.search("".join(pkg.lines)):
+dist_version = mo.group("dist_version")
+normalized = self.perl.normalize(dist_version)
+if normalized != pkg.version:
+yield MismatchedPerlVersion(dist_version, normalized, 
pkg=pkg)
+
+missing_virtual_perl = set()
+for attr in (x.lower() for x in pkg.eapi.dep_keys):
+try:
+deps = getattr(pkg, attr)
+except MetadataException:
+continue
+for atom in iflatten_instance(deps, (atom_cls,)):
+if (
+not atom.op
+and atom.key.startswith("virtual/perl-")
+and pkg.key != "dev-lang/perl"
+and pkg.category != "perl-core"
+and not pkg.key.startswith("virtual/perl-")
+):
+missing_virtual_perl.add(str(atom))
+
+for atom in sorted(missing_virtual_perl):
+yield MissingVersionedVirtualPerlDependency(str(atom), pkg=pkg)

diff --git a/tests/checks/test_perl.py b/tests/checks/test_perl.py
index 8de1a795..b2f76eab 100644
--- a/tests/checks/test_perl.py
+++ b/tests/checks/test_perl.py
@@ -73,3 +73,39 @@ class TestPerlCheck(misc.ReportTestCase):
 for verbosity in (0, 1):
 with 

[gentoo-commits] proj/pkgcore/pkgcheck:master commit in: src/pkgcheck/checks/, tests/checks/

2023-03-10 Thread Arthur Zamarin
commit: 7410c137c57c645b5e502f279eb183a14d7ef216
Author: Arthur Zamarin  gentoo  org>
AuthorDate: Sat Mar 11 07:10:29 2023 +
Commit: Arthur Zamarin  gentoo  org>
CommitDate: Sat Mar 11 07:10:29 2023 +
URL:
https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=7410c137

GitPkgCommitsCheck: fix modification check for added ebuild in pkgset

When commit range has modification for multiple versions, with one of
them modifying a newly added version in the same range, it wouldn't find
the correct base commit and fail. Fix it by grouping based on fullver.

The test is special with time.sleep, since I need the commits be in
different seconds, otherwise the sorting by time might be bad.

Resolves: https://github.com/pkgcore/pkgcheck/issues/563
Signed-off-by: Arthur Zamarin  gentoo.org>

 src/pkgcheck/checks/git.py |  6 +-
 tests/checks/test_git.py   | 15 +++
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/src/pkgcheck/checks/git.py b/src/pkgcheck/checks/git.py
index 7309a08f..aec3b05f 100644
--- a/src/pkgcheck/checks/git.py
+++ b/src/pkgcheck/checks/git.py
@@ -497,7 +497,11 @@ class GitPkgCommitsCheck(GentooRepoCheck, GitCommitsCheck):
 yield from self.rename_checks(list(pkg_map["R"]))
 # run modified package checks
 if modified := [pkg for pkg in pkg_map["M"] if pkg not in 
pkg_map["D"]]:
-yield from self.modified_checks(modified, list(pkg_map["A"]))
+version_modifications = defaultdict(list)
+for pkg in modified:
+version_modifications[pkg.fullver].append(pkg)
+for modified in version_modifications.values():
+yield from self.modified_checks(modified, pkg_map["A"])
 
 for git_pkg in pkgset:
 # remaining checks are irrelevant for removed packages

diff --git a/tests/checks/test_git.py b/tests/checks/test_git.py
index 7eb7907a..03687451 100644
--- a/tests/checks/test_git.py
+++ b/tests/checks/test_git.py
@@ -1,5 +1,6 @@
 import os
 import textwrap
+import time
 from datetime import datetime, timedelta
 from unittest.mock import patch
 
@@ -736,6 +737,20 @@ class TestGitPkgCommitsCheck(ReportTestCase):
 self.init_check()
 self.assertNoReport(self.check, self.source)
 
+def test_modified_added_file(self):
+self.child_repo.create_ebuild("cat/pkg-0", 
homepage="https://gentoo.org;)
+self.child_git_repo.add_all("cat/pkg: update HOMEPAGE")
+time.sleep(1)
+self.child_repo.create_ebuild("cat/pkg-1", eapi="7")
+self.child_git_repo.add_all("cat/pkg: add 1")
+time.sleep(1)
+self.child_repo.create_ebuild("cat/pkg-1", eapi="8")
+self.child_git_repo.add_all("cat/pkg: bump EAPI")
+self.init_check()
+r = self.assertReport(self.check, self.source)
+expected = git_mod.EAPIChangeWithoutRevbump(pkg=CPV("cat/pkg-1"))
+assert r == expected
+
 
 class TestGitEclassCommitsCheck(ReportTestCase):
 check_kls = git_mod.GitEclassCommitsCheck



[gentoo-commits] proj/pkgcore/pkgcheck:master commit in: src/pkgcheck/checks/, tests/checks/

2023-03-05 Thread Arthur Zamarin
commit: e8d16ecb9765c32694b7a518381aee94ef5d9108
Author: Sam James  gentoo  org>
AuthorDate: Sat Mar  4 09:20:28 2023 +
Commit: Arthur Zamarin  gentoo  org>
CommitDate: Sun Mar  5 17:13:22 2023 +
URL:
https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=e8d16ecb

checks: git: add PythonPEP517WithoutRevbump

Warn when DISTUTILS_USE_PEP517 is added or removed from an
ebuild without a new revision.

This is important because PEP517 affects a package's installed
files anyway and it's important to ensure that dependencies
work correctly against it, but also because e.g. config files
or other data files might either now be installed to the wrong
location or not installed at all. Developers must inspect
the image before/after (e.g. using iwdevtools) to avoid
issues.

Fixes: https://github.com/pkgcore/pkgcheck/issues/498
Signed-off-by: Sam James  gentoo.org>
Signed-off-by: Arthur Zamarin  gentoo.org>

 src/pkgcheck/checks/git.py | 28 
 tests/checks/test_git.py   | 19 +++
 2 files changed, 47 insertions(+)

diff --git a/src/pkgcheck/checks/git.py b/src/pkgcheck/checks/git.py
index 8b272531..22780cbe 100644
--- a/src/pkgcheck/checks/git.py
+++ b/src/pkgcheck/checks/git.py
@@ -171,6 +171,18 @@ class MissingMove(results.PackageResult, results.Error):
 return f"renamed package: {self.old} -> {self.new}"
 
 
+class PythonPEP517WithoutRevbump(results.PackageResult, results.Warning):
+"""Package has started/stopped using DISTUTILS_USE_PEP517 without revbump.
+
+The package has started or stopped using DISTUTILS_USE_PEP517 without
+a new revision. PEP517 affects the files installed by a package
+and might lead to some files missing.
+
+"""
+
+desc = "changed DISTUTILS_USE_PEP517 without new revision"
+
+
 class SrcUriChecksumChange(results.PackageResult, results.Error):
 """SRC_URI changing checksum without distfile rename."""
 
@@ -265,9 +277,12 @@ class GitPkgCommitsCheck(GentooRepoCheck, GitCommitsCheck):
 MissingMove,
 SrcUriChecksumChange,
 SuspiciousSrcUriChange,
+PythonPEP517WithoutRevbump,
 ]
 )
 
+python_pep517_regex = re.compile("^DISTUTILS_USE_PEP517=")
+
 # package categories that are committed with stable keywords
 allowed_direct_stable = frozenset(["acct-user", "acct-group"])
 
@@ -364,6 +379,19 @@ class GitPkgCommitsCheck(GentooRepoCheck, GitCommitsCheck):
 if pkg not in added and old_pkg.rdepend != new_pkg.rdepend:
 yield RdependChange(pkg=new_pkg)
 
+if "distutils-r1" in new_pkg.inherited:
+
+def found_pep517_lines(cmp_pkg):
+return any(
+self.python_pep517_regex.match(line) for line in 
cmp_pkg.ebuild.text_fileobj()
+)
+
+found_old_pep517_line = found_pep517_lines(old_pkg)
+found_new_pep517_line = found_pep517_lines(new_pkg)
+
+if found_old_pep517_line ^ found_new_pep517_line:
+yield PythonPEP517WithoutRevbump(pkg=new_pkg)
+
 old_slot, new_slot = old_pkg.slot, new_pkg.slot
 if old_slot != new_slot:
 slotmoves = (

diff --git a/tests/checks/test_git.py b/tests/checks/test_git.py
index 57fc28ac..5deaad71 100644
--- a/tests/checks/test_git.py
+++ b/tests/checks/test_git.py
@@ -675,6 +675,25 @@ class TestGitPkgCommitsCheck(ReportTestCase):
 r = self.assertReport(self.check, self.source)
 assert r == git_mod.SrcUriChecksumChange(distfile[1], 
pkg=CP("cat/pkg"))
 
+def test_python_pep517_change(self):
+with open(pjoin(self.parent_git_repo.path, 
"eclass/distutils-r1.eclass"), "w") as f:
+f.write("# Copyright 1999-2019 Gentoo Authors")
+self.parent_git_repo.add_all("eclass: add distutils-r1")
+
+# add pkgs to parent repo
+self.parent_repo.create_ebuild("newcat/newpkg-1", data="inherit 
distutils-r1")
+self.parent_git_repo.add_all("newcat/newpkg: initial import")
+# pull changes to child repo
+self.child_git_repo.run(["git", "pull", "origin", "main"])
+# change an existing ebuild to have DISTUTILS_USE_PEP517 with no 
revbump
+with open(pjoin(self.child_git_repo.path, 
"newcat/newpkg/newpkg-1.ebuild"), "a") as f:
+f.write("\nDISTUTILS_USE_PEP517=setuptools\n")
+self.child_git_repo.add_all("newcat/newpkg: use PEP517")
+self.init_check()
+r = self.assertReport(self.check, self.source)
+expected = 
git_mod.PythonPEP517WithoutRevbump(pkg=CPV("newcat/newpkg-1"))
+assert r == expected
+
 def test_src_uri_change(self):
 distfile = [
 "DIST",



[gentoo-commits] proj/pkgcore/pkgcheck:master commit in: src/pkgcheck/checks/, tests/checks/

2023-03-03 Thread Arthur Zamarin
commit: 861c24ab76bfc36de2ca80a8375866e4123dc51a
Author: Arthur Zamarin  gentoo  org>
AuthorDate: Sat Mar  4 05:56:56 2023 +
Commit: Arthur Zamarin  gentoo  org>
CommitDate: Sat Mar  4 05:56:56 2023 +
URL:
https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=861c24ab

StableRequestCheck: ignore version not keyworded for arches

packages that are not keyworded for relevant arches but keyworded to
another arch, were not ignored by the check. This patch fixes that.

Resolves: https://github.com/pkgcore/pkgcheck/issues/544
Signed-off-by: Arthur Zamarin  gentoo.org>

 src/pkgcheck/checks/stablereq.py | 5 +
 tests/checks/test_stablereq.py   | 9 +
 2 files changed, 14 insertions(+)

diff --git a/src/pkgcheck/checks/stablereq.py b/src/pkgcheck/checks/stablereq.py
index 57e41a84..be8e2c7f 100644
--- a/src/pkgcheck/checks/stablereq.py
+++ b/src/pkgcheck/checks/stablereq.py
@@ -71,6 +71,7 @@ class StableRequestCheck(GentooRepoCheck):
 pkg_keywords.update(pkg.keywords)
 
 if stable_pkg_keywords := {x for x in pkg_keywords if x[0] not in 
{"-", "~"}}:
+keyworded_pkg_keywords = {"~" + x for x in stable_pkg_keywords}
 for slot, pkgs in sorted(pkg_slotted.items()):
 slot_keywords = set().union(*(pkg.keywords for pkg in pkgs))
 stable_slot_keywords = 
slot_keywords.intersection(stable_pkg_keywords)
@@ -79,6 +80,10 @@ class StableRequestCheck(GentooRepoCheck):
 if stable_pkg_keywords.intersection(pkg.keywords):
 break
 
+# stop if not keyworded for stable
+if not keyworded_pkg_keywords.intersection(pkg.keywords):
+break
+
 try:
 match = 
next(self.modified_repo.itermatch(pkg.versioned_atom))
 except StopIteration:

diff --git a/tests/checks/test_stablereq.py b/tests/checks/test_stablereq.py
index 43f4380b..efb94b7a 100644
--- a/tests/checks/test_stablereq.py
+++ b/tests/checks/test_stablereq.py
@@ -118,6 +118,15 @@ class TestStableRequestCheck(ReportTestCase):
 expected = StableRequest("1", ["~amd64"], 30, 
pkg=VersionedCPV("cat/pkg-2"))
 assert r == expected
 
+def test_unkeyworded_new_pkg(self):
+self.parent_repo.create_ebuild("cat/pkg-1", keywords=["amd64"])
+self.parent_git_repo.add_all("cat/pkg-1")
+self.parent_repo.create_ebuild("cat/pkg-2", keywords=["~x86"])
+self.parent_git_repo.add_all("cat/pkg-2")
+self.child_git_repo.run(["git", "pull", "origin", "main"])
+self.init_check(future=30)
+self.assertNoReport(self.check, self.source)
+
 def test_moved_category(self):
 self.parent_repo.create_ebuild("cat/pkg-1", keywords=["amd64"])
 self.parent_git_repo.add_all("cat/pkg-1")



[gentoo-commits] proj/pkgcore/pkgcheck:master commit in: src/pkgcheck/checks/, tests/checks/

2023-01-21 Thread Arthur Zamarin
commit: 7d50c226b79d158ed08e925369560727993fb0b7
Author: Arthur Zamarin  gentoo  org>
AuthorDate: Sat Jan 21 09:44:17 2023 +
Commit: Arthur Zamarin  gentoo  org>
CommitDate: Sat Jan 21 09:44:17 2023 +
URL:
https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=7d50c226

SuspiciousSrcUriChange: fix false positive with mirrors

The original code for comparing for URL change was giving false
positives when the URI is mirror based, since an object was used to
compare. Pre-compute the URI string and use strings for comparison.
Also add a test for that failure.

Resolves: https://github.com/pkgcore/pkgcheck/issues/531
Signed-off-by: Arthur Zamarin  gentoo.org>

 src/pkgcheck/checks/git.py | 26 ++
 tests/checks/test_git.py   |  6 ++
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/src/pkgcheck/checks/git.py b/src/pkgcheck/checks/git.py
index 764dfc5d..adc16874 100644
--- a/src/pkgcheck/checks/git.py
+++ b/src/pkgcheck/checks/git.py
@@ -186,16 +186,10 @@ class SrcUriChecksumChange(results.PackageResult, 
results.Error):
 class SuspiciousSrcUriChange(results.PackageResult, results.Warning):
 """Suspicious SRC_URI changing URI without distfile rename."""
 
-def __init__(self, old_uri, new_uri, filename, **kwargs):
+def __init__(self, old_uri: str, new_uri: str, filename: str, **kwargs):
 super().__init__(**kwargs)
-if isinstance(old_uri, tuple):
-self.old_uri = f"mirror://{old_uri[0].mirror_name}/{old_uri[1]}"
-else:
-self.old_uri = str(old_uri)
-if isinstance(new_uri, tuple):
-self.new_uri = f"mirror://{new_uri[0].mirror_name}/{new_uri[1]}"
-else:
-self.new_uri = str(new_uri)
+self.old_uri = old_uri
+self.new_uri = new_uri
 self.filename = filename
 
 @property
@@ -381,18 +375,26 @@ class GitPkgCommitsCheck(GentooRepoCheck, 
GitCommitsCheck):
 else:
 yield MissingSlotmove(old_slot, new_slot, pkg=new_pkg)
 
+@staticmethod
+def _fetchable_str(fetch: fetchable) -> str:
+uri = tuple(fetch.uri._uri_source)[0]
+if isinstance(uri, tuple):
+return f"mirror://{uri[0].mirror_name}/{uri[1]}"
+else:
+return str(uri)
+
 def src_uri_changes(self, pkgset):
 pkg = pkgset[0].unversioned_atom
 
 try:
 new_checksums = {
-fetch.filename: (fetch.chksums, tuple(fetch.uri._uri_source))
+fetch.filename: (fetch.chksums, self._fetchable_str(fetch))
 for pkg in self.repo.match(pkg)
 for fetch in iflatten_instance(pkg.fetchables, fetchable)
 }
 
 old_checksums = {
-fetch.filename: (fetch.chksums, tuple(fetch.uri._uri_source))
+fetch.filename: (fetch.chksums, self._fetchable_str(fetch))
 for pkg in self.modified_repo(pkgset).match(pkg)
 for fetch in iflatten_instance(pkg.fetchables, fetchable)
 }
@@ -406,7 +408,7 @@ class GitPkgCommitsCheck(GentooRepoCheck, GitCommitsCheck):
 if old_checksum != new_checksum:
 yield SrcUriChecksumChange(filename, pkg=pkg)
 elif old_uri != new_uri:
-yield SuspiciousSrcUriChange(old_uri[0], new_uri[0], filename, 
pkg=pkg)
+yield SuspiciousSrcUriChange(old_uri, new_uri, filename, 
pkg=pkg)
 
 def feed(self, pkgset: list[git.GitPkgChange]):
 # Mapping of commit types to pkgs, available commit types can be seen

diff --git a/tests/checks/test_git.py b/tests/checks/test_git.py
index b69893d8..eed40e13 100644
--- a/tests/checks/test_git.py
+++ b/tests/checks/test_git.py
@@ -702,6 +702,12 @@ class TestGitPkgCommitsCheck(ReportTestCase):
 self.init_check()
 r = self.assertReport(self.check, self.source)
 assert r == git_mod.SuspiciousSrcUriChange(old_url, new_url, 
distfile[1], pkg=CP("cat/pkg"))
+# revert change and check for no report with same mirror url
+self.child_git_repo.run(["git", "reset", "--hard", "origin/main"])
+self.child_repo.create_ebuild("cat/pkg-1", src_uri=old_url, eapi="8")
+self.child_git_repo.add_all("cat/pkg: bump EAPI", signoff=True)
+self.init_check()
+self.assertNoReport(self.check, self.source)
 
 
 class TestGitEclassCommitsCheck(ReportTestCase):



[gentoo-commits] proj/pkgcore/pkgcheck:master commit in: src/pkgcheck/checks/, tests/checks/

2023-01-20 Thread Arthur Zamarin
commit: 09559c09f2389246ea98261832e281a9baaedbdf
Author: Arthur Zamarin  gentoo  org>
AuthorDate: Sat Nov 26 17:06:06 2022 +
Commit: Arthur Zamarin  gentoo  org>
CommitDate: Fri Jan 20 20:36:42 2023 +
URL:
https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=09559c09

GitPkgCommitsCheck: catch SRC_URI mistakes

Resolves: https://github.com/pkgcore/pkgcheck/issues/493
Signed-off-by: Arthur Zamarin  gentoo.org>

 src/pkgcheck/checks/git.py | 67 +-
 tests/checks/test_git.py   | 55 -
 2 files changed, 120 insertions(+), 2 deletions(-)

diff --git a/src/pkgcheck/checks/git.py b/src/pkgcheck/checks/git.py
index 6e48d47f..764dfc5d 100644
--- a/src/pkgcheck/checks/git.py
+++ b/src/pkgcheck/checks/git.py
@@ -13,9 +13,11 @@ from urllib.parse import urlparse
 
 from pkgcore.ebuild.misc import sort_keywords
 from pkgcore.ebuild.repository import UnconfiguredTree
+from pkgcore.fetch import fetchable
 from snakeoil import klass
 from snakeoil.mappings import ImmutableDict
 from snakeoil.osutils import pjoin
+from snakeoil.sequences import iflatten_instance
 from snakeoil.strings import pluralism
 
 from .. import base, results, sources
@@ -169,6 +171,38 @@ class MissingMove(results.PackageResult, results.Error):
 return f"renamed package: {self.old} -> {self.new}"
 
 
+class SrcUriChecksumChange(results.PackageResult, results.Error):
+"""SRC_URI changing checksum without distfile rename."""
+
+def __init__(self, filename, **kwargs):
+super().__init__(**kwargs)
+self.filename = filename
+
+@property
+def desc(self):
+return f"{self.filename!r} has different checksums across commits"
+
+
+class SuspiciousSrcUriChange(results.PackageResult, results.Warning):
+"""Suspicious SRC_URI changing URI without distfile rename."""
+
+def __init__(self, old_uri, new_uri, filename, **kwargs):
+super().__init__(**kwargs)
+if isinstance(old_uri, tuple):
+self.old_uri = f"mirror://{old_uri[0].mirror_name}/{old_uri[1]}"
+else:
+self.old_uri = str(old_uri)
+if isinstance(new_uri, tuple):
+self.new_uri = f"mirror://{new_uri[0].mirror_name}/{new_uri[1]}"
+else:
+self.new_uri = str(new_uri)
+self.filename = filename
+
+@property
+def desc(self):
+return f"{self.filename!r} has changed SRC_URI from {self.old_uri!r} 
to {self.new_uri!r}"
+
+
 class _RemovalRepo(UnconfiguredTree):
 """Repository of removed packages stored in a temporary directory."""
 
@@ -235,6 +269,8 @@ class GitPkgCommitsCheck(GentooRepoCheck, GitCommitsCheck):
 DroppedUnstableKeywords,
 MissingSlotmove,
 MissingMove,
+SrcUriChecksumChange,
+SuspiciousSrcUriChange,
 ]
 )
 
@@ -345,7 +381,34 @@ class GitPkgCommitsCheck(GentooRepoCheck, GitCommitsCheck):
 else:
 yield MissingSlotmove(old_slot, new_slot, pkg=new_pkg)
 
-def feed(self, pkgset):
+def src_uri_changes(self, pkgset):
+pkg = pkgset[0].unversioned_atom
+
+try:
+new_checksums = {
+fetch.filename: (fetch.chksums, tuple(fetch.uri._uri_source))
+for pkg in self.repo.match(pkg)
+for fetch in iflatten_instance(pkg.fetchables, fetchable)
+}
+
+old_checksums = {
+fetch.filename: (fetch.chksums, tuple(fetch.uri._uri_source))
+for pkg in self.modified_repo(pkgset).match(pkg)
+for fetch in iflatten_instance(pkg.fetchables, fetchable)
+}
+except (IndexError, FileNotFoundError, tarfile.ReadError):
+# ignore broken ebuild
+return
+
+for filename in old_checksums.keys() & new_checksums.keys():
+old_checksum, old_uri = old_checksums[filename]
+new_checksum, new_uri = new_checksums[filename]
+if old_checksum != new_checksum:
+yield SrcUriChecksumChange(filename, pkg=pkg)
+elif old_uri != new_uri:
+yield SuspiciousSrcUriChange(old_uri[0], new_uri[0], filename, 
pkg=pkg)
+
+def feed(self, pkgset: list[git.GitPkgChange]):
 # Mapping of commit types to pkgs, available commit types can be seen
 # under the --diff-filter option in git log parsing support and are
 # disambiguated as follows:
@@ -407,6 +470,8 @@ class GitPkgCommitsCheck(GentooRepoCheck, GitCommitsCheck):
 if not pkg.maintainers and newly_added:
 yield DirectNoMaintainer(pkg=pkg)
 
+yield from self.src_uri_changes(pkgset)
+
 
 class MissingSignOff(results.CommitResult, results.Error):
 """Local commit with missing sign offs.

diff --git a/tests/checks/test_git.py b/tests/checks/test_git.py
index 0294f0b3..b69893d8 100644
--- 

[gentoo-commits] proj/pkgcore/pkgcheck:master commit in: src/pkgcheck/checks/, tests/checks/

2022-11-26 Thread Arthur Zamarin
commit: 7938bcce6cf79addfd1c0b6e7bedee7a51b564e2
Author: Michał Górny  gentoo  org>
AuthorDate: Thu Nov 24 18:58:28 2022 +
Commit: Arthur Zamarin  gentoo  org>
CommitDate: Thu Nov 24 18:58:28 2022 +
URL:
https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=7938bcce

PythonCheck: remove obsolete pypy packages

Unlist the removed dev-python/pypy*-bin and virtual/pypy* packages
from PythonCheck, as well as the no-longer-relevant virtual/pypy*
exceptions.

Signed-off-by: Michał Górny  gentoo.org>

 src/pkgcheck/checks/python.py | 11 ---
 tests/checks/test_python.py   |  6 --
 2 files changed, 17 deletions(-)

diff --git a/src/pkgcheck/checks/python.py b/src/pkgcheck/checks/python.py
index 5d6a8a1a..bb4825e2 100644
--- a/src/pkgcheck/checks/python.py
+++ b/src/pkgcheck/checks/python.py
@@ -22,14 +22,8 @@ INTERPRETERS = frozenset([
 'dev-lang/python',
 'dev-python/pypy',
 'dev-python/pypy3',
-'dev-python/pypy-bin',
-'dev-python/pypy3-bin',
-'virtual/pypy',
-'virtual/pypy3',
 ])
 
-CHECK_EXCLUDE = frozenset(['virtual/pypy', 'virtual/pypy3'])
-
 IUSE_PREFIX = 'python_targets_'
 IUSE_PREFIX_S = 'python_single_target_'
 
@@ -439,11 +433,6 @@ class PythonCheck(Check):
 return
 
 if eclass is None:
-# virtual/pypy* need to be exempted as they serve as slot-matchers
-# for other packages
-if pkg.key in CHECK_EXCLUDE:
-return
-
 # check whether we should be using one
 highest_found = None
 for attr in (x.lower() for x in pkg.eapi.dep_keys):

diff --git a/tests/checks/test_python.py b/tests/checks/test_python.py
index 411fff7f..992b7dce 100644
--- a/tests/checks/test_python.py
+++ b/tests/checks/test_python.py
@@ -105,12 +105,6 @@ class TestPythonCheck(misc.ReportTestCase):
 self.assertReport(self.check, 
self.mk_pkg(RDEPEND='dev-python/pypy')),
 python.MissingPythonEclass)
 
-# special exception: virtual/pypy
-self.assertNoReport(self.check, self.mk_pkg(cpv='virtual/pypy-4.1',
-RDEPEND='|| ( dev-python/pypy:0/41 dev-python/pypy-bin:0/41 )'))
-self.assertNoReport(self.check, self.mk_pkg(cpv='virtual/pypy3-4.1',
-RDEPEND='|| ( dev-python/pypy3:0/41 dev-python/pypy3-bin:0/41 )'))
-
 def test_missing_eclass_pdepend(self):
 self.assertNoReport(
 self.check,



[gentoo-commits] proj/pkgcore/pkgcheck:master commit in: src/pkgcheck/checks/, tests/checks/

2022-11-26 Thread Arthur Zamarin
commit: 0c533a1ece525ff7e010b92dd2423b49328e04ff
Author: Michał Górny  gentoo  org>
AuthorDate: Thu Nov 24 19:01:52 2022 +
Commit: Arthur Zamarin  gentoo  org>
CommitDate: Thu Nov 24 19:01:52 2022 +
URL:
https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=0c533a1e

PythonCheck: stop testing for pypy(2.7)

The eclasses no longer support the pypy target, so stop checking
for dev-python/pypy.

Signed-off-by: Michał Górny  gentoo.org>

 src/pkgcheck/checks/python.py |  1 -
 tests/checks/test_python.py   | 12 
 2 files changed, 13 deletions(-)

diff --git a/src/pkgcheck/checks/python.py b/src/pkgcheck/checks/python.py
index bb4825e2..918b5d5b 100644
--- a/src/pkgcheck/checks/python.py
+++ b/src/pkgcheck/checks/python.py
@@ -20,7 +20,6 @@ ECLASSES = frozenset(['python-r1', 'python-single-r1', 
'python-any-r1'])
 # NB: dev-java/jython omitted as not supported by the eclasses atm
 INTERPRETERS = frozenset([
 'dev-lang/python',
-'dev-python/pypy',
 'dev-python/pypy3',
 ])
 

diff --git a/tests/checks/test_python.py b/tests/checks/test_python.py
index 992b7dce..dd32147e 100644
--- a/tests/checks/test_python.py
+++ b/tests/checks/test_python.py
@@ -43,9 +43,6 @@ class TestPythonCheck(misc.ReportTestCase):
 self.check,
 self.mk_pkg(DEPEND='|| ( dev-lang/python:2.7 
dev-lang/python:3.6 )')),
 python.MissingPythonEclass)
-assert isinstance(
-self.assertReport(self.check, 
self.mk_pkg(DEPEND='dev-python/pypy')),
-python.MissingPythonEclass)
 
 def test_missing_eclass_bdepend(self):
 self.assertNoReport(
@@ -70,9 +67,6 @@ class TestPythonCheck(misc.ReportTestCase):
 self.check,
 self.mk_pkg(BDEPEND='|| ( dev-lang/python:2.7 
dev-lang/python:3.6 )')),
 python.MissingPythonEclass)
-assert isinstance(
-self.assertReport(self.check, 
self.mk_pkg(BDEPEND='dev-python/pypy')),
-python.MissingPythonEclass)
 
 def test_missing_eclass_rdepend(self):
 self.assertNoReport(
@@ -101,9 +95,6 @@ class TestPythonCheck(misc.ReportTestCase):
 self.check,
 self.mk_pkg(RDEPEND='|| ( dev-lang/python:2.7 
dev-lang/python:3.6 )')),
 python.MissingPythonEclass)
-assert isinstance(
-self.assertReport(self.check, 
self.mk_pkg(RDEPEND='dev-python/pypy')),
-python.MissingPythonEclass)
 
 def test_missing_eclass_pdepend(self):
 self.assertNoReport(
@@ -131,9 +122,6 @@ class TestPythonCheck(misc.ReportTestCase):
 self.check,
 self.mk_pkg(PDEPEND='|| ( dev-lang/python:2.7 
dev-lang/python:3.6 )')),
 python.MissingPythonEclass)
-assert isinstance(
-self.assertReport(self.check, 
self.mk_pkg(PDEPEND='dev-python/pypy')),
-python.MissingPythonEclass)
 
 def test_valid_packages(self):
 self.assertNoReport(



[gentoo-commits] proj/pkgcore/pkgcheck:master commit in: src/pkgcheck/checks/, tests/checks/

2022-10-28 Thread Arthur Zamarin
commit: c415e94f833acc4b824cf2b6db332244e97313e9
Author: Arthur Zamarin  gentoo  org>
AuthorDate: Sat Oct 22 08:21:13 2022 +
Commit: Arthur Zamarin  gentoo  org>
CommitDate: Fri Oct 28 13:15:03 2022 +
URL:
https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=c415e94f

ExcessiveLineCheck: check for too long lines

Closes: https://bugs.gentoo.org/440686
Signed-off-by: Arthur Zamarin  gentoo.org>

 src/pkgcheck/checks/codingstyle.py | 39 +
 tests/checks/test_codingstyle.py   | 59 ++
 2 files changed, 98 insertions(+)

diff --git a/src/pkgcheck/checks/codingstyle.py 
b/src/pkgcheck/checks/codingstyle.py
index e8a2f45a..0933c492 100644
--- a/src/pkgcheck/checks/codingstyle.py
+++ b/src/pkgcheck/checks/codingstyle.py
@@ -1079,3 +1079,42 @@ class 
EclassUnquotedVariablesCheck(_UnquotedVariablesCheck):
 def feed(self, eclass):
 for var_name, lines in self._feed(eclass):
 yield EclassUnquotedVariable(var_name, lines=lines, 
eclass=eclass.name)
+
+
+class ExcessiveLineLength(results.LinesResult, results.Style):
+"""Line is longer than 120 characters."""
+
+line_length = 120
+word_length = 110
+
+@property
+def desc(self):
+return f'excessive line length (over {self.line_length} characters) 
{self.lines_str}'
+
+
+class LineLengthCheck(Check):
+"""Scan ebuild for lines with excessive length."""
+
+_source = sources.EbuildFileRepoSource
+known_results = frozenset([ExcessiveLineLength])
+
+def __init__(self, options, **kwargs):
+super().__init__(options, **kwargs)
+self.exception = re.compile(r'\s*(?:DESCRIPTION|KEYWORDS|IUSE)=')
+str_length = f'[^\'\"]{{{ExcessiveLineLength.word_length},}}'
+self.long_string = re.compile(rf'"{str_length}"|\'{str_length}\'')
+
+def feed(self, pkg):
+lines = []
+for lineno, line in enumerate(pkg.lines, 1):
+if len(line) <= ExcessiveLineLength.line_length:
+continue
+if self.exception.match(line):
+continue # exception variables which are fine to be long
+if max(map(len, line.split())) > ExcessiveLineLength.word_length:
+continue # if one part of the line is very long word
+if self.long_string.search(line):
+continue # skip lines with long quoted string
+lines.append(lineno)
+if lines:
+yield ExcessiveLineLength(lines=lines, pkg=pkg)

diff --git a/tests/checks/test_codingstyle.py b/tests/checks/test_codingstyle.py
index 3becc919..1c6a0075 100644
--- a/tests/checks/test_codingstyle.py
+++ b/tests/checks/test_codingstyle.py
@@ -433,3 +433,62 @@ class TestStaticSrcUri(misc.ReportTestCase):
 r = self.assertReport(self.check, 
self._prepare_pkg('Diffball-0.1.2.3', pkgver='Diffball-0.1.2.3'))
 assert r.static_str == 'Diffball-0.1.2.3'
 assert r.replacement == '${P}'
+
+
+class TestExcessiveLineLength(misc.ReportTestCase):
+
+check_kls = codingstyle.LineLengthCheck
+check = check_kls(None)
+word_length = codingstyle.ExcessiveLineLength.word_length
+
+
+@staticmethod
+def _prepare_pkg(*lines: str):
+fake_pkg = misc.FakePkg("dev-util/diffball-0", ebuild=''.join(lines), 
lines=lines)
+data = ''.join(lines).encode()
+return _ParsedPkg(data, pkg=fake_pkg)
+
+def test_normal_length(self):
+self.assertNoReport(self.check, self._prepare_pkg('echo "short line"'))
+
+def test_long_line(self):
+r = self.assertReport(self.check, self._prepare_pkg(f'echo {"a " * 
codingstyle.ExcessiveLineLength.line_length}'))
+assert r.lines == (1, )
+
+def test_multiple_lines(self):
+r = self.assertReport(self.check, self._prepare_pkg(
+f'echo {"a " * codingstyle.ExcessiveLineLength.line_length}',
+'echo "short line"',
+f'echo {"Hello " * codingstyle.ExcessiveLineLength.line_length}',
+))
+assert r.lines == (1, 3)
+
+@pytest.mark.parametrize('variable', ('DESCRIPTION', 'KEYWORDS', 'IUSE'))
+def test_special_variables(self, variable):
+self.assertNoReport(self.check, self._prepare_pkg(
+f'{variable}="{"a " * 
codingstyle.ExcessiveLineLength.line_length}"',
+f'{variable}="{"a " * 
codingstyle.ExcessiveLineLength.line_length}"',
+f'\t\t{variable}="{"a " * 
codingstyle.ExcessiveLineLength.line_length}"',
+))
+
+def test_long_words(self):
+long_word = 'a' * self.word_length + 'b'
+medium_word = 'a' * (self.word_length // 2)
+r = self.assertReport(self.check, self._prepare_pkg(
+f'echo {"a" * codingstyle.ExcessiveLineLength.line_length}',
+f'echo {medium_word} {long_word}',
+f'echo {medium_word} {long_word[:-5]}',
+))
+assert r.lines == (3, )
+
+def