Compare commits

...
Author SHA1 Message Date
c52453dc68
App.__get_project_refs(): Fix recursion stop conditions
Some checks failed
CI / Packaging - Kali Linux (pull_request) Failing after 4m22s
CI / Packaging - OpenSUSE Tumbleweed (pull_request) Failing after 4m25s
CI / Packaging test (pull_request) Failing after 0s
App.__get_project_refs() recurses into the package dependency graph, but
the recursion end conditions only work well if all required packages are
present. Whether a required package is installed or not is decided upon a
wrong condition, however - existence of the project's project directory,
which may or may not be misleading for both the -devel and the -run
requirements. This can lead to various unwanted outcomes: Missing packages
happily inserted into the recursion buffer, process termination instead of
recursion stop, path lookup errors instead of a clearer "unmet dependency"
message (No project path found for module xyz, Failed to find directory of
project foo).

This commit cleanly detects if -run or -devel are installed and makes the
walk stop or raise under the appropriate conditions:

1. -run missing but required, raises unmet dependency
2. -devel missing but required, raises unmet dependency
3. -run present, no -devel required, stop recursing

Signed-off-by: Jan Lindemann <jan@janware.com>
Assisted-by: unsloth/Qwen3.8-27B-GGUF:Q4_K_M with pi.dev v0.85.1
2026-09-10 11:44:25 +02:00
c038676366
App.is_installed(): Add method
The installed state of a project is judged by the proofs of installation,
which differ per subpackage: make/project.conf in the dev tree or /opt
proves the -devel package or a buildable checkout, a VERSION file in the
project directory or /usr/share/doc/packages the -run package.

Add is_installed(), which answers the proof question for a given subpackage
by searching the per-subpackage locations.

Signed-off-by: Jan Lindemann <jan@janware.com>
Assisted-by: unsloth/Qwen3.8-27B-GGUF:Q4_K_M with pi.dev v0.84.2
2026-09-10 11:44:25 +02:00

View file

@ -98,6 +98,25 @@ class App(Base):
return None
raise Exception('No project path found for module "{}"'.format(name))
@cache
def __is_installed(self, name: str, devel: bool) -> bool:
# devel: the project is in the dev tree or the -devel
# package is installed: make/project.conf is present.
# run: the -run package is installed: a VERSION file is
# present in the project directory or
# /usr/share/doc/packages.
search, file = (
(self.__projs_root, self.___opt_root),
'/make/project.conf'
) if devel else (
(self.__projs_root, '/usr/share/doc/packages'),
'/VERSION'
)
for root in search:
if root is not None and os.path.exists(f'{root}/{name}{file}'):
return True
return False
def __find_dir(
self,
name: str,
@ -187,6 +206,7 @@ class App(Base):
names_only: bool,
) -> None:
name = self.strip_module_from_spec(spec)
mod = re.split('([=><]+)', spec)[0].strip()
if names_only:
spec = name
if spec in buf:
@ -196,6 +216,15 @@ class App(Base):
buf.append(spec)
return
visited.add(spec)
needed_subpackage = 'devel' if mod.endswith(('-dev', '-devel')) else 'run'
if not self.is_installed(name, devel = True):
if not mod.endswith(('-dev', '-devel')):
if self.is_installed(name, devel = False):
return
raise Exception(
f'Unmet dependency on {mod}: the -{needed_subpackage} package '
f'of project {name} is not installed'
)
vals = self.get_value(name, section, key)
log(
DEBUG,
@ -404,6 +433,18 @@ class App(Base):
raise Exception('No distro object')
return self.__distro
def is_installed(
self,
name: str,
devel: bool = False,
) -> bool:
"""True if the project is installed: for devel,
make/project.conf is present in the dev tree or /opt; for
run, a VERSION file is present in the project directory
or /usr/share/doc/packages.
"""
return self.__is_installed(name, devel)
def find_dir(
self,
name: str,