meta_package_manager.managers.pkg module¶
FreeBSD package managers.
Two managers share this module because they share the FreeBSD ecosystem and the same on-disk install database:
PKGwraps the binarypkgfrontend, which fetches pre-compiled artifacts from the official FreeBSD repository.Portswraps the source-build workflow rooted at/usr/ports, driving make recipes directly and delegating registry queries back topkg.
References:
- meta_package_manager.managers.pkg.PORTS_TREE = PosixPath('/usr/ports')¶
Canonical location of the FreeBSD ports tree.
The Handbook documents this path as the convention;
PORTSDIRcan override it, but every tool and consumer in the wild assumes this default.
- class meta_package_manager.managers.pkg.PKG[source]¶
Bases:
PackageManagerFreeBSD’s binary pkg frontend, fetching pre-compiled artifacts from the official FreeBSD repository.
Only root may modify the package database, so mutating operations escalate through
sudoby default, like thePortssibling.Note
outdatedparsespkg upgrade --dry-runrather thanpkg version, because only the dry-run names the target version each package would move to.Caution
syncforcesIGNORE_OSVERSION=yes: a package built for a newer FreeBSD than the running kernel would otherwise trigger an interactive confirmation that hangs the subprocess. It is passed as a-ocommand-line option rather than an environment variable, which sudo’s environment reset would strip from the escalated call. Support for that setting is also why the version floor is1.11.Initialize
cli_errorslist.- name: str = 'FreeBSD pkg'¶
Return package manager’s common name.
Default value is based on class name.
- homepage_url: str | None = 'https://github.com/freebsd/pkg'¶
Home page of the project, only used in documentation for reference.
- logo: str | None = 'freebsd'¶
Slug of the brand mark standing for this manager in the documentation.
Names an SVG vendored under
docs/assets/managers/, whose provenance and license are recorded indocs/assets/managers/logos.yaml. Inlined at the top of the manager’s page bymeta_package_manager._docs; a manager leaving it unset keeps the page’s default package glyph.Several managers legitimately share one slug, either because they wrap the same upstream (
brewandcask) or because the tool has no mark of its own and its ecosystem’s stands in (aptunder Debian’s swirl,cargounder Rust’s gear). Documentation-only, likehomepage_url: no CLI output reads it.
- keywords: tuple[str, ...] = ('freebsd',)¶
Well-known names for this manager that its
iddoes not already carry.Merged into the PyPI keywords of
pyproject.tomlbyupdate_keywords()ofdocs/docs_update.py, alongside every manager ID and the globally curatedKEYWORDS_EXTRAS. Declare an alias here rather than in that tuple whenever it names this manager: an alias living beside the class it describes cannot outlive it, where a central entry silently rots once the manager is renamed or dropped.Reserve
KEYWORDS_EXTRASfor terms belonging to no manager in particular, likecyclonedxorpackage manager. Documentation-only: no CLI output reads it.
- platforms: frozenset[Platform] | Group | Platform | Iterable[Platform | Group] = frozenset({Platform(id='freebsd', name='FreeBSD')})¶
List of platforms supported by the manager.
Allows for a mishmash of platforms and groups of platforms. Will be normalized into a
frozensetofPlatforminstances at instantiation.
- default_sudo: bool = True¶
Built-in escalation default, used when
sudoisNone.Falseon the base: most managers install into user-writable trees and never need root. The system package managers whose privileged operations require root (apt,dnf,pacman,zypper, …) set this toTrueso theirbuild_cli(..., sudo=True)operations escalate out of the box, while staying switchable off throughsudo(--no-sudoor config) for rootless setups.
- requirement: str | None = '>=1.11'¶
1.11 is the first version to support the
IGNORE_OSVERSIONsetting.$ pkg --version 1.20.9
- property installed: Iterator[Package]¶
Fetch installed packages.
$ pkg query "%n %v %c" 7-zip 21.07_2 Console version of the 7-Zip file archiver ap24-mod_mpm_itk 2.4.7_2 Run each vhost under a separate uid and gid apache24 2.4.57 Version 2.4.x of Apache web server aquantia-atlantic-kmod 0.0.5_1 Aquantia AQtion (Atlantic) Network Driver arcconf 3.07.23971,1 Adaptec SCSI/SAS RAID administration tool areca-cli-amd64 1.14.7.150519,1 Command Line Interface for ARC-xxxx RAID base64 1.5_1 Utility to encode and decode base64 files bash 5.1.12 GNU Project's Bourne Again SHell beadm 1.4_1 Solaris-like utility to manage Boot Environments on ZFS
- property outdated: Iterator[Package]¶
Fetch outdated packages.
$ pkg upgrade --quiet --dry-run Updating FreeBSD repository catalogue... FreeBSD repository is up to date. All repositories are up to date. Checking for upgrades (312 candidates): 100% Processing candidates (312 candidates): 100% The following 466 package(s) will be affected (of 0 checked): Installed packages to be REMOVED: freenas-files: 13.0_1700495253 py39-midcli: 20190509171453 py39-middlewared: 13.0_1700495253 New packages to be INSTALLED: abseil: 20230125.3 [FreeBSD] argp-standalone: 1.5.0 [FreeBSD] brotli: 1.1.0,1 [FreeBSD] Installed packages to be UPGRADED: 7-zip: 21.07_2 -> 23.01 [FreeBSD] apache24: 2.4.57 -> 2.4.58_1 [FreeBSD] apr: 1.7.0.1.6.1_1 -> 1.7.3.1.6.3_1 [FreeBSD] aquantia-atlantic-kmod: 0.0.5_1 -> 0.0.5_2 [FreeBSD] bash: 5.1.12 -> 5.2.21 [FreeBSD]
Note
We rely on
pkg upgradeinstead ofpkg versionbecause the latter does not provides the new version:$ pkg version --like "<" Updating FreeBSD repository catalogue... FreeBSD repository is up to date. All repositories are up to date. 7-zip-21.07_2 < apache24-2.4.57 < apr-1.7.0.1.6.1_1 < aquantia-atlantic-kmod-0.0.5_1 < bash-5.1.12 <
- property orphans: Iterator[Package]¶
Fetch packages installed as dependencies that nothing requires anymore.
--dry-runturnsautoremoveinto a read-only report of the would-be-removed packages.$ pkg autoremove --quiet --dry-run Checking integrity... done (0 conflicting) Deinstallation has been requested for the following 2 packages: Installed packages to be REMOVED: libiconv: 1.17 pcre: 8.45_3 Number of packages to be removed: 2
- search(query, extended, exact)[source]¶
Fetch matching packages.
Caution
The result is a single JSON array, not one object per line.
--rawwraps every match in one, andjson-compactonly strips the whitespace. The stream of bare objects this once parsed waspkg1.x’s shape; the array below is what 2.7.5 returns.Caution
--quietstays out of this command even thoughsearchaccepts it: it overrides--rawand collapses the output to bare<name>-<version>tokens, which carry neither the version field nor the comment.A search matching nothing exits
1with an empty array on<stdout>and nothing on<stderr>, which is why nomust_succeedis passed: mpm only counts a non-zero exit as a failure when<stderr>is non-empty, so the empty result reads as one.Default search on ID substring, truncated for width:
$ pkg search --raw --raw-format json-compact --search name nyancat [{"name":"nyancat","origin":"net/nyancat","version":"1.5.2,1","comment":"Animated telnet server that renders a loop of the nyan cat animation",(...)}]
Exact search on ID:
$ pkg search --raw --raw-format json-compact --search name --exact nyancat
Extended search over the comment and description fields:
$ pkg search --raw --raw-format json-compact --search name --search comment --search description nyancat
- install(package_id, version=None)[source]¶
Install one package.
$ sudo pkg install --quiet --yes dmg2img Updating FreeBSD repository catalogue... FreeBSD repository is up to date. All repositories are up to date. Checking integrity... done (0 conflicting) The following 1 package(s) will be affected (of 0 checked): New packages to be INSTALLED: dmg2img: 1.6.7 [FreeBSD] Number of packages to be installed: 1 [1/1] Installing dmg2img-1.6.7... [1/1] Extracting dmg2img-1.6.7: 100%
- Return type:
- upgrade_all_cli()[source]¶
Generates the CLI to upgrade all outdated packages.
$ sudo pkg upgrade --quiet --yes
- upgrade_one_cli(package_id, version=None)[source]¶
Generates the CLI to upgrade the provided package.
$ sudo pkg upgrade --quiet --yes dmg2img
- remove(package_id)[source]¶
Remove one package.
$ sudo pkg delete --quiet --yes dmg2img Checking integrity... done (0 conflicting) Deinstallation has been requested for the following 1 packages: Installed packages to be REMOVED: dmg2img: 1.6.7 Number of packages to be removed: 1 [1/1] Deinstalling dmg2img-1.6.7... [1/1] Deleting files for dmg2img-1.6.7: 100% pkg: Package database is busy while closing!
- Return type:
- sync()[source]¶
Sync package metadata.
$ sudo pkg -o IGNORE_OSVERSION=yes update --quiet Updating FreeBSD repository catalogue... Fetching meta.conf: 100% 163 B 0.2kB/s 00:01 Fetching packagesite.pkg: 100% 7 MiB 3.6MB/s 00:02 Processing entries: 100% FreeBSD repository update completed. 33804 packages processed. All repositories are up to date.
The
IGNORE_OSVERSION=yesprevents blocking update:$ pkg update --quiet Updating FreeBSD repository catalogue... Fetching meta.conf: 100% 163 B 0.2kB/s 00:01 Fetching packagesite.pkg: 100% 7 MiB 3.6MB/s 00:02 Processing entries: 0% Newer FreeBSD version for package zziplib: To ignore this error set IGNORE_OSVERSION=yes - package: 1302001 - running kernel: 1301000 Ignore the mismatch and continue? [y/N]:
- Return type:
- cleanup_orphan()[source]¶
Remove every package installed as a dependency and no longer required.
$ sudo pkg autoremove --quiet --yes Checking integrity... done (0 conflicting) Nothing to do.
- Return type:
- cleanup_cache()[source]¶
Delete every cached package from the local cache directory.
$ sudo pkg clean --quiet --yes --all Nothing to do.
- Return type:
- doctor_cli()[source]¶
Generates the CLI running the native self-diagnosis.
check --checksumsvalidates every installed package’s files against their recorded checksums, exiting non-zero on mismatches.$ pkg check --checksums --all
- cli_names: tuple[str, ...] = ('pkg',)¶
List of CLI names the package manager is known as.
This list of recognized CLI names is ordered by priority. That way we can influence the search of the right binary.
- ..hint::
This was helpful in the case of the Python transition from 2.x to 3.x, where multiple versions of the same executable were named
pythonorpython3.
By default, this property’s value is derived from the manager’s ID (see the
MetaPackageManager.__init__method above).
- class meta_package_manager.managers.pkg.Ports[source]¶
Bases:
PackageManagerFreeBSD ports tree: the source-build workflow rooted at
/usr/ports.Note
Coexists with
PKGon the same system: both share the install database maintained bypkg.Portsbuilds and tracks ports compiled from source under/usr/ports, whilePKGhandles binary packages from the FreeBSD repository. Listing operations may overlap becausepkgdoes not distinguish ports-built from binary-installed packages once they are registered.Note
installedandoutdateddelegate to the siblingpkgbinary, since the ports tree keeps no registry of its own. Builds drive FreeBSD’smakedirectly withBATCH=yesto accept default build options without prompting. Upgrades shell out to the third-partyportmaster: the ports tree ships no batch upgrader.syncrefreshes the tree withgit(portsnapwas removed after FreeBSD 13).Caution
Mutating operations require root privileges and a populated ports tree at
/usr/ports. The manager flags itself unavailable when the tree is missing.Caution
Mutating operations compile from source, so their duration is set by the port rather than by the network. A small library finishes well inside the 500 second ceiling
mpmputs on a state-changing command (expattakes about a minute), where a compiler or a browser runs for hours and reportsTimed out after 500s. Raise the ceiling for this manager alone, in the configuration file:[mpm.overrides.ports] timeout = 14400
No single value fits, a build scaling with the port, its dependency tree and the machine.
syncandinstalledare unaffected, delegating togitandpkgrather than building.Initialize
cli_errorslist.- name: str = 'FreeBSD Ports Collection'¶
Return package manager’s common name.
Default value is based on class name.
- homepage_url: str | None = 'https://www.freebsd.org/ports/'¶
Home page of the project, only used in documentation for reference.
- logo: str | None = 'freebsd'¶
Slug of the brand mark standing for this manager in the documentation.
Names an SVG vendored under
docs/assets/managers/, whose provenance and license are recorded indocs/assets/managers/logos.yaml. Inlined at the top of the manager’s page bymeta_package_manager._docs; a manager leaving it unset keeps the page’s default package glyph.Several managers legitimately share one slug, either because they wrap the same upstream (
brewandcask) or because the tool has no mark of its own and its ecosystem’s stands in (aptunder Debian’s swirl,cargounder Rust’s gear). Documentation-only, likehomepage_url: no CLI output reads it.
- keywords: tuple[str, ...] = ('freebsd ports',)¶
Well-known names for this manager that its
iddoes not already carry.Merged into the PyPI keywords of
pyproject.tomlbyupdate_keywords()ofdocs/docs_update.py, alongside every manager ID and the globally curatedKEYWORDS_EXTRAS. Declare an alias here rather than in that tuple whenever it names this manager: an alias living beside the class it describes cannot outlive it, where a central entry silently rots once the manager is renamed or dropped.Reserve
KEYWORDS_EXTRASfor terms belonging to no manager in particular, likecyclonedxorpackage manager. Documentation-only: no CLI output reads it.
- platforms: frozenset[Platform] | Group | Platform | Iterable[Platform | Group] = frozenset({Platform(id='freebsd', name='FreeBSD')})¶
List of platforms supported by the manager.
Allows for a mishmash of platforms and groups of platforms. Will be normalized into a
frozensetofPlatforminstances at instantiation.
- default_sudo: bool = True¶
Built-in escalation default, used when
sudoisNone.Falseon the base: most managers install into user-writable trees and never need root. The system package managers whose privileged operations require root (apt,dnf,pacman,zypper, …) set this toTrueso theirbuild_cli(..., sudo=True)operations escalate out of the box, while staying switchable off throughsudo(--no-sudoor config) for rootless setups.
- cli_names: tuple[str, ...] = ('make',)¶
The ports tree is driven by FreeBSD’s make.
No dedicated frontend exists; each port is a directory whose
Makefiletargets are invoked directly.
- extra_env: ClassVar = {'BATCH': 'yes'}¶
Force non-interactive builds.
Many ports prompt for build option dialogs by default.
BATCH=yesaccepts the saved or default options without user interaction, which is the only sensible behavior for an automated tool. Seeports(7).
- version_cli_options: tuple[str, ...] = ('-V', 'MAKE_VERSION')¶
FreeBSD
makeexposes its version via internal variable expansion.GNU Make’s
--versionflag does not work on BSD make, so the probe reads the variable instead, which also avoids matching a GNU Make installation shadowing the BSD binary.The variable is
MAKE_VERSION, the onemake(1)documents as “the version of make (…) typically the date of last import from NetBSD”. The dotted.MAKE.VERSIONthis once read is not among the.MAKE.*family that page lists, and expands to the empty string: the probe then found no version at all, which leftportspermanently unavailable rather than merely misreported.
- version_regexes: tuple[str, ...] = ('(?P<version>\\d{8,})',)¶
BSD make reports its version as a date-like integer (e.g.
20240218).
- property available: bool[source]¶
Available only when
makeis found and the ports tree exists.The make binary alone is not enough: without a populated
/usr/portsdirectory, every operation would fail. Treat the tree as part of the manager’s runtime requirement.
- id: str = 'ports'¶
Package manager’s ID.
Derived by defaults from the lower-cased class name in which underscores
_are replaced by dashes-.This ID must be unique among all package manager definitions and lower-case, as they’re used as feature flags for the mpm CLI.
- property installed: Iterator[Package]¶
Fetch packages currently registered as installed.
Delegates to
pkg querybecause the ports tree itself maintains no registry: ports installs are recorded in the same database as binarypkginstalls.$ pkg query "%n %v %o %c" curl 8.7.1 ftp/curl Non-interactive tool to get files from FTP/HTTP servers python311 3.11.9 lang/python311 Interpreted object-oriented programming language
- virtual: bool = False¶
Should we expose the package manager to the user?
Virtual package manager are just skeleton classes used to factorize code among managers of the same family.
- property outdated: Iterator[Package]¶
Fetch packages whose installed version lags the ports tree.
Uses
pkg versionin ports-comparison mode (-P): it walks the local tree for each installed package and reports those with a newerMakefileversion available.-L =drops the packages that are already current, so every reported line is an actionable one.-I, which reads/usr/ports/INDEX-<major>instead of the tree, is not combined with it:pkgaccepts only one source and exits with a usage error on-vIPL=. The tree is also whatavailablealready requires, where the index is a separate file the user has to fetch.$ pkg version -vPL= expat-2.8.2 < needs updating (port has 2.8.3) git-2.54.0 < needs updating (port has 2.55.0) libffi-3.6.0 < needs updating (port has 3.8.0) FreeBSD-acct-15.1 ? orphaned: base/FreeBSD-acct
- install(package_id, version=None)[source]¶
Build and install a port from source.
package_idmay be either a bare port name likenginxor its full origin likewww/nginx. A bare name is resolved to its origin through_resolve_origin, which queries the active repository.The block below illustrates rather than captures: the origin is resolved by a query, so the corpus cannot rebuild this command from a stand-in package id. Read the exact argv off
mpm --plan install.$ sudo make -C /usr/ports/www/nginx install clean BATCH=yes
- Return type:
- upgrade_all_cli()[source]¶
Generate the CLI to upgrade every outdated port.
The ports tree has no first-party batch upgrader; the workflow relies on the third-party
portmastertool. We build the command line without checking thatportmasteris installed, because upgrade commands are typically printed for the user to inspect before running.-Gis what makes the run unattended, and--no-confirmdoes not cover it:portmasterinvokesmake configfor any port whose options were never saved, which spawns theportconfigdialog even underBATCH=yes. With no terminal to answer it, the dialog spins untilmpmtimes out the whole command, having built nothing.Both flags stay short because
portmaster3.35 offers no long form for either: its parser accepts--force-config, the opposite of-G, and nothing spelling-a.$ sudo portmaster --no-confirm --no-term-title -G -a
- upgrade_one_cli(package_id, version=None)[source]¶
Generate the CLI to upgrade one port via
portmaster.Carries
-Gfor the reasonupgrade_all_cli()gives: without itportmasterstops on theportconfigoptions dialog.$ sudo portmaster --no-confirm --no-term-title -G www/nginx
- remove¶
Reuses
PKG.remove(): the ports tree has no native uninstaller, and removal goes through the shared install database regardless of how the package was originally built.
- sync()[source]¶
Refresh the local ports tree from upstream.
Modern FreeBSD distributes the ports tree via Git;
portsnapwas deprecated and removed after FreeBSD 13. We pull from whatever remote the tree was checked out from.$ sudo git -C /usr/ports pull --ff-only
- Return type:
- cleanup_cache()[source]¶
Remove cached build artifacts from the ports tree.
Walks the tree once and invokes make clean at the root, which recursively cleans every port’s work directory.
DISTCLEAN=yesalso removes downloaded distfiles.$ sudo make -C /usr/ports clean DISTCLEAN=yes BATCH=yes
- Return type: