forked from Mirror/pmbootstrap
commands: port repo_bootstrap (MR 2252)
The repo_bootstrap command is totally standalone and has it's own state, making it a good candidate for the pmb.commands submodule. Port it over and move the require_bootstrap() helper function over to pmb/helpers/pmaports.py We also fix the call to pmb.build.package() which broke during rework. Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
This commit is contained in:
parent
97bd8b96ec
commit
f422b5c7ca
5 changed files with 198 additions and 196 deletions
164
pmb/commands/repo_bootstrap.py
Normal file
164
pmb/commands/repo_bootstrap.py
Normal file
|
@ -0,0 +1,164 @@
|
|||
# Copyright 2024 Oliver Smith
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from typing import Optional
|
||||
from pmb.core.chroot import Chroot, ChrootType
|
||||
from pmb.core.context import Context
|
||||
from pmb.helpers import logging
|
||||
import glob
|
||||
|
||||
import pmb.config.pmaports
|
||||
import pmb.helpers.repo
|
||||
import pmb.build
|
||||
from pmb.types import Config
|
||||
from pmb.core import get_context
|
||||
|
||||
from pmb import commands
|
||||
|
||||
class RepoBootstrap(commands.Command):
|
||||
arch: str
|
||||
repo: str
|
||||
context: Context
|
||||
|
||||
progress_done: int = 0
|
||||
progress_total: int = 0
|
||||
progress_step: str
|
||||
|
||||
def check_repo_arg(self):
|
||||
cfg = pmb.config.pmaports.read_config_repos()
|
||||
|
||||
if self.repo in cfg:
|
||||
return
|
||||
|
||||
if not cfg:
|
||||
raise ValueError("pmaports.cfg of current branch does not have any"
|
||||
" sections starting with 'repo:'")
|
||||
|
||||
logging.info(f"Valid repositories: {', '.join(cfg.keys())}")
|
||||
raise ValueError(f"Couldn't find section 'repo:{self.repo}' in pmaports.cfg of"
|
||||
" current branch")
|
||||
|
||||
|
||||
def __init__(self, arch: Optional[str], repository: str):
|
||||
context = get_context()
|
||||
if arch:
|
||||
self.arch = arch
|
||||
else:
|
||||
if context.config.build_default_device_arch:
|
||||
self.arch = pmb.parse.deviceinfo().arch
|
||||
else:
|
||||
self.arch = pmb.config.arch_native
|
||||
|
||||
self.repo = repository
|
||||
self.context = context
|
||||
|
||||
self.check_repo_arg()
|
||||
|
||||
|
||||
def get_packages(self, bootstrap_line):
|
||||
ret = []
|
||||
for word in bootstrap_line.split(" "):
|
||||
if word.startswith("["):
|
||||
continue
|
||||
ret += [word]
|
||||
return ret
|
||||
|
||||
|
||||
def set_progress_total(self, steps):
|
||||
self.progress_total = 0
|
||||
|
||||
# Add one progress point per package
|
||||
for step, bootstrap_line in steps.items():
|
||||
self.progress_total += len(self.get_packages(bootstrap_line))
|
||||
|
||||
# Add progress points per bootstrap step
|
||||
self.progress_total += len(steps) * 2
|
||||
|
||||
# Foreign arch: need to initialize one additional chroot each step
|
||||
if pmb.parse.arch.cpu_emulation_required(self.arch):
|
||||
self.progress_total += len(steps)
|
||||
|
||||
|
||||
def log_progress(self, msg):
|
||||
percent = int(100 * self.progress_done / self.progress_total)
|
||||
logging.info(f"*** {percent}% [{self.progress_step}] {msg} ***")
|
||||
|
||||
self.progress_done += 1
|
||||
|
||||
|
||||
def run_steps(self, steps):
|
||||
chroot: Chroot
|
||||
if pmb.parse.arch.cpu_emulation_required(self.arch):
|
||||
chroot = Chroot(ChrootType.BUILDROOT, self.arch)
|
||||
else:
|
||||
chroot = Chroot.native()
|
||||
|
||||
for step, bootstrap_line in steps.items():
|
||||
self.progress_step = step.replace("bootstrap_", "BOOTSTRAP=")
|
||||
|
||||
self.log_progress("zapping")
|
||||
pmb.chroot.zap(confirm=False)
|
||||
|
||||
usr_merge = pmb.chroot.UsrMerge.OFF
|
||||
if "[usr_merge]" in bootstrap_line:
|
||||
usr_merge = pmb.chroot.UsrMerge.ON
|
||||
|
||||
if chroot != Chroot.native():
|
||||
self.log_progress(f"initializing native chroot (merge /usr: {usr_merge.name})")
|
||||
# Native chroot needs pmOS binary package repo for cross compilers
|
||||
pmb.chroot.init(Chroot.native(), usr_merge)
|
||||
|
||||
self.log_progress(f"initializing {chroot} chroot (merge /usr: {usr_merge.name})")
|
||||
# Initialize without pmOS binary package repo
|
||||
pmb.chroot.init(chroot, usr_merge, postmarketos_mirror=False)
|
||||
|
||||
for package in self.get_packages(bootstrap_line):
|
||||
self.log_progress(f"building {package}")
|
||||
bootstrap_stage = int(step.split("bootstrap_", 1)[1])
|
||||
pmb.build.package(self.context, package, self.arch, force=True,
|
||||
strict=True, bootstrap_stage=bootstrap_stage)
|
||||
|
||||
self.log_progress("bootstrap complete!")
|
||||
|
||||
|
||||
def check_existing_pkgs(self):
|
||||
channel = pmb.config.pmaports.read_config()["channel"]
|
||||
path = self.context.config.work / "packages" / channel / self.arch
|
||||
|
||||
if glob.glob(f"{path}/*"):
|
||||
logging.info(f"Packages path: {path}")
|
||||
|
||||
msg = f"Found previously built packages for {channel}/{self.arch}, run" \
|
||||
" 'pmbootstrap zap -p' first"
|
||||
if pmb.parse.arch.cpu_emulation_required(self.arch):
|
||||
msg += " or remove the path manually (to keep cross compilers if" \
|
||||
" you just built them)"
|
||||
|
||||
raise RuntimeError(f"{msg}!")
|
||||
|
||||
|
||||
def get_steps(self):
|
||||
cfg = pmb.config.pmaports.read_config_repos()
|
||||
prev_step = 0
|
||||
ret = {}
|
||||
|
||||
for key, packages in cfg[self.repo].items():
|
||||
if not key.startswith("bootstrap_"):
|
||||
continue
|
||||
|
||||
step = int(key.split("bootstrap_", 1)[1])
|
||||
assert step == prev_step + 1, (f"{key}: wrong order of steps, expected"
|
||||
f" bootstrap_{prev_step + 1} (previous: bootstrap_{prev_step})")
|
||||
prev_step = step
|
||||
|
||||
ret[key] = packages
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def run(self): # noqa: F821
|
||||
self.check_existing_pkgs()
|
||||
|
||||
steps = self.get_steps()
|
||||
|
||||
self.set_progress_total(steps)
|
||||
self.run_steps(steps)
|
Loading…
Add table
Add a link
Reference in a new issue