fix: handle permissionerror during walking over tree

Previously it tried to look into 700 directories (e.g. .gnupg) which
breaks running as non-ahriman user
This commit is contained in:
2026-02-02 17:13:30 +02:00
parent 799dc73d8a
commit 43856b500a
3 changed files with 29 additions and 3 deletions

View File

@@ -431,6 +431,22 @@ def safe_filename(source: str) -> str:
return re.sub(r"[^A-Za-z\d\-._~:\[\]@]", "-", source) return re.sub(r"[^A-Za-z\d\-._~:\[\]@]", "-", source)
def safe_iterdir(path: Path) -> Iterator[Path]:
"""
wrapper around :func:`pathlib.Path.iterdir`, which suppresses :exc:`PermissionError`
Args:
path(Path): path to iterate
Yields:
Path: content of the directory
"""
try:
yield from path.iterdir()
except PermissionError:
pass
def srcinfo_property(key: str, srcinfo: Mapping[str, Any], package_srcinfo: Mapping[str, Any], *, def srcinfo_property(key: str, srcinfo: Mapping[str, Any], package_srcinfo: Mapping[str, Any], *,
default: Any = None) -> Any: default: Any = None) -> Any:
""" """

View File

@@ -279,14 +279,16 @@ class RepositoryPaths(LazyLogging):
Note, however, that this method doesn't handle any exceptions and will eventually interrupt Note, however, that this method doesn't handle any exceptions and will eventually interrupt
if there will be any. if there will be any.
""" """
from ahriman.core.utils import safe_iterdir
path = path or self.root path = path or self.root
def walk(root: Path) -> Iterator[Path]: def walk(root: Path) -> Iterator[Path]:
# basically walk, but skipping some content # basically walk, but skipping some content
for child in root.iterdir(): for child in safe_iterdir(root):
yield child yield child
if child in (self.chroot.parent,): if child in (self.chroot.parent,):
yield from child.iterdir() # we only yield top-level in chroot directory yield from safe_iterdir(child) # we only yield top-level in chroot directory
elif child.is_dir(): elif child.is_dir():
yield from walk(child) yield from walk(child)

View File

@@ -11,7 +11,7 @@ from unittest.mock import call as MockCall
from ahriman.core.exceptions import BuildError, CalledProcessError, OptionError, UnsafeRunError from ahriman.core.exceptions import BuildError, CalledProcessError, OptionError, UnsafeRunError
from ahriman.core.utils import check_output, check_user, dataclass_view, enum_values, extract_user, filter_json, \ from ahriman.core.utils import check_output, check_user, dataclass_view, enum_values, extract_user, filter_json, \
full_version, minmax, package_like, parse_version, partition, pretty_datetime, pretty_interval, pretty_size, \ full_version, minmax, package_like, parse_version, partition, pretty_datetime, pretty_interval, pretty_size, \
safe_filename, srcinfo_property, srcinfo_property_list, trim_package, utcnow, walk safe_filename, safe_iterdir, srcinfo_property, srcinfo_property_list, trim_package, utcnow, walk
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.package_source import PackageSource from ahriman.models.package_source import PackageSource
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId
@@ -426,6 +426,14 @@ def test_safe_filename() -> None:
assert safe_filename("tolua++-1.0.93-4-x86_64.pkg.tar.zst") == "tolua---1.0.93-4-x86_64.pkg.tar.zst" assert safe_filename("tolua++-1.0.93-4-x86_64.pkg.tar.zst") == "tolua---1.0.93-4-x86_64.pkg.tar.zst"
def test_safe_iterdir(mocker: MockerFixture) -> None:
"""
must suppress PermissionError
"""
iterdir_mock = mocker.patch("pathlib.Path.iterdir", side_effect=PermissionError)
assert list(safe_iterdir(Path("root"))) == []
def test_srcinfo_property() -> None: def test_srcinfo_property() -> None:
""" """
must correctly extract properties must correctly extract properties