Skip to content

Commit 15cff72

Browse files
committed
GitCommitMessageCheck: flag pkg additions missing versions in the summary
Fixes #298.
1 parent fdb69e4 commit 15cff72

4 files changed

Lines changed: 58 additions & 26 deletions

File tree

src/pkgcheck/addons/git.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
import re
66
import shlex
77
import subprocess
8-
from collections import deque
8+
from collections import defaultdict, deque
99
from dataclasses import dataclass
1010
from datetime import datetime
1111
from functools import partial
12-
from itertools import chain, takewhile
12+
from itertools import takewhile
1313

1414
from pathspec import PathSpec
1515
from pkgcore.ebuild import cpv
@@ -21,7 +21,7 @@
2121
from snakeoil.cli import arghparse
2222
from snakeoil.contexts import GitStash
2323
from snakeoil.klass import jit_attr
24-
from snakeoil.mappings import OrderedSet
24+
from snakeoil.mappings import ImmutableDict, OrderedSet
2525
from snakeoil.osutils import pjoin
2626
from snakeoil.process import CommandNotFound, find_binary
2727
from snakeoil.strings import pluralism
@@ -41,7 +41,7 @@ class GitCommit:
4141
author: str
4242
committer: str
4343
message: tuple
44-
pkgs: tuple = ()
44+
pkgs: ImmutableDict = ImmutableDict()
4545

4646
def __str__(self):
4747
return self.hash
@@ -180,8 +180,15 @@ def __next__(self):
180180
author = next(self.git_log)
181181
committer = next(self.git_log)
182182
message = list(takewhile(lambda x: x != '\x00', self.git_log))
183-
pkgs = list(chain.from_iterable(pkgs for _, pkgs in self.changes))
184-
return GitCommit(commit_hash, commit_time, author, committer, message, pkgs)
183+
pkgs = defaultdict(set)
184+
for status, atoms in self.changes:
185+
if status == 'R':
186+
old, new = atoms
187+
pkgs['A'].add(new)
188+
pkgs['D'].add(old)
189+
else:
190+
pkgs[status].update(atoms)
191+
return GitCommit(commit_hash, commit_time, author, committer, message, ImmutableDict(pkgs))
185192

186193

187194
class GitRepoPkgs(_ParseGitRepo):

src/pkgcheck/checks/git.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -562,18 +562,24 @@ def feed(self, commit):
562562

563563
# categorize package changes
564564
pkg_changes = defaultdict(set)
565-
for pkg in commit.pkgs:
566-
pkg_changes[pkg.category].add(pkg.package)
565+
for atom in chain.from_iterable(commit.pkgs.values()):
566+
pkg_changes[atom.category].add(atom)
567567

568568
# check git commit summary formatting
569569
if len(pkg_changes) == 1:
570-
category, pkgs = pkg_changes.popitem()
571-
if len(pkgs) == 1:
570+
category, atoms = pkg_changes.popitem()
571+
if len({x.package for x in atoms}) == 1:
572572
# changes to a single cat/pn
573-
pkg = commit.pkgs[0]
574-
if not re.match(rf'^({re.escape(pkg.key)}|{re.escape(pkg.cpvstr)}): ', summary):
575-
error = f'summary missing {pkg.key!r} package prefix'
573+
atom = next(iter(atoms))
574+
if not re.match(rf'^({re.escape(atom.key)}|{re.escape(atom.cpvstr)}): ', summary):
575+
error = f'summary missing {atom.key!r} package prefix'
576576
yield BadCommitSummary(error, summary, commit=commit)
577+
# check for version in summary for singular version bumps
578+
if len(commit.pkgs['A']) == 1:
579+
version = next(iter(commit.pkgs['A'])).version
580+
if not re.match(rf'^.+\b{version}\b.*$', summary):
581+
error = f'summary missing package version {version!r}'
582+
yield BadCommitSummary(error, summary, commit=commit)
577583
else:
578584
# mutiple pkg changes in the same category
579585
if not re.match(rf'^{re.escape(category)}: ', summary):

tests/addons/test_git.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -250,15 +250,15 @@ def test_parsing(self, make_repo, make_git_repo):
250250
commits = list(git.GitRepoCommits(path, 'HEAD'))
251251
assert len(commits) == 1
252252
assert commits[0].message == ['foo']
253-
assert commits[0].pkgs == []
253+
assert commits[0].pkgs == {}
254254
orig_commit = commits[0]
255255

256256
# make another commit
257257
git_repo.add('bar', msg='bar', create=True)
258258
commits = list(git.GitRepoCommits(path, 'HEAD'))
259259
assert len(commits) == 2
260260
assert commits[0].message == ['bar']
261-
assert commits[0].pkgs == []
261+
assert commits[0].pkgs == {}
262262
assert commits[1] == orig_commit
263263
assert len(set(commits)) == 2
264264

@@ -268,7 +268,7 @@ def test_parsing(self, make_repo, make_git_repo):
268268
commits = list(git.GitRepoCommits(path, 'HEAD'))
269269
assert len(commits) == 3
270270
assert commits[0].message == ['cat/pkg-0']
271-
assert commits[0].pkgs == [atom_cls('=cat/pkg-0')]
271+
assert commits[0].pkgs == {'A': {atom_cls('=cat/pkg-0')}}
272272

273273
# make a multiple pkg commit
274274
repo.create_ebuild('newcat/newpkg-0')
@@ -277,19 +277,23 @@ def test_parsing(self, make_repo, make_git_repo):
277277
commits = list(git.GitRepoCommits(path, 'HEAD'))
278278
assert len(commits) == 4
279279
assert commits[0].message == ['newcat: various updates']
280-
assert commits[0].pkgs == [atom_cls('=newcat/newpkg-0'), atom_cls('=newcat/newpkg-1')]
280+
assert commits[0].pkgs == {
281+
'A': {atom_cls('=newcat/newpkg-0'), atom_cls('=newcat/newpkg-1')}}
281282

282283
# remove the old version
283284
git_repo.remove('newcat/newpkg/newpkg-0.ebuild')
284285
commits = list(git.GitRepoCommits(path, 'HEAD'))
285286
assert len(commits) == 5
286-
assert commits[0].pkgs == [atom_cls('=newcat/newpkg-0')]
287+
assert commits[0].pkgs == {'D': {atom_cls('=newcat/newpkg-0')}}
287288

288289
# rename the pkg
289290
git_repo.move('newcat', 'newcat2')
290291
commits = list(git.GitRepoCommits(path, 'HEAD'))
291292
assert len(commits) == 6
292-
assert commits[0].pkgs == [atom_cls('=newcat/newpkg-1'), atom_cls('=newcat2/newpkg-1')]
293+
assert commits[0].pkgs == {
294+
'A': {atom_cls('=newcat2/newpkg-1')},
295+
'D': {atom_cls('=newcat/newpkg-1')},
296+
}
293297

294298
# malformed atoms don't show up as pkgs
295299
repo.create_ebuild('cat/pkg-3')
@@ -298,7 +302,7 @@ def test_parsing(self, make_repo, make_git_repo):
298302
fake_atom.side_effect = MalformedAtom('bad atom')
299303
commits = list(git.GitRepoCommits(path, 'HEAD'))
300304
assert len(commits) == 7
301-
assert commits[0].pkgs == []
305+
assert commits[0].pkgs == {}
302306

303307

304308
class TestGitRepoPkgs:

tests/checks/test_git.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -285,14 +285,29 @@ def test_bad_commit_summary_pkg(self):
285285

286286
# poorly prefixed commit summary
287287
self.child_repo.create_ebuild('cat/pkg-4')
288-
self.child_git_repo.add_all('version bump', signoff=True)
289-
commit = self.child_git_repo.HEAD
288+
self.child_git_repo.add_all('version bump to 4', signoff=True)
289+
commit1 = self.child_git_repo.HEAD
290+
# commit summary missing package version
291+
self.child_repo.create_ebuild('cat/pkg-5')
292+
self.child_git_repo.add_all('cat/pkg: version bump', signoff=True)
293+
commit2 = self.child_git_repo.HEAD
294+
# commit summary missing renamed package version
295+
self.child_git_repo.move(
296+
'cat/pkg/pkg-3.ebuild', 'cat/pkg/pkg-6.ebuild',
297+
msg='cat/pkg: version bump and remove old', signoff=True)
298+
commit3 = self.child_git_repo.HEAD
290299
self.init_check()
291-
r = self.assertReport(self.check, self.source)
292-
expected = git_mod.BadCommitSummary(
300+
results = self.assertReports(self.check, self.source)
301+
r1 = git_mod.BadCommitSummary(
293302
"summary missing 'cat/pkg' package prefix",
294-
'version bump', commit=commit)
295-
assert r == expected
303+
'version bump to 4', commit=commit1)
304+
r2 = git_mod.BadCommitSummary(
305+
"summary missing package version '5'",
306+
'cat/pkg: version bump', commit=commit2)
307+
r3 = git_mod.BadCommitSummary(
308+
"summary missing package version '6'",
309+
'cat/pkg: version bump and remove old', commit=commit3)
310+
assert set(results) == {r1, r2, r3}
296311

297312
def test_bad_commit_summary_category(self):
298313
# properly prefixed commit summary

0 commit comments

Comments
 (0)