diff options
author | Arthur Zamarin <arthurzam@gentoo.org> | 2022-05-04 20:08:36 +0300 |
---|---|---|
committer | Arthur Zamarin <arthurzam@gentoo.org> | 2022-05-05 20:27:49 +0300 |
commit | 9ed5db0a2c63c105feefb124d290949f54a1a86c (patch) | |
tree | 1c83187bdf43e199bb7ea2f4a4fc992723a813b0 | |
parent | Add documentation for configuration (diff) | |
download | pkgdev-9ed5db0a2c63c105feefb124d290949f54a1a86c.tar.gz pkgdev-9ed5db0a2c63c105feefb124d290949f54a1a86c.tar.bz2 pkgdev-9ed5db0a2c63c105feefb124d290949f54a1a86c.zip |
pkgdev manifest: add --if-modified
Restrict targets for manifest to only targets that have uncommitted
modifications.
Resolves: https://github.com/pkgcore/pkgdev/issues/65
Signed-off-by: Arthur Zamarin <arthurzam@gentoo.org>
-rw-r--r-- | completion/bash/pkgdev | 1 | ||||
-rw-r--r-- | completion/zsh/_pkgdev | 1 | ||||
-rw-r--r-- | src/pkgdev/scripts/pkgdev_manifest.py | 41 | ||||
-rw-r--r-- | tests/scripts/test_pkgdev_manifest.py | 50 |
4 files changed, 86 insertions, 7 deletions
diff --git a/completion/bash/pkgdev b/completion/bash/pkgdev index bd89f2b..1f11a28 100644 --- a/completion/bash/pkgdev +++ b/completion/bash/pkgdev @@ -98,6 +98,7 @@ _pkgdev() { -f --force -m --mirrors -d --distdir + --if-modified " case "${prev}" in diff --git a/completion/zsh/_pkgdev b/completion/zsh/_pkgdev index ddba6b2..c363596 100644 --- a/completion/zsh/_pkgdev +++ b/completion/zsh/_pkgdev @@ -59,6 +59,7 @@ case $state in {'(--distdir)-d','(-d)--distdir'}'[target download directory]:distdir:_files -/' \ {'(--force)-f','(-f)--force'}'[forcibly remanifest packages]' \ {'(--mirrors)-m','(-m)--mirrors'}'[enable fetching from Gentoo mirrors]' \ + '--if-modified[only check packages that have uncommitted modifications]' \ && ret=0 ;; (mask) diff --git a/src/pkgdev/scripts/pkgdev_manifest.py b/src/pkgdev/scripts/pkgdev_manifest.py index 26f6534..76dc69a 100644 --- a/src/pkgdev/scripts/pkgdev_manifest.py +++ b/src/pkgdev/scripts/pkgdev_manifest.py @@ -1,11 +1,13 @@ import os +import re +import subprocess from pkgcore.operations import observer as observer_mod from pkgcore.restrictions import packages from pkgcore.util.parserestrict import parse_match from snakeoil.cli import arghparse -from .. import cli +from .. import cli, git from .argparsers import cwd_repo_argparser manifest = cli.ArgumentParser( @@ -43,17 +45,21 @@ manifest_opts.add_argument( default because manifest generation is often performed when adding new ebuilds with distfiles that aren't on Gentoo mirrors yet. """) +manifest_opts.add_argument( + '--if-modified', dest='if_modified', help='Only check packages that have uncommitted modifications', + action='store_true', + docs=""" + In addition to matching the specified restriction, restrict to targets + which are marked as modified by git, including untracked files. + """) -@manifest.bind_final_check -def _manifest_validate(parser, namespace): - targets = namespace.target if namespace.target else [namespace.cwd] +def _restrict_targets(repo, targets): restrictions = [] - for target in targets: if os.path.exists(target): try: - restrictions.append(namespace.repo.path_restrict(target)) + restrictions.append(repo.path_restrict(target)) except ValueError as e: manifest.error(e) else: @@ -61,8 +67,29 @@ def _manifest_validate(parser, namespace): restrictions.append(parse_match(target)) except ValueError: manifest.error(f'invalid atom: {target!r}') + return packages.OrRestriction(*restrictions) + + +def _restrict_modified_files(repo): + ebuild_re = re.compile(r'^[ MTARC?]{2} (?P<path>[^/]+/[^/]+/[^/]+\.ebuild)$') + p = git.run('status', '--porcelain=v1', '-z', "*.ebuild", + cwd=repo.location, stdout=subprocess.PIPE) + + restrictions = [] + for line in p.stdout.strip('\x00').split('\x00'): + if mo := ebuild_re.match(line): + restrictions.append(repo.path_restrict(mo.group('path'))) + return packages.OrRestriction(*restrictions) + + +@manifest.bind_final_check +def _manifest_validate(parser, namespace): + targets = namespace.target if namespace.target else [namespace.cwd] - namespace.restriction = packages.OrRestriction(*restrictions) + namespace.restriction = _restrict_targets(namespace.repo, targets) + if namespace.if_modified: + namespace.restriction = packages.AndRestriction(namespace.restriction, + _restrict_modified_files(namespace.repo)) @manifest.bind_main_func diff --git a/tests/scripts/test_pkgdev_manifest.py b/tests/scripts/test_pkgdev_manifest.py index 1131ff7..696a2f2 100644 --- a/tests/scripts/test_pkgdev_manifest.py +++ b/tests/scripts/test_pkgdev_manifest.py @@ -1,4 +1,5 @@ from functools import partial +from typing import Set from unittest.mock import patch import pytest @@ -44,6 +45,55 @@ class TestPkgdevManifestParseArgs: matches = [x.cpvstr for x in repo.itermatch(options.restriction)] assert matches == ['cat/pkg-0'] + def test_if_modified_target(self, repo, make_git_repo, tool): + def manifest_matches() -> Set[str]: + repo.sync() + with chdir(repo.location): + options, _ = tool.parse_args(['manifest', '--if-modified']) + return {x.cpvstr for x in repo.itermatch(options.restriction)} + + git_repo = make_git_repo(repo.location) + repo.create_ebuild('cat/oldpkg-0') + git_repo.add_all('cat/oldpkg-0') + + # New package + repo.create_ebuild('cat/newpkg-0') + assert manifest_matches() == {'cat/newpkg-0'} + git_repo.add_all('cat/newpkg-0') + + # Untracked file + ebuild_path = repo.create_ebuild('cat/newpkg-1') + assert manifest_matches() == {'cat/newpkg-1'} + + # Staged file + git_repo.add(ebuild_path, commit=False) + assert manifest_matches() == {'cat/newpkg-1'} + + # No modified files + git_repo.add_all('cat/newpkg-1') + assert manifest_matches() == set() + + # Modified file + ebuild_path = repo.create_ebuild('cat/newpkg-1', eapi=8) + assert manifest_matches() == {'cat/newpkg-1'} + git_repo.add_all('cat/newpkg-1: eapi 8') + + # Renamed file + git_repo.remove(ebuild_path, commit=False) + ebuild_path = repo.create_ebuild('cat/newpkg-2') + git_repo.add(ebuild_path, commit=False) + assert manifest_matches() == {'cat/newpkg-2'} + git_repo.add_all('cat/newpkg-2: rename') + + # Deleted file + git_repo.remove(ebuild_path, commit=False) + assert manifest_matches() == set() + + # Deleted package + ebuild_path = repo.create_ebuild('cat/newpkg-0') + git_repo.remove(ebuild_path, commit=False) + assert manifest_matches() == set() + def test_non_repo_dir_target(self, tmp_path, repo, capsys, tool): with pytest.raises(SystemExit) as excinfo, \ chdir(repo.location): |