2024-05-17 23:04:34 +08:00
|
|
|
import os
|
|
|
|
import logging
|
|
|
|
from sys import stdout
|
|
|
|
from locale import setlocale, LC_ALL
|
|
|
|
from argparse import ArgumentParser
|
|
|
|
from builder.build import bootstrap
|
|
|
|
from builder.lib import config, utils
|
|
|
|
from builder.lib.context import ArchBuilderContext
|
2024-05-21 17:00:51 +08:00
|
|
|
from builder.lib.config import ArchBuilderConfigError
|
2024-05-17 23:04:34 +08:00
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
def parse_arguments(ctx: ArchBuilderContext):
|
|
|
|
parser = ArgumentParser(
|
|
|
|
prog="arch-image-builder",
|
|
|
|
description="Build flashable image for Arch Linux",
|
|
|
|
)
|
2024-05-21 17:21:56 +08:00
|
|
|
parser.add_argument("-C", "--clean", help="Clean workspace before build", default=False, action='store_true')
|
2024-05-21 17:00:51 +08:00
|
|
|
parser.add_argument("-p", "--preset", help="Select preset to create package")
|
|
|
|
parser.add_argument("-c", "--config", help="Select config to build", action='append')
|
2024-05-24 00:39:00 +08:00
|
|
|
parser.add_argument("-m", "--mirror", help="Select mirror to download package", action='append')
|
2024-05-17 23:04:34 +08:00
|
|
|
parser.add_argument("-o", "--workspace", help="Set workspace for builder", default=ctx.work)
|
|
|
|
parser.add_argument("-d", "--debug", help="Enable debug logging", default=False, action='store_true')
|
|
|
|
parser.add_argument("-G", "--no-gpgcheck", help="Disable GPG check", default=False, action='store_true')
|
|
|
|
parser.add_argument("-r", "--repack", help="Repack rootfs only", default=False, action='store_true')
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
# debug logging
|
|
|
|
if args.debug:
|
|
|
|
logging.root.setLevel(logging.DEBUG)
|
|
|
|
log.debug("enabled debug logging")
|
|
|
|
|
|
|
|
if args.no_gpgcheck: ctx.gpgcheck = False
|
|
|
|
if args.repack: ctx.repack = True
|
2024-05-21 17:21:56 +08:00
|
|
|
if args.clean: ctx.clean = True
|
2024-05-17 23:04:34 +08:00
|
|
|
|
|
|
|
# collect configs path
|
|
|
|
configs = []
|
2024-05-21 17:00:51 +08:00
|
|
|
if args.config:
|
|
|
|
for conf in args.config:
|
|
|
|
configs.extend(conf.split(","))
|
|
|
|
|
|
|
|
# load preset config for build package
|
|
|
|
if args.preset:
|
|
|
|
config.load_preset(ctx, args.preset)
|
|
|
|
pcfgs = ctx.get("package.configs", [])
|
|
|
|
configs.extend(pcfgs)
|
2024-05-17 23:04:34 +08:00
|
|
|
|
2024-05-24 00:39:00 +08:00
|
|
|
if args.mirror:
|
|
|
|
for mirror in args.mirror:
|
|
|
|
configs.extend([f"mirrors/{name}" for name in mirror.split(",")])
|
|
|
|
|
2024-05-17 23:04:34 +08:00
|
|
|
# load and populate configs
|
|
|
|
config.load_configs(ctx, configs)
|
|
|
|
config.populate_config(ctx)
|
|
|
|
|
|
|
|
# build folder: {TOP}/build/{TARGET}
|
|
|
|
ctx.work = os.path.realpath(os.path.join(args.workspace, ctx.target))
|
|
|
|
|
|
|
|
|
|
|
|
def init_environment():
|
|
|
|
# set user agent for pacman (some mirrors requires)
|
|
|
|
os.environ["HTTP_USER_AGENT"] = "arch-image-builder(pacman) pyalpm"
|
|
|
|
|
|
|
|
# set to default language to avoid problems
|
|
|
|
os.environ["LANG"] = "C"
|
|
|
|
os.environ["LANGUAGE"] = "C"
|
|
|
|
os.environ["LC_ALL"] = "C"
|
|
|
|
setlocale(LC_ALL, "C")
|
|
|
|
|
|
|
|
|
|
|
|
def check_system():
|
|
|
|
# why not root?
|
|
|
|
if os.getuid() != 0:
|
|
|
|
raise PermissionError("this tool can only run as root")
|
|
|
|
|
|
|
|
# always need pacman
|
|
|
|
if not utils.have_external("pacman"):
|
|
|
|
raise FileNotFoundError("pacman not found")
|
|
|
|
|
|
|
|
|
2024-05-21 17:00:51 +08:00
|
|
|
def done_package(ctx: ArchBuilderContext):
|
|
|
|
file: str = ctx.get("package.file", "")
|
|
|
|
out = file
|
|
|
|
if not out.startswith("/"):
|
|
|
|
out = os.path.join(ctx.work, file)
|
|
|
|
if not out.endswith(".7z"):
|
|
|
|
raise ArchBuilderConfigError("current only supports 7z")
|
|
|
|
log.info(f"creating package {file}")
|
|
|
|
args = ["7z", "a", "-ms=on", "-mx=9", out, "."]
|
|
|
|
ret = ctx.run_external(args, cwd=ctx.get_output())
|
|
|
|
if ret != 0: raise OSError("create package failed")
|
|
|
|
log.info(f"created package at {out}")
|
|
|
|
|
|
|
|
|
2024-05-17 23:04:34 +08:00
|
|
|
def main():
|
|
|
|
logging.basicConfig(stream=stdout, level=logging.INFO)
|
|
|
|
check_system()
|
|
|
|
init_environment()
|
|
|
|
ctx = ArchBuilderContext()
|
|
|
|
ctx.dir = os.path.realpath(os.path.join(os.path.dirname(__file__), os.path.pardir))
|
|
|
|
ctx.work = os.path.realpath(os.path.join(ctx.dir, "build"))
|
|
|
|
parse_arguments(ctx)
|
2024-05-21 17:00:51 +08:00
|
|
|
log.info(f"package version: {ctx.version}")
|
2024-05-17 23:04:34 +08:00
|
|
|
log.info(f"source tree folder: {ctx.dir}")
|
|
|
|
log.info(f"workspace folder: {ctx.work}")
|
|
|
|
log.info(f"build target name: {ctx.target}")
|
|
|
|
bootstrap.build_rootfs(ctx)
|
2024-05-21 17:00:51 +08:00
|
|
|
if ctx.preset:
|
|
|
|
done_package(ctx)
|