i hope i fixed db and dependency shit

This commit is contained in:
2026-05-09 16:16:27 +02:00
parent 10cc4f968f
commit ccf96a5229
2 changed files with 25 additions and 19 deletions

View File

@@ -23,6 +23,7 @@ from utils import download_extract, version_satisfies, PKG_DIR, _ensure_symlink,
from tqdm import tqdm from tqdm import tqdm
# --- basic dirs --- # --- basic dirs ---
GLOBAL_INSTALLED = set()
TMP_RECIPE_DIR = "/tmp/fempkg" TMP_RECIPE_DIR = "/tmp/fempkg"
os.makedirs(TMP_RECIPE_DIR, exist_ok=True) os.makedirs(TMP_RECIPE_DIR, exist_ok=True)
@@ -70,10 +71,8 @@ def rebuild_package(packages, repo_dir=None):
if isinstance(packages, str): if isinstance(packages, str):
packages = [packages] packages = [packages]
db = load_db() # <-- load db once
for pkg in packages: for pkg in packages:
if pkg not in db["installed"]: if pkg not in load_db()["installed"]:
print(f"[fempkg] Skipping rebuild of {pkg}: not installed.") print(f"[fempkg] Skipping rebuild of {pkg}: not installed.")
continue continue
@@ -137,16 +136,22 @@ def build_package(recipe_file, repo_dir=None, force_rebuild=False, _visited=None
if _visited is None: if _visited is None:
_visited = set() # track packages in current build chain _visited = set() # track packages in current build chain
db = load_db()
recipe = {} recipe = {}
with open(recipe_file, "r") as f: with open(recipe_file, "r") as f:
exec(f.read(), recipe) exec(f.read(), recipe)
name, version = recipe["pkgname"], recipe["pkgver"] name, version = recipe["pkgname"], recipe["pkgver"]
global GLOBAL_INSTALLED
if name in GLOBAL_INSTALLED:
return
GLOBAL_INSTALLED.add(name)
# Prevent infinite recursion from dependency loops # Prevent infinite recursion from dependency loops
if name in _visited: if name in _visited:
print(f"[fempkg] Detected circular dependency on {name}, skipping...") print(f"[fempkg] Something went wrong please report it! (circular dependency)")
return return
_visited.add(name) _visited.add(name)
@@ -159,7 +164,7 @@ def build_package(recipe_file, repo_dir=None, force_rebuild=False, _visited=None
source_only = os.environ.get("FEMPKG_SOURCE", "").lower() in ("1", "true", "yes") source_only = os.environ.get("FEMPKG_SOURCE", "").lower() in ("1", "true", "yes")
nodelete_env = os.environ.get("FEMPKG_NODELETE", "").lower() in ("1", "true", "yes") nodelete_env = os.environ.get("FEMPKG_NODELETE", "").lower() in ("1", "true", "yes")
if not force_rebuild and is_installed(name, version, db=db): if not force_rebuild and is_installed(name, version):
print(f"[fempkg] {name}-{version} is already installed. Skipping installation.") print(f"[fempkg] {name}-{version} is already installed. Skipping installation.")
return return
@@ -177,7 +182,7 @@ def build_package(recipe_file, repo_dir=None, force_rebuild=False, _visited=None
with open(dep_recipe, "r") as f: with open(dep_recipe, "r") as f:
exec(f.read(), dep_info) exec(f.read(), dep_info)
dep_latest_ver = dep_info["pkgver"] dep_latest_ver = dep_info["pkgver"]
installed_ver = db["installed"].get(dep_name) installed_ver = load_db()["installed"].get(dep_name)
if installed_ver is None or not version_satisfies(installed_ver, dep_latest_ver): if installed_ver is None or not version_satisfies(installed_ver, dep_latest_ver):
print(f"Installing/updating dependency {dep_name} " print(f"Installing/updating dependency {dep_name} "
f"(installed: {installed_ver}, latest: {dep_latest_ver})") f"(installed: {installed_ver}, latest: {dep_latest_ver})")
@@ -233,7 +238,7 @@ def build_package(recipe_file, repo_dir=None, force_rebuild=False, _visited=None
else: else:
print(f"[fempkg] No manifest available to snapshot for {name} {version}.") print(f"[fempkg] No manifest available to snapshot for {name} {version}.")
old_installed_version = db["installed"].get(name) old_installed_version = load_db()["installed"].get(name)
if old_installed_version and (not atomic_upgrade) and (not nodelete_env): if old_installed_version and (not atomic_upgrade) and (not nodelete_env):
old_versioned_path = os.path.join(VERSIONED_MANIFEST_DIR, f"{name}-{old_installed_version}.txt") old_versioned_path = os.path.join(VERSIONED_MANIFEST_DIR, f"{name}-{old_installed_version}.txt")
if os.path.exists(old_versioned_path): if os.path.exists(old_versioned_path):
@@ -277,7 +282,7 @@ def build_package(recipe_file, repo_dir=None, force_rebuild=False, _visited=None
print(f"[fempkg] Extracting binary package to / : {local_path}") print(f"[fempkg] Extracting binary package to / : {local_path}")
extract_tar_zst_with_progress(local_path, dest="/") extract_tar_zst_with_progress(local_path, dest="/")
register_package(name, version, db=db) register_package(name, version)
print(f"[fempkg] Installed {name}-{version} from binary package.") print(f"[fempkg] Installed {name}-{version} from binary package.")
os.system(f"rm -rf {local_path} {asc_path}") os.system(f"rm -rf {local_path} {asc_path}")
@@ -323,7 +328,7 @@ def build_package(recipe_file, repo_dir=None, force_rebuild=False, _visited=None
print(f"> {cmd}") print(f"> {cmd}")
subprocess.run(f". /etc/profile && mkdir -p /tmp/fempkg && {cmd}", shell=True, check=True) subprocess.run(f". /etc/profile && mkdir -p /tmp/fempkg && {cmd}", shell=True, check=True)
register_package(name, version, db=db) register_package(name, version)
try: try:
resolved_manifest = fetch_manifest(name, pkgver=version) resolved_manifest = fetch_manifest(name, pkgver=version)
if resolved_manifest: if resolved_manifest:
@@ -331,7 +336,7 @@ def build_package(recipe_file, repo_dir=None, force_rebuild=False, _visited=None
versioned_path = os.path.join(VERSIONED_MANIFEST_DIR, f"{name}-{version}.txt") versioned_path = os.path.join(VERSIONED_MANIFEST_DIR, f"{name}-{version}.txt")
shutil.copy(resolved_manifest, versioned_path) shutil.copy(resolved_manifest, versioned_path)
shutil.copy(versioned_path, os.path.join(MANIFEST_CACHE_DIR, f"{name}.txt")) shutil.copy(versioned_path, os.path.join(MANIFEST_CACHE_DIR, f"{name}.txt"))
old_installed_version = db["installed"].get(name) old_installed_version = load_db()["installed"].get(name)
if old_installed_version and old_installed_version != version: if old_installed_version and old_installed_version != version:
remove_versioned_manifest(name, old_installed_version) remove_versioned_manifest(name, old_installed_version)
except Exception as e: except Exception as e:

17
fempkg
View File

@@ -18,12 +18,13 @@ import sys, os
from db import register_package, load_db, save_db from db import register_package, load_db, save_db
from build import build_package, fetch_recipe, MANIFEST_CACHE_DIR from build import build_package, fetch_recipe, MANIFEST_CACHE_DIR
from utils import fetch_all from utils import fetch_all
import shutil
RECIPE_CACHE_DIR = "/var/lib/fempkg/repo" RECIPE_CACHE_DIR = "/var/lib/fempkg/repo"
def list_installed(): def list_installed():
db = load_db()
for pkg, ver in db["installed"].items(): for pkg, ver in load_db()["installed"].items():
print(f"{pkg}-{ver}") print(f"{pkg}-{ver}")
def update_all(): def update_all():
@@ -31,7 +32,7 @@ def update_all():
print("Recipe, manifest and the binpkg index cache updated.") print("Recipe, manifest and the binpkg index cache updated.")
def upgrade_packages(pkg=None): def upgrade_packages(pkg=None):
db = load_db()
if pkg: if pkg:
recipe_file = os.path.join(RECIPE_CACHE_DIR, f"{pkg}.recipe.py") recipe_file = os.path.join(RECIPE_CACHE_DIR, f"{pkg}.recipe.py")
if not os.path.exists(recipe_file): if not os.path.exists(recipe_file):
@@ -39,7 +40,7 @@ def upgrade_packages(pkg=None):
return return
build_package(recipe_file) build_package(recipe_file)
else: else:
for pkgname in db["installed"]: for pkgname in load_db()["installed"]:
recipe_file = os.path.join(RECIPE_CACHE_DIR, f"{pkgname}.recipe.py") recipe_file = os.path.join(RECIPE_CACHE_DIR, f"{pkgname}.recipe.py")
if not os.path.exists(recipe_file): if not os.path.exists(recipe_file):
print(f"Recipe for {pkgname} missing, skipping.") print(f"Recipe for {pkgname} missing, skipping.")
@@ -79,10 +80,10 @@ def uninstall_package(pkgname):
print(f"Failed to remove manifest {manifest_path}: {e}") print(f"Failed to remove manifest {manifest_path}: {e}")
# Remove from DB # Remove from DB
db = load_db()
if pkgname in db["installed"]: if pkgname in load_db()["installed"]:
db["installed"].pop(pkgname) load_db()["installed"].pop(pkgname)
save_db(db) save_db(load_db())
print(f"{pkgname} uninstalled.") print(f"{pkgname} uninstalled.")