git: ee9cfd727578 - main - bsdinstall: add pkgbase target
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 28 Apr 2025 16:14:07 UTC
The branch main has been updated by emaste: URL: https://cgit.FreeBSD.org/src/commit/?id=ee9cfd7275784b61b030beb242df588bb35b21f0 commit ee9cfd7275784b61b030beb242df588bb35b21f0 Author: Isaac Freund <ifreund@freebsdfoundation.org> AuthorDate: 2025-04-01 23:25:49 +0000 Commit: Ed Maste <emaste@FreeBSD.org> CommitDate: 2025-04-28 16:12:27 +0000 bsdinstall: add pkgbase target Reviewed by: ziaee (manpages), kevans (lua), emaste Relnotes: Yes Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D49822 --- usr.sbin/bsdinstall/FreeBSD-base.conf.in | 7 ++ usr.sbin/bsdinstall/Makefile | 17 +++ usr.sbin/bsdinstall/bsdinstall.8 | 22 ++++ usr.sbin/bsdinstall/scripts/Makefile | 6 ++ usr.sbin/bsdinstall/scripts/pkgbase.in | 172 +++++++++++++++++++++++++++++++ 5 files changed, 224 insertions(+) diff --git a/usr.sbin/bsdinstall/FreeBSD-base.conf.in b/usr.sbin/bsdinstall/FreeBSD-base.conf.in new file mode 100644 index 000000000000..792c290facdf --- /dev/null +++ b/usr.sbin/bsdinstall/FreeBSD-base.conf.in @@ -0,0 +1,7 @@ +FreeBSD-base: { + url: "pkg+https://pkg.FreeBSD.org/${ABI}/%%SUBURL%%", + mirror_type: "srv", + signature_type: "fingerprints", + fingerprints: "/usr/share/keys/pkg", + enabled: yes +} diff --git a/usr.sbin/bsdinstall/Makefile b/usr.sbin/bsdinstall/Makefile index c9ba7cb52cd6..75db149b814b 100644 --- a/usr.sbin/bsdinstall/Makefile +++ b/usr.sbin/bsdinstall/Makefile @@ -12,4 +12,21 @@ SCRIPTSDIR_startbsdinstall= ${LIBEXECDIR}/bsdinstall UPDATE_DEPENDFILE= no +FILESDIR= ${SHAREDIR}/bsdinstall +FILES= FreeBSD-base.conf + +_BRANCH!= ${MAKE} -C ${SRCTOP}/release -V BRANCH +BRANCH?= ${_BRANCH} +_REVISION!= ${MAKE} -C ${SRCTOP}/release -V REVISION +REVISION?= ${_REVISION} + +.if ${BRANCH} == CURRENT || ${BRANCH} == STABLE +SUBURL= base_latest +.else +SUBURL= base_release_${REVISION:C/[0-9]+\.//} +.endif + +FreeBSD-base.conf: FreeBSD-base.conf.in + sed "s|%%SUBURL%%|${SUBURL}|" < ${.ALLSRC} > ${.TARGET} + .include <bsd.prog.mk> diff --git a/usr.sbin/bsdinstall/bsdinstall.8 b/usr.sbin/bsdinstall/bsdinstall.8 index 50c8948a7989..8fadacab9189 100644 --- a/usr.sbin/bsdinstall/bsdinstall.8 +++ b/usr.sbin/bsdinstall/bsdinstall.8 @@ -244,6 +244,17 @@ Extracts the distributions listed in .Ev DISTRIBUTIONS into .Ev BSDINSTALL_CHROOT . +.It Cm pkgbase Op Fl --no-kernel +Fetch and install base system packages to +.Ev BSDINSTALL_CHROOT . +Packages are fetched according to repository configuration in +.Ev BSDINSTALL_PKG_REPOS_DIR +if set, or +.Lk pkg.freebsd.org +otherwise. +If the +.Fl --no-kernel +option is passed, no kernel is installed. .It Cm firmware executes .Xr fwget 8 @@ -324,6 +335,17 @@ Example: .Pa https://download.freebsd.org/ftp/releases/powerpc/powerpc64/13.1-RELEASE/ or .Pa http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/amd64/12.2-RELEASE/ . +.It Ev BSDINSTALL_PKG_REPOS_DIR +Directory containing +.Xr pkg 8 +repository configuration files used by the +.Cm pkgbase +target. +See +.Sx REPOSITORY CONFIGURATION +in +.Xr pkg.conf 5 . +Default: unset .It Ev BSDINSTALL_CHROOT The directory into which the distribution files should be unpacked and the directory at which the root file system of the new system should be mounted. diff --git a/usr.sbin/bsdinstall/scripts/Makefile b/usr.sbin/bsdinstall/scripts/Makefile index f3b9f07ed376..4fd59e49d506 100644 --- a/usr.sbin/bsdinstall/scripts/Makefile +++ b/usr.sbin/bsdinstall/scripts/Makefile @@ -1,3 +1,5 @@ +.include <bsd.compat.pre.mk> + SCRIPTS=auto \ adduser \ bootconfig \ @@ -17,6 +19,7 @@ SCRIPTS=auto \ netconfig \ netconfig_ipv4 \ netconfig_ipv6 \ + pkgbase \ rootpass \ script \ services \ @@ -29,4 +32,7 @@ BINDIR= ${LIBEXECDIR}/bsdinstall MAN= +pkgbase: pkgbase.in + sed "s|%%_ALL_libcompats%%|${_ALL_libcompats}|" < ${.ALLSRC} > ${.TARGET} + .include <bsd.prog.mk> diff --git a/usr.sbin/bsdinstall/scripts/pkgbase.in b/usr.sbin/bsdinstall/scripts/pkgbase.in new file mode 100755 index 000000000000..7faeee40647b --- /dev/null +++ b/usr.sbin/bsdinstall/scripts/pkgbase.in @@ -0,0 +1,172 @@ +#!/usr/libexec/flua + +-- SPDX-License-Identifier: BSD-2-Clause +-- +-- Copyright(c) 2025 The FreeBSD Foundation. +-- +-- This software was developed by Isaac Freund <ifreund@freebsdfoundation.org> +-- under sponsorship from the FreeBSD Foundation. + +local all_libcompats <const> = "%%_ALL_libcompats%%" + +-- Run a command using the OS shell and capture the stdout +-- Strips exactly one trailing newline if present, does not strip any other whitespace. +-- Asserts that the command exits cleanly +local function capture(command) + local p = io.popen(command) + local output = p:read("*a") + assert(p:close()) + -- Strip exactly one trailing newline from the output, if there is one + return output:match("(.-)\n$") or output +end + +local function prompt_yn(question) + while true do + io.write(question .. " (y/n) ") + local input = io.read() + if input == "y" or input == "Y" then + return true + elseif input == "n" or input == "N" then + return false + end + end +end + +local function append_list(list, other) + for _, item in ipairs(other) do + table.insert(list, item) + end +end + +-- Returns a list of pkgbase packages equivalent to the default base.txz and kernel.txz +local function select_packages(pkg, options) + local components = { + ["kernel"] = {}, + ["kernel-dbg"] = {}, + ["base"] = {}, + ["base-dbg"] = {}, + ["src"] = {}, + ["tests"] = {}, + } + + for compat in all_libcompats:gmatch("%S+") do + components["lib" .. compat] = {} + components["lib" .. compat .. "-dbg"] = {} + end + + local rquery = capture(pkg .. "rquery -U -r FreeBSD-base %n") + for package in rquery:gmatch("[^\n]+") do + if package == "FreeBSD-src" or package:match("^FreeBSD%-src%-.*") then + table.insert(components["src"], package) + elseif package == "FreeBSD-tests" or package:match("^FreeBSD%-tests%-.*") then + table.insert(components["tests"], package) + elseif package:match("^FreeBSD%-kernel%-.*") then + -- Kernels other than FreeBSD-kernel-generic are ignored + if package == "FreeBSD-kernel-generic" then + table.insert(components["kernel"], package) + elseif package == "FreeBSD-kernel-generic-dbg" then + table.insert(components["kernel-dbg"], package) + end + elseif package:match(".*%-dbg$") then + table.insert(components["base-dbg"], package) + else + local found = false + for compat in all_libcompats:gmatch("%S+") do + if package:match(".*%-dbg%-lib" .. compat .. "$") then + table.insert(components["lib" .. compat .. "-dbg"], package) + found = true + break + elseif package:match(".*%-lib" .. compat .. "$") then + table.insert(components["lib" .. compat], package) + found = true + break + end + end + if not found then + table.insert(components["base"], package) + end + end + end + -- Don't assert the existence of dbg, tests, and src packages here. If using + -- a custom local repository with BSDINSTALL_PKG_REPOS_DIR we shouldn't + -- require it to have all packages. + assert(#components["kernel"] == 1) + assert(#components["base"] > 0) + + local selected = {} + append_list(selected, components["base"]) + if not options.no_kernel then + append_list(selected, components["kernel"]) + end + + return selected +end + +local function parse_options() + local options = {} + for _, a in ipairs(arg) do + if a == "--no-kernel" then + options.no_kernel = true + else + io.stderr:write("Error: unknown option " .. a .. "\n") + os.exit(1) + end + end + return options +end + +-- Fetch and install pkgbase packages to BSDINSTALL_CHROOT. +-- Respect BSDINSTALL_PKG_REPOS_DIR if set, otherwise use pkg.freebsd.org. +local function pkgbase() + local options = parse_options() + + -- TODO Support fully offline pkgbase installation by taking a new enough + -- version of pkg.pkg as input. + if not os.execute("pkg -N > /dev/null 2>&1") then + print("Bootstrapping pkg on the host system") + assert(os.execute("pkg bootstrap -y")) + end + + local chroot = assert(os.getenv("BSDINSTALL_CHROOT")) + assert(os.execute("mkdir -p " .. chroot)) + + local repos_dir = os.getenv("BSDINSTALL_PKG_REPOS_DIR") + if not repos_dir then + repos_dir = chroot .. "/usr/local/etc/pkg/repos/" + assert(os.execute("mkdir -p " .. repos_dir)) + assert(os.execute("cp /usr/share/bsdinstall/FreeBSD-base.conf " .. repos_dir)) + + -- Since pkg always interprets fingerprints paths as relative to + -- the --rootdir we must copy the key from the host. + assert(os.execute("mkdir -p " .. chroot .. "/usr/share/keys")) + assert(os.execute("cp -R /usr/share/keys/pkg " .. chroot .. "/usr/share/keys/")) + end + + -- We must use --repo-conf-dir rather than -o REPOS_DIR here as the latter + -- is interpreted relative to the --rootdir. BSDINSTALL_PKG_REPOS_DIR must + -- be allowed to point to a path outside the chroot. + local pkg = "pkg --rootdir " .. chroot .. + " --repo-conf-dir " .. repos_dir .. " -o IGNORE_OSVERSION=yes " + + while not os.execute(pkg .. "update") do + if not prompt_yn("Updating repositories failed, try again?") then + print("Canceled") + os.exit(1) + end + end + + local packages = table.concat(select_packages(pkg, options), " ") + + while not os.execute(pkg .. "install -U -F -y -r FreeBSD-base " .. packages) do + if not prompt_yn("Fetching packages failed, try again?") then + print("Canceled") + os.exit(1) + end + end + + if not os.execute(pkg .. "install -U -y -r FreeBSD-base " .. packages) then + os.exit(1) + end +end + +pkgbase()