App.__get_project_refs(): Fix broken detection of missing build dependencies #94
2 changed files with 77 additions and 10 deletions
|
|
@ -21,7 +21,7 @@ if TYPE_CHECKING:
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from typing import TypeAlias
|
from typing import Iterable, TypeAlias
|
||||||
|
|
||||||
from .lib.PackageFilter import PackageFilter
|
from .lib.PackageFilter import PackageFilter
|
||||||
|
|
||||||
|
|
@ -77,12 +77,17 @@ class App(Base):
|
||||||
raise Exception('Tried to access undefined pretty top directory')
|
raise Exception('Tried to access undefined pretty top directory')
|
||||||
return self.___pretty_topdir
|
return self.___pretty_topdir
|
||||||
|
|
||||||
def __proj_dir(self, name: str, pretty: bool) -> str | None:
|
def __proj_dir(
|
||||||
|
self,
|
||||||
|
name: str,
|
||||||
|
pretty: bool,
|
||||||
|
projs_roots: Iterable[str | None] | None = None,
|
||||||
|
) -> str | None:
|
||||||
if name == self.__top_name:
|
if name == self.__top_name:
|
||||||
if pretty:
|
if pretty:
|
||||||
return self.__pretty_topdir
|
return self.__pretty_topdir
|
||||||
return self.__topdir
|
return self.__topdir
|
||||||
for d in [self.__projs_root, self.___opt_root]:
|
for d in projs_roots or [self.__projs_root, self.___opt_root]:
|
||||||
if d is None:
|
if d is None:
|
||||||
continue
|
continue
|
||||||
ret = d + '/' + name
|
ret = d + '/' + name
|
||||||
|
|
@ -93,12 +98,36 @@ class App(Base):
|
||||||
return None
|
return None
|
||||||
raise Exception('No project path found for module "{}"'.format(name))
|
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.
|
||||||
|
if devel and name == self.__top_name:
|
||||||
|
# the topdir is the project's own buildable checkout
|
||||||
|
if os.path.exists(f'{self.__topdir}/make/project.conf'):
|
||||||
|
return True
|
||||||
|
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(
|
def __find_dir(
|
||||||
self,
|
self,
|
||||||
name: str,
|
name: str,
|
||||||
search_subdirs: list[str] | None = None,
|
search_subdirs: list[str] | None = None,
|
||||||
search_absdirs: list[str] | None = None,
|
search_absdirs: list[str] | None = None,
|
||||||
pretty: bool = True,
|
pretty: bool = True,
|
||||||
|
projs_roots: Iterable[str | None] | None = None,
|
||||||
) -> str | None:
|
) -> str | None:
|
||||||
if search_subdirs is None:
|
if search_subdirs is None:
|
||||||
search_subdirs = []
|
search_subdirs = []
|
||||||
|
|
@ -134,7 +163,7 @@ class App(Base):
|
||||||
f'Tried to pretty-format directory {pd}, not implemented'
|
f'Tried to pretty-format directory {pd}, not implemented'
|
||||||
)
|
)
|
||||||
|
|
||||||
pd = self.__proj_dir(name, False)
|
pd = self.__proj_dir(name, pretty = False, projs_roots = projs_roots)
|
||||||
if pd is None:
|
if pd is None:
|
||||||
return None
|
return None
|
||||||
if not search_subdirs and not search_absdirs:
|
if not search_subdirs and not search_absdirs:
|
||||||
|
|
@ -181,6 +210,7 @@ class App(Base):
|
||||||
names_only: bool,
|
names_only: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
name = self.strip_module_from_spec(spec)
|
name = self.strip_module_from_spec(spec)
|
||||||
|
mod = re.split('([=><]+)', spec)[0].strip()
|
||||||
if names_only:
|
if names_only:
|
||||||
spec = name
|
spec = name
|
||||||
if spec in buf:
|
if spec in buf:
|
||||||
|
|
@ -190,6 +220,15 @@ class App(Base):
|
||||||
buf.append(spec)
|
buf.append(spec)
|
||||||
return
|
return
|
||||||
visited.add(spec)
|
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)
|
vals = self.get_value(name, section, key)
|
||||||
log(
|
log(
|
||||||
DEBUG,
|
DEBUG,
|
||||||
|
|
@ -398,6 +437,18 @@ class App(Base):
|
||||||
raise Exception('No distro object')
|
raise Exception('No distro object')
|
||||||
return self.__distro
|
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(
|
def find_dir(
|
||||||
self,
|
self,
|
||||||
name: str,
|
name: str,
|
||||||
|
|
@ -405,8 +456,9 @@ class App(Base):
|
||||||
search_absdirs: list[str] | None = None,
|
search_absdirs: list[str] | None = None,
|
||||||
pretty: bool = True,
|
pretty: bool = True,
|
||||||
throw: bool = False,
|
throw: bool = False,
|
||||||
|
projs_roots: Iterable[str | None] | None = None,
|
||||||
) -> str | None:
|
) -> str | None:
|
||||||
ret = self.__find_dir(name, search_subdirs, search_absdirs, pretty)
|
ret = self.__find_dir(name, search_subdirs, search_absdirs, pretty, projs_roots)
|
||||||
if ret is not None:
|
if ret is not None:
|
||||||
return ret
|
return ret
|
||||||
if not throw:
|
if not throw:
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,14 @@ class CmdBuild(Cmd): # export
|
||||||
@override
|
@override
|
||||||
async def _run(self, args: Namespace) -> None:
|
async def _run(self, args: Namespace) -> None:
|
||||||
|
|
||||||
|
@lru_cache(maxsize = None)
|
||||||
|
def proj_dir(module: str) -> str | None:
|
||||||
|
return self.app.find_dir(
|
||||||
|
module,
|
||||||
|
pretty = False,
|
||||||
|
projs_roots = [self.app.projs_root],
|
||||||
|
)
|
||||||
|
|
||||||
@lru_cache(maxsize = None)
|
@lru_cache(maxsize = None)
|
||||||
def read_deps(cur: str, dep_flavour: str) -> list[str]:
|
def read_deps(cur: str, dep_flavour: str) -> list[str]:
|
||||||
# dep cache doesn't make a difference at all
|
# dep cache doesn't make a difference at all
|
||||||
|
|
@ -172,20 +180,27 @@ class CmdBuild(Cmd): # export
|
||||||
dep_tree[k].remove(d)
|
dep_tree[k].remove(d)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
def log_skip(module: str, msg: str) -> None:
|
||||||
|
title = f'---- {module}'
|
||||||
|
log(NOTICE, f',{title} >')
|
||||||
|
log(NOTICE, f'| {msg}<')
|
||||||
|
log(NOTICE, f'`{title} <')
|
||||||
|
|
||||||
async def run_make(
|
async def run_make(
|
||||||
module: str, target: str, cur_project: int, num_projects: int
|
module: str, target: str, cur_project: int, num_projects: int
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
patt = self.app.is_excluded_from_build(module)
|
patt = self.app.is_excluded_from_build(module)
|
||||||
if patt is not None:
|
if patt is not None:
|
||||||
title = f'---- {module}'
|
log_skip(module, f'Configured to skip build on platform >{patt}<')
|
||||||
log(NOTICE, f',{title} >')
|
return
|
||||||
log(NOTICE, f'| Configured to skip build on platform >{patt}<')
|
|
||||||
log(NOTICE, f'`{title} <')
|
wd = proj_dir(module)
|
||||||
|
if wd is None:
|
||||||
|
log_skip(module, 'Skipping: No buildable project directory')
|
||||||
return
|
return
|
||||||
|
|
||||||
make_cmd = ['make', target]
|
make_cmd = ['make', target]
|
||||||
wd = self.app.find_dir(module, pretty = False)
|
|
||||||
title = '---- [%d/%d]: Running "%s" in %s -' % (
|
title = '---- [%d/%d]: Running "%s" in %s -' % (
|
||||||
cur_project,
|
cur_project,
|
||||||
num_projects,
|
num_projects,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue