feat: replace scan paths options to single one

It has been found that previous system didn't allow to configure
specific cases (e.g. a whitelisted directory inside /usr/lib/cmake). The
current solution replaces two options to single one, which also allows a
regular expressions

Also PackageArchive class has been moved to core package, because it is
more about service rather than model
This commit is contained in:
2024-08-25 16:22:11 +03:00
parent 16308dc3ae
commit 69f0966ff1
19 changed files with 141 additions and 155 deletions

View File

@ -17,7 +17,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from dataclasses import dataclass
from elftools.elf.dynamic import DynamicSection
from elftools.elf.elffile import ELFFile
from pathlib import Path
@ -33,7 +32,6 @@ from ahriman.models.package import Package
from ahriman.models.scan_paths import ScanPaths
@dataclass
class PackageArchive:
"""
helper for package archives
@ -45,10 +43,20 @@ class PackageArchive:
scan_paths(ScanPaths): scan paths holder
"""
root: Path
package: Package
pacman: Pacman
scan_paths: ScanPaths
def __init__(self, root: Path, package: Package, pacman: Pacman, scan_paths: ScanPaths) -> None:
"""
default constructor
Args:
root(Path): path to root filesystem
package(Package): package descriptor
pacman(Pacman): alpm wrapper instance
scan_paths(ScanPaths): scan paths holder
"""
self.root = root
self.package = package
self.pacman = pacman
self.scan_paths = scan_paths
@staticmethod
def dynamic_needed(binary_path: Path) -> list[str]:

View File

@ -169,14 +169,6 @@ CONFIGURATION_SCHEMA: ConfigurationSchema = {
"build": {
"type": "dict",
"schema": {
"allowed_scan_paths": {
"type": "list",
"coerce": "list",
"schema": {
"type": "path",
"coerce": "absolute_path",
},
},
"archbuild_flags": {
"type": "list",
"coerce": "list",
@ -185,14 +177,6 @@ CONFIGURATION_SCHEMA: ConfigurationSchema = {
"empty": False,
},
},
"blacklisted_scan_paths": {
"type": "list",
"coerce": "list",
"schema": {
"type": "path",
"coerce": "absolute_path",
},
},
"build_command": {
"type": "string",
"required": True,
@ -226,6 +210,14 @@ CONFIGURATION_SCHEMA: ConfigurationSchema = {
"empty": False,
},
},
"scan_paths": {
"type": "list",
"coerce": "list",
"schema": {
"type": "string",
"empty": False,
},
},
"triggers": {
"type": "list",
"coerce": "list",

View File

@ -23,13 +23,13 @@ from collections.abc import Iterable
from pathlib import Path
from tempfile import TemporaryDirectory
from ahriman.core.build_tools.package_archive import PackageArchive
from ahriman.core.build_tools.task import Task
from ahriman.core.repository.cleaner import Cleaner
from ahriman.core.repository.package_info import PackageInfo
from ahriman.core.utils import safe_filename
from ahriman.models.changes import Changes
from ahriman.models.package import Package
from ahriman.models.package_archive import PackageArchive
from ahriman.models.package_description import PackageDescription
from ahriman.models.packagers import Packagers
from ahriman.models.result import Result

View File

@ -80,10 +80,7 @@ class RepositoryProperties(LazyLogging):
self.reporter = Client.load(repository_id, configuration, database, report=report)
self.triggers = TriggerLoader.load(repository_id, configuration)
self.scan_paths = ScanPaths(
allowed_paths=configuration.getpathlist("build", "allowed_scan_paths", fallback=[]),
blacklisted_paths=configuration.getpathlist("build", "blacklisted_scan_paths", fallback=[]),
)
self.scan_paths = ScanPaths(configuration.getlist("build", "scan_paths", fallback=[]))
@property
def architecture(self) -> str:

View File

@ -17,29 +17,33 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import re
from dataclasses import dataclass
from functools import cached_property
from pathlib import Path
@dataclass(frozen=True, kw_only=True)
@dataclass(frozen=True)
class ScanPaths:
"""
paths used for scan filesystem
Attributes:
allowed_paths(list[Path]): list of whitelisted paths
blacklisted_paths(list[Path]): list of paths to be skipped from scan
paths(list[str]): list of regular expressions to be used to match paths
"""
allowed_paths: list[Path]
blacklisted_paths: list[Path]
paths: list[str]
def __post_init__(self) -> None:
@cached_property
def patterns(self) -> list[re.Pattern[str]]:
"""
compute relative to / paths
compiled regular expressions
Returns:
list[re.Pattern]: a list of compiled regular expressions
"""
object.__setattr__(self, "allowed_paths", [path.relative_to("/") for path in self.allowed_paths])
object.__setattr__(self, "blacklisted_paths", [path.relative_to("/") for path in self.blacklisted_paths])
return [re.compile(path) for path in self.paths]
def is_allowed(self, path: Path) -> bool:
"""
@ -49,10 +53,7 @@ class ScanPaths:
path(Path): path to be checked
Returns:
bool: ``True`` in case if :attr:`allowed_paths` contains element which is parent for the path and
:attr:`blacklisted_paths` doesn't and ``False`` otherwise
bool: ``True`` in case if :attr:`paths` contains at least one element to which the path is matched
and ``False`` otherwise
"""
if any(path.is_relative_to(blacklisted) for blacklisted in self.blacklisted_paths):
return False # path is blacklisted
# check if we actually have to check this path
return any(path.is_relative_to(allowed) for allowed in self.allowed_paths)
return any(pattern.match(str(path)) for pattern in self.patterns)