- Introduce explicit CLI layer model (os-packages, nix, python, makefile) and central InstallationPipeline to orchestrate installers. - Move installer orchestration out of install_repos() into pkgmgr.actions.repository.install.pipeline, using layer precedence and capability tracking. - Add pkgmgr.actions.repository.install.layers to classify commands into layers and compare priorities. - Rework PythonInstaller to always use isolated environments: PKGMGR_PIP override → active venv → per-repo venv under ~/.venvs/<identifier>, avoiding system Python and PEP 668 conflicts. - Adjust NixFlakeInstaller to install flake outputs based on repository identity: pkgmgr/package-manager → pkgmgr (mandatory) + default (optional), all other repos → default (mandatory). - Tighten MakefileInstaller behaviour, add global PKGMGR_DISABLE_MAKEFILE_INSTALLER switch, and simplify install target detection. - Rewrite resolve_command_for_repo() with explicit Repository typing, better Python package detection, Nix/PATH resolution, and a library-only fallback instead of raising on missing CLI. - Update flake.nix devShell to provide python3 with pip and add pip as a propagated build input. - Remove deprecated/wip repository entries from config defaults and drop the unused config/wip.yml. https://chatgpt.com/share/69399157-86d8-800f-9935-1a820893e908
98 lines
3.1 KiB
Python
98 lines
3.1 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
import re
|
|
|
|
from pkgmgr.actions.repository.install.context import RepoContext
|
|
from pkgmgr.actions.repository.install.installers.base import BaseInstaller
|
|
from pkgmgr.core.command.run import run_command
|
|
|
|
|
|
class MakefileInstaller(BaseInstaller):
|
|
"""
|
|
Generic installer that runs `make install` if a Makefile with an
|
|
install target is present.
|
|
|
|
Safety rules:
|
|
- If PKGMGR_DISABLE_MAKEFILE_INSTALLER=1 is set, this installer
|
|
is globally disabled.
|
|
- The higher-level InstallationPipeline ensures that Makefile
|
|
installation does not run if a stronger CLI layer already owns
|
|
the command (e.g. Nix or OS packages).
|
|
"""
|
|
|
|
layer = "makefile"
|
|
MAKEFILE_NAME = "Makefile"
|
|
|
|
def supports(self, ctx: RepoContext) -> bool:
|
|
"""
|
|
Return True if this repository has a Makefile and the installer
|
|
is not globally disabled.
|
|
"""
|
|
# Optional global kill switch.
|
|
if os.environ.get("PKGMGR_DISABLE_MAKEFILE_INSTALLER") == "1":
|
|
if not ctx.quiet:
|
|
print(
|
|
"[INFO] MakefileInstaller is disabled via "
|
|
"PKGMGR_DISABLE_MAKEFILE_INSTALLER."
|
|
)
|
|
return False
|
|
|
|
makefile_path = os.path.join(ctx.repo_dir, self.MAKEFILE_NAME)
|
|
return os.path.exists(makefile_path)
|
|
|
|
def _has_install_target(self, makefile_path: str) -> bool:
|
|
"""
|
|
Heuristically check whether the Makefile defines an install target.
|
|
|
|
We look for:
|
|
|
|
- a plain 'install:' target, or
|
|
- any 'install-*:' style target.
|
|
"""
|
|
try:
|
|
with open(makefile_path, "r", encoding="utf-8", errors="ignore") as f:
|
|
content = f.read()
|
|
except OSError:
|
|
return False
|
|
|
|
# Simple heuristics: look for "install:" or targets starting with "install-"
|
|
if re.search(r"^install\s*:", content, flags=re.MULTILINE):
|
|
return True
|
|
|
|
if re.search(r"^install-[a-zA-Z0-9_-]*\s*:", content, flags=re.MULTILINE):
|
|
return True
|
|
|
|
return False
|
|
|
|
def run(self, ctx: RepoContext) -> None:
|
|
"""
|
|
Execute `make install` in the repository directory if an install
|
|
target exists.
|
|
"""
|
|
makefile_path = os.path.join(ctx.repo_dir, self.MAKEFILE_NAME)
|
|
|
|
if not os.path.exists(makefile_path):
|
|
if not ctx.quiet:
|
|
print(
|
|
f"[pkgmgr] Makefile '{makefile_path}' not found, "
|
|
"skipping MakefileInstaller."
|
|
)
|
|
return
|
|
|
|
if not self._has_install_target(makefile_path):
|
|
if not ctx.quiet:
|
|
print(
|
|
f"[pkgmgr] No 'install' target found in {makefile_path}."
|
|
)
|
|
return
|
|
|
|
if not ctx.quiet:
|
|
print(
|
|
f"[pkgmgr] Running 'make install' in {ctx.repo_dir} "
|
|
f"(MakefileInstaller)"
|
|
)
|
|
|
|
cmd = "make install"
|
|
run_command(cmd, cwd=ctx.repo_dir, preview=ctx.preview)
|