From nobody Mon Jun 29 15:52:21 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gprPx6ddbz6jNWf for ; Mon, 29 Jun 2026 15:52:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gprPx1sJ5z3LB2 for ; Mon, 29 Jun 2026 15:52:21 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782748341; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=YNY2FXolMKvGq/2RCt9Th9stByXRie9xjlTh62Gr3D0=; b=kzmCoSLtKFB58fiRMQLCyFzUzbjIPkyt7oV4wprDmHqmjClYDUHdieBBQP2Zk4UF3I1gCO SOAoSFf3WtiicT2IhMCr1G3zYt8ZUdRlIYnFv6VpQMOfA6nQn8VIRCHtVKpDtZ38x37iz2 yZfHNbQlBozY9yQEEig8Ze5GzGfJnhwBaS/LJUywgJrdZ+IqmwIDwIr79Lo2Uh1/WRHwxm seIV7w9KrLfwGJFE6sIVdimtSGLj+23ezMLaNVuVR1SiLRVsCw/L0s6fit8H6VlBMFVC7H nixCx/dVYPA9Dl/aWIFY4ClXicGUWzkoMyOe0eGSaC+kz3vi3PJz81UAsgtsBw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1782748341; a=rsa-sha256; cv=none; b=OfPLO/QII/ohClyinnRfTOLu+Kp9dPGkJ8pFo3QMJgvLj02/aUNuYk4s09UkvLpK5nVEA0 7RC6ftCQoJD5abYdfgcbr/INRVAT03GX6c/uplJd2nc+nb8EQpPRdq9qi9NVuW/uN1PK+V S4nEOYxWGG/TtJGq8cC++Dc9CV1OUeYgWDslp94OXiV7M3EQMoYmo4i3MZ3tQ2FsR2xhAt o5ufqPCihle6b6uwcrsT9N7fxpiAbO13tB8pZxADPE4aUcDHHqJEUvzxbMmhymPh7m2W+m GqugCypScdg+61zDM59Xr4Z4hfiTxKXinEF4Q4r7A6GHc32qguEQqdPr5tIDtQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782748341; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=YNY2FXolMKvGq/2RCt9Th9stByXRie9xjlTh62Gr3D0=; b=UDmDpg6XES7BUATUP4Ytqk6GfQzw/3i+p/hPL2a0IxULuwNd8WK6Ln31u5RVUHupgwqOCV c9XOviGYHsqJrqfZwakhI53NqlebPcOYStim1nf0x1UwgbQ+n7sNvJ8UJOPK8l8CDJwDN5 RGt1FkHbBFObNDFJ2LhKW7GZR/QZdKYbHxQzgOFu46gNOXoD6MGJXbvANhISC7CAaiItZA W++VEjudqfSzB/UpyKxL8qxJiVo09LybFwlmxXJmXdK1GE/XTh+XvynsEX2sbIa9tjohFu GpSHQdhx4ZB0tDmXKGzMuACBwTS54MLD8i3iYCnVJJTE/Cfy1DvXWORKXZdHGA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gprPx0J8Wz148b for ; Mon, 29 Jun 2026 15:52:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3c62b by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 29 Jun 2026 15:52:21 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Dag-Erling=?utf-8?Q? Sm=C3=B8rg?=rav Subject: git: e6467516f584 - main - pkgbasify: Add new utility List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: des X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: e6467516f584505ac29fd370966abd530a7b5454 Auto-Submitted: auto-generated Date: Mon, 29 Jun 2026 15:52:21 +0000 Message-Id: <6a4294b5.3c62b.74319574@gitrepo.freebsd.org> The branch main has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=e6467516f584505ac29fd370966abd530a7b5454 commit e6467516f584505ac29fd370966abd530a7b5454 Author: Dag-Erling Smørgrav AuthorDate: 2026-06-29 00:41:11 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2026-06-29 13:49:22 +0000 pkgbasify: Add new utility The pkgbasify utility converts a system installed from distribution sets to packaged base by registering, without actually installing, a set of packages that corresponds to what is already installed. MFC after: 1 week --- usr.sbin/Makefile | 1 + usr.sbin/pkgbasify/Makefile | 6 + usr.sbin/pkgbasify/pkgbasify.8 | 215 +++++++++++++++ usr.sbin/pkgbasify/pkgbasify.sh | 596 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 818 insertions(+) diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 9e885d5d45c5..2b478b26d3d8 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -57,6 +57,7 @@ SUBDIR= adduser \ nologin \ pciconf \ periodic \ + pkgbasify \ pnfsdscopymr \ pnfsdsfile \ pnfsdskill \ diff --git a/usr.sbin/pkgbasify/Makefile b/usr.sbin/pkgbasify/Makefile new file mode 100644 index 000000000000..cbd8637b78c3 --- /dev/null +++ b/usr.sbin/pkgbasify/Makefile @@ -0,0 +1,6 @@ +SCRIPTS=pkgbasify.sh +LINKS= ${BINDIR}/pkgbasify ${BINDIR}/depkgbasify +MAN= pkgbasify.8 +MLINKS= pkgbasify.8 depkgbasify.8 + +.include diff --git a/usr.sbin/pkgbasify/pkgbasify.8 b/usr.sbin/pkgbasify/pkgbasify.8 new file mode 100644 index 000000000000..9c44740e4132 --- /dev/null +++ b/usr.sbin/pkgbasify/pkgbasify.8 @@ -0,0 +1,215 @@ +.\"- +.\" Copyright (c) 2026 Dag-Erling Smørgrav +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd June 28, 2026 +.Dt PKGBASIFY 8 +.Os +.Sh NAME +.Nm pkgbasify , +.Nm depkgbasify +.Nd convert a system to and from pkgbase +.Sh SYNOPSIS +.Nm pkgbasify +.Op Fl hnqtv +.Op Fl a | Fl y +.Op Fl b Ar basedir +.Op Fl j Ar jail +.Op Fl r Ar repo +.Nm depkgbasify +.Op Fl hnqv +.Op Fl a | Fl y +.Op Fl b Ar basedir +.Op Fl j Ar jail +.Sh DESCRIPTION +The +.Nm pkgbasify +utility converts a system installed from distribution sets to packaged +base by registering, without actually installing, a set of packages +that corresponds to what is already installed. +See +.Sx Converting to Packaged Base +below. +.Pp +The +.Nm depkgbasify +utility converts a packaged base system back to distribution sets by +unregistering all base packages. +See +.Sx Converting from Packaged Base +below. +.Pp +In both cases, the user is urged to take a backup or snapshot of the +system and perform a dry run before the actual conversion. +.Pp +The following options are available: +.Bl -tag -width indent +.It Fl a +Automatic mode. +Do not prompt the user, but skip certain optional steps. +Mutually exclusive with +.Fl y . +.It Fl b Ar basedir +Operate on a system mounted at +.Ar basedir . +.It Fl h +Print a usage message and exit. +.It Fl j Ar jail +Operate on the specified jail. +.It Fl n +Dry run. +Examine the system and download the necessary files but do not +register or unregister anything. +.It Fl q +Quiet mode. +.It Fl r Ar repo +.Po +.Nm pkgbasify +only +.Pc +Use the specified packaged base repository instead of the default. +.It Fl t +.Po +.Nm pkgbasify +only +.Pc +Trim. +Not yet implemented. +.It Fl v +Verbose mode. +.It Fl y +Assume the answer to every prompt is +.Dq yes . +Mutually exclusive with +.Fl a . +.El +.Ss Converting to Packaged Base +The +.Nm pkgbasify +utility begins by inspecting the system to identify which distribution +sets are installed. +It then downloads and registers the sets of base packages that +correspond to those distribution sets. +If not running in automatic mode, it then performs a forced upgrade +and enables the +.Dv BACKUP_LIBRARIES +options in the +.Xr pkg 8 +configuration. +.Pp +It is important to note that after the conversion, files that should +have been present on the system but weren't will still be recorded in +the package database. +This is why a non-automatic +.Nm pkgbasify +offers to perform a forced upgrade: to reset the system to a state +where the files on disk match the recorded inventory. +However, since +.Nm pkgbasify +does not make a backup of the system before converting it, this forced +upgrade is irreversible, which is also why it is skipped in automatic +mode. +.Ss Converting from Packaged Base +The +.Nm depkgbasify +utility begins by identifying the repository from which the base +system was installed. +It then attempts to identify which package sets are partially or +completely installed. +If not running in automatic mode, it will then offer to complete any +partially installed sets, remove the source tree (if installed from +packages), and perform a last upgrade before the conversion. +Finally, it unregisters all remaining base packages without removing +any of the files. +.Ss Round-trip Conversion +When run in automatic mode, neither +.Nm pkgbasify +nor +.Nm depkgbasify +will make any changes to the system that the other cannot undo. +Thus, starting with a system installed from distribution sets and +running +.Ql pkgbasify -a +followed by +.Ql depkgbasify -a +should have a net effect of no changes to the system except for the +package cache. +Conversely, starting with a freshly updated packaged base system and +running +.Ql depkgbasify -a +followed by +.Ql pkgbasify -a +should also have a net zero effect. +.Sh ENVIRONMENT +.Bl -tag -width indent +.It Ev BASEDIR +base directory as if passed to the +.Fl b +option. +.It Ev BASEREPO +repository as if passed to the +.Fl r +option. +.It Ev JAIL +jail id or name as if passed to the +.Fl j +option. +.El +.Sh EXIT STATUS +.Ex -std pkgbasify depkgbasify +.Sh SEE ALSO +.Xr build 7 , +.Xr pkg 7 , +.Xr pkgbase 7 , +.Xr freebsd-update 8 , +.Xr pkg 8 +.Sh HISTORY +The +.Nm pkgbasify +and +.Nm depkgbasify +utilities first appeared in +.Fx 15.2 . +.Sh AUTHORS +The +.Nm pkgbasify +and +.Nm depkgbasify +utilities and this manual page were written by +.An Dag-Erling Sm\(/orgrav Aq Mt des@FreeBSD.org . +.Sh CAVEATS +The +.Nm pkgbasify +utility is intended for use on systems installed from distribution +sets. +It will also work on systems installed from source, but if the system +has been customized through the use of build options, the conversion +will round it back up, so to speak, to the smallest set of +distribution sets which include everything present on the system. +Conversely, +.Nm pkgbasify +will not notice or register elements of the system which are disabled +by default but have been locally enabled, built and installed, unless +installing from a repository that has been built with the same build +options. +.Pp +When converting a system installed from source to packaged base, the +recommended procedure is to build a set of packages from the same +source tree and using the same build options, then configure a +repository pointing to those packages, and perform the conversion +using that repository before switching to another and doing a forced +upgrade. +.Pp +The +.Nm depkgbasify +utility merely unregisters the base packages. +It does not revert the binaries to a state that could have been +produced by an official installation image or +.Xr freebsd-update 8 . +However, if the system was using base packages from the official +.Fx +packaged base repository prior to the conversion, the contents should +match what +.Xr freebsd-update 8 +expects. diff --git a/usr.sbin/pkgbasify/pkgbasify.sh b/usr.sbin/pkgbasify/pkgbasify.sh new file mode 100755 index 000000000000..86f926bfcd83 --- /dev/null +++ b/usr.sbin/pkgbasify/pkgbasify.sh @@ -0,0 +1,596 @@ +#!/bin/sh +#- +# Copyright (c) 2026 Dag-Erling Smørgrav +# +# SPDX-License-Identifier: BSD-2-Clause +# + +set -eu +exec 3>&2 + +progname="${0##*/}" +localbase="$(/sbin/sysctl -qn user.localbase || echo /usr/local)" + +# +# All the top-level sets except src +# +topsets="base base-dbg kernels kernels-dbg lib32 lib32-dbg tests" + +# +# Default repository +# +OS=FreeBSD +BASEREPO=${BASEREPO:-${OS}-base} + +# +# Command-line options +# +auto= +base=${BASEDIR:-} +dryrun= +jail=${JAIL:-} +quiet= +repo= +trim= +verbose= +yes= + +# +# Print a message +# +msg() { + local width=$((${COLUMNS:-80} - ${#progname} - 4)) + echo "$@" | /usr/bin/fmt -sw${width} | + /usr/bin/sed "s|^|${progname}: |" +} + +# +# Print an error message and exit +# +err() { + msg "$@" >&3 + exit 1 +} + +# +# Print a warning message +# +warn() { + if ! [ "${quiet}" ]; then + msg "$@" >&3 + fi +} + +# +# Print an informational message +# +info() { + if ! [ "${quiet}" ]; then + msg "$@" + fi +} + +# +# Ask the user for confirmation +# +confirm() { + local ans= + if [ "${yes}" ]; then + return 0 + fi + while :; do + read -p "$@ " -r ans + case ${ans} in + [Yy]|[Yy][Ee][Ss]) + return 0 + ;; + [Nn]|[Nn][Oo]) + return 1 + ;; + *) + echo "Please answer with yes or no." >&3 + ;; + esac + done +} + +# +# Execute a command, but print it first if verbose +# +v() { + if [ "${verbose}" ]; then + echo "$@" >&3 + fi + "$@" +} + +# +# Compute the path of a file in the target environment +# +path() { + local path="${base}$1" + if [ -n "${jail}" ]; then + path="$(/usr/sbin/jls -j "${jail}" path)${path}" + fi + echo "${path}" +} + +# +# Check if a file exists in the target environment +# +exists() { + v test -e "$(path "$@")" +} + +# +# Run pkg(7) +# +# pkg(7) currently lacks support for -j and -r, otherwise we could run +# every pkg command through it, which would prepare us for when pkg +# eventually moves into base. For now, we can use jexec for -j, but +# there is no way to emulate -r. +# +pkg7() { + if [ -n "${base}" ]; then + err "pkg(7) currently lacks -r option" + elif [ -n "${jail}" ]; then + v /usr/sbin/jexec "${jail}" /usr/sbin/pkg "$@" + else + v /usr/sbin/pkg "$@" + fi +} + +# +# Run pkg(8) +# +pkg() { + v "${localbase}"/sbin/pkg ${jail:+-j"${jail}"} ${base:+-r"${base}"} "$@" +} + +# +# Run pkg bootstrap +# +pkg_bootstrap() { + if ! pkg7 -N 2>/dev/null; then + warn "Package manager not installed" + if confirm "Bootstrap the package manager?"; then + pkg7 bootstrap -r"${repo}" -y + else + err "Unable to proceed without package manager" + fi + fi +} + +# +# Check if a package exists in the repository +# +pkg_exists() { + pkg rquery -r"${repo}" -U %v "$@" >/dev/null +} + +# +# Run pkg fetch +# +pkg_fetch() { + pkg fetch -r"${repo}" -U ${quiet:+-q} "$@" +} + +# +# Run pkg install +# +pkg_install() { + pkg install -r"${repo}" -U ${dryrun:+-n} ${quiet:+-q} "$@" +} + +# +# Check if a package is installed +# +pkg_installed() { + pkg info -q "$@" +} + +# +# Run pkg query +# +pkg_query() { + pkg query "$@" +} + +# +# Run pkg install --register-only +# +pkg_register() { + pkg install -r"${repo}" --register-only ${dryrun:+-n} ${quiet:+-q} "$@" +} + +# +# Run pkg remove +# +pkg_remove() { + pkg remove ${dryrun:+-n} ${quiet:+-q} "$@" +} + +# +# Run pkg rquery +# +pkg_rquery() { + pkg rquery -r"${repo}" -U "$@" +} + +# +# Run pkg unregister +# +pkg_unregister() { + pkg unregister ${dryrun:+-n} ${quiet:+-q} "$@" +} + +# +# Run pkg update +# +pkg_update() { + pkg update -r"${repo}" ${quiet:+-q} "$@" +} + +# +# Run pkg upgrade +# +pkg_upgrade() { + pkg upgrade -r"${repo}" ${dryrun:+-n} ${quiet:+-q} "$@" +} + +# +# Generate a complete transitive list of dependencies +# +pkg_alldeps() { + local deps=$(pkg rquery %dn "$@") + if [ "${deps}" ]; then + echo "${deps}" + pkg_alldeps ${deps} + fi | sort -u +} + +# +# Check if pkg is new enough +# +check_pkg() { + local ver=$(pkg -v) + case ${ver} in + 1.*|2.[0-6].*|2.7.[0-4]) + err "pkg ${ver} is too old, I need pkg 2.7.5 or newer" + ;; + esac +} + +# +# Try to ascertain if the system is running pkgbase +# +ispkgbase() { + pkg which -q /sbin/init >/dev/null +} + +# +# Convert to pkgbase +# +pkgbasify() { + local sets=base set= + + # Check if we're running pkgbase + if ispkgbase; then + err "The system is already running packaged base" + fi + + # Update the repository + pkg_update + + # Some paths + local debug=/usr/lib/debug + local ld=/libexec/ld-elf.so.1 + local ld32=/libexec/ld-elf32.so.1 + local test=/usr/tests/Kyuafile + local src=/usr/src + + # Sanity check + if ! exists "${ld}"; then + err "No base system found" + fi + + # Decide whether to register base-dbg + if ! exists "${debug}${ld}.debug"; then + warn "No debugging symbols found" + else + sets="${sets} base-dbg" + fi + + # Decide whether to register lib32 and lib32-dbg + if ! pkg_exists ${OS}-set-lib32; then + # Not available + elif ! exists "${ld32}"; then + warn "No 32-bit loader found" + else + sets="${sets} lib32" + if exists "${debug}${ld32}.debug"; then + sets="${sets} lib32-dbg" + fi + fi + + # Decide whether to register tests + if ! exists "${test}"; then + warn "No test suite found" + else + sets="${sets} tests" + fi + + # Decide whether to register kernels and kernels-dbg + local kernel=/boot/kernel/kernel + if [ -z "${jail}${base}" ]; then + if ! kernel=$(/sbin/sysctl -qn kern.bootfile); then + err "Unable to identify the running kernel" + fi + case ${kernel%/kernel} in + *.old) + kernel=${kernel%.old/kernel}/kernel + ;; + esac + case ${kernel} in + /boot/kernel/kernel) + ;; + *) + kernel= + ;; + esac + fi + if [ -z "${kernel}" ] || ! exists "${kernel}"; then + warn "Non-standard kernel, or no kernel installed" + kernel= + else + sets="${sets} kernels" + if exists "${debug}${kernel}.debug"; then + sets="${sets} kernels-dbg" + fi + fi + + # Decide whether to register src + if ! exists "${src}/Makefile.inc1"; then + warn "No source tree found" + elif exists "${src}/.git"; then + warn "Source tree managed by Git " + else + sets="${sets} src" + fi + + # We now have our list of sets + sets=$(for set in ${sets}; do echo ${OS}-set-$set; done) + + if ! [ "${quiet}" ] || ! [ "${yes}" ]; then + echo "The following package sets will be installed:" + echo + pkg_rquery "%n %c" ${sets} | \ + /usr/bin/sed 's/ (metapackage)//' | + /usr/bin/column -tl2 | + /usr/bin/sed 's/^/ /' + echo + fi + + # Final checkpoint + if ! [ "${auto}" ] && ! confirm "Proceed with conversion?"; then + err "Conversion abandoned" + fi + + # Download the packages first + warn "Downloading packages, this may take a while..." + pkg_fetch -d -y ${sets} + + # Now register them + pkg_register -y ${sets} + + # Force-upgrade + if ! [ "${auto}" ] && confirm "Reinstall base packages?"; then + pkg_upgrade -f -y + fi + + # Check if BACKUP_LIBRARIES is turned on + case $(pkg config BACKUP_LIBRARIES) in + no) + warn "The recommended BACKUP_LIBRARIES option is not enabled" + if ! [ "${auto}" ] && + confirm "Enable BACKUP_LIBRARIES option?"; then + if ! [ "${dryrun}" ]; then + v /usr/bin/sed -i.bak \ + -e $'1i\\\nBACKUP_LIBRARIES = true;' \ + $(path ${localbase}/etc/pkg.conf) + fi + info "BACKUP_LIBRARIES option enabled" + fi + ;; + esac + + # Done! + if ! [ "${dryrun}" ]; then + info "Conversion complete" + fi +} + +# +# Convert from pkgbase +# +depkgbasify() { + local havesrc= pkg= set= + + # Check if we're running pkgbase + if ! ispkgbase; then + err "The system is not running packaged base" + fi + + # Identify and update the repository + repo=$(pkg_query %R ${OS}-runtime) + info "Using repository ${repo}" + pkg_update + + # Check which sets are partially or completely installed + info "Examining the system..." + for set in ${topsets}; do + if pkg_installed ${OS}-set-${set}; then + info "The ${set} set is installed" + continue + elif ! pkg_exists %v ${OS}-set-${set}; then + # set does not exist + continue + fi + local want=$(pkg_alldeps ${OS}-set-${set} | grep -v ${OS}-set) + local have=$(pkg_query %n ${want} || true) + if [ "${have}" = "${want}" ]; then + info "The ${set} set is complete" + elif [ "${have}" ]; then + info "The ${set} set is partially installed" + if ! [ "${auto}" ] && + confirm "Complete the ${set} set?"; then + pkg_fetch -d -y ${OS}-set-${set} + pkg_install -y ${OS}-set-${set} + fi + else + info "The ${set} set is absent" + fi + done + + # Check if the source tree is installed + for pkg in set-src src-sys src; do + if pkg_installed ${OS}-${pkg}; then + havesrc="${havesrc} ${OS}-${pkg}" + fi + done + if [ "${havesrc}" ]; then + info "The source tree appears to be installed. You may want" \ + "to uninstall it before converting to make room for a" \ + "Git clone." + if ! [ "${auto}" ] && confirm "Uninstall the source tree?"; then + pkg_remove -fy ${havesrc} + fi + fi + + # One final upgrade? + if ! [ "${auto}" ] && confirm "Upgrade installed base packages?"; then + pkg_upgrade -y + fi + + # Final checkpoint + if ! [ "${auto}" ] && ! confirm "Proceed with conversion?"; then + err "Conversion abandoned" + fi + + # Unregister all base packages + pkg_unregister -f -y $(pkg_query -e '%o ~ base/*' '%n') + + # Done! + if ! [ "${dryrun}" ]; then + info "Conversion complete" + fi +} + +# +# Print usage message and exit +# +usage() { + exec >&3 + echo -n "usage: ${progname} " + case ${progname%.sh} in + pkgbasify) + echo "[-hnqtv] [-a | -y] [-b basedir] [-j jail] [-r repo]" + ;; + depkgbasify) + echo "[-hnqv] [-a | -y] [-b basedir] [-j jail]" + ;; + *) + echo "-h" + ;; + esac + exit 1 +} + +# +# Entry point +# +main() { + local opt + + # Check program name and set defaults + case ${progname%.sh} in + pkgbasify) + repo=${BASEREPO} + ;; + depkgbasify) + ;; + *) + usage + ;; + esac + + # Parse options + while getopts "ab:hj:nr:qtvy" opt; do + case ${opt} in + a) + auto=true + ;; + b) + base="${OPTARG}" + ;; + h) + usage + ;; + j) + jail="${OPTARG}" + ;; + n) + dryrun=true + ;; + r) + repo="${OPTARG}" + ;; + q) + quiet=true + ;; + t) + trim=true + ;; + v) + verbose=true + ;; + y) + yes=true + ;; + *) + usage + ;; + esac + done + shift $((OPTIND - 1)) + + # Check for conflicting options + if [ "${auto}" ] && [ "${yes}" ]; then + usage + fi + case ${progname%.sh} in + depkgbasify) + if [ "${repo}" ] || [ "${trim}" ]; then + usage + fi + ;; + esac + + # Bootstrap pkg if necessary + pkg_bootstrap + + # Check the pkg version + check_pkg + + # Do what we were asked to do + case ${progname%.sh} in + pkgbasify) + pkgbasify "$@" + ;; + depkgbasify) + depkgbasify "$@" + ;; + esac +} + +main "$@"