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()