aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur Zamarin <arthurzam@gentoo.org>2022-05-04 20:08:36 +0300
committerArthur Zamarin <arthurzam@gentoo.org>2022-05-05 20:27:49 +0300
commit9ed5db0a2c63c105feefb124d290949f54a1a86c (patch)
tree1c83187bdf43e199bb7ea2f4a4fc992723a813b0
parentAdd documentation for configuration (diff)
downloadpkgdev-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/pkgdev1
-rw-r--r--completion/zsh/_pkgdev1
-rw-r--r--src/pkgdev/scripts/pkgdev_manifest.py41
-rw-r--r--tests/scripts/test_pkgdev_manifest.py50
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):