Documentation
¶
Overview ¶
Package platform models a target platform as a standalone, op-free capability.
A platform is its OS, architecture, distro, and the package and service managers available on it. It is constructed by cloning a named default Spec (e.g. Debian, Fedora, Darwin, Windows) or by detecting the host (Detect), optionally mutating the spec via its `With*` methods, then sealing it with New. The sealed Platform exposes its identity plus one PackageManager — the Composite router over the platform's leaf drivers — and one ServiceManager. `pkg/platform` imports nothing from `pkg/op`; `pkg/op` imports it (the same shape as `pkg/result` and `pkg/status`).
Build tags apply only to the per-OS manager primitives (`*_<os>.go`) and host detection (`detect_<os>.go`). The manager types and the contract compile on every host, so a graph can target any platform from any host; the run-time preflight catches target-vs-host mismatches before a wrong-platform manager is invoked.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DetectToken ¶
func DetectToken() string
DetectToken detects the host platform and returns its canonical token, falling back to "Linux" when detection fails.
Returns:
- `string`: the host's canonical token, or "Linux" when the host cannot be detected.
func Token ¶
Token returns the canonical dotted platform token: "Darwin", "Windows", "Linux.Debian", "Linux.Fedora", or "Linux" when the distro family is unknown.
The token is the vocabulary the devlore tools share — lore's registry resolves platform-partitioned script directories by it (`docker/Linux.Debian/Deploy/`), writ's tree matches segment-variant directories with the same capitalized names, and manifest planning selects releases by it. Distro grouping is by package-manager family: apt-based distributions render as `Linux.Debian`, dnf/yum-based as `Linux.Fedora`.
Parameters:
- `p`: the platform to render.
Returns:
- `string`: the canonical token.
Types ¶
type PURL ¶
type PURL struct {
Type string // package ecosystem ("brew", "deb", "winget", etc.)
Namespace string // owner/group prefix (winget publisher, npm scope, Maven group ID)
Name string // the package name
Version string // release version
Qualifiers map[string]string // key=value pairs (OS, arch, repository, distro)
Subpath string // path within the package
}
PURL is a structured Package URL (purl) identity, modeled after url.URL.
The purl specification defines the canonical format:
pkg:{type}/{namespace}/{name}@{version}?{qualifiers}#{subpath}
Type and Name are required. All other components are optional.
func ParseIdentifier ¶
ParseIdentifier parses a package identifier into a PURL whose type is canonical for `plat`.
Three forms are accepted, and the canonical one is checked first. A string that declares the scheme is a purl: a parse failure is reported as one and never re-read as a manager prefix, since a fallback would turn a typo into a package named after it.
- `pkg:{type}/{namespace}/{name}@{version}?{qualifiers}`: the purl; its type resolves through Platform.ResolvePurlType.
- `{manager}:{name}[@{version}]`: the manager-prefix form; the prefix resolves the same way.
- `{name}[@{version}]`: the bare name, on the platform's default manager (Platform.DefaultPurlType).
The result is the identifier's full coordinates, version included. Identity is versionless: a caller that interns or compares packages clears `Version` first, so `jq` and `jq@1.7` are one package at two versions.
This is the one grammar for package identifiers. The pkg provider builds its resources from it and writ's manifest merge keys claims by it, so what is planned and what is compared are the same parse (#814).
Parameters:
- `plat`: the target platform; resolves manager prefixes and supplies the default type.
- `raw`: the identifier, in any of the three forms.
Returns:
- `PURL`: the parsed coordinates, with a canonical type.
- `error`: a malformed purl, or a purl type or manager prefix no manager on `plat` answers to.
type PackageManager ¶
type PackageManager interface {
// Install converges each package to present at the requested version.
//
// Parameters:
// - `packages`: the packages to install, each carrying its resolved [PURL].
// - `kwargs`: opaque native-installer flags passed through verbatim per manager (e.g. `cask`).
//
// Returns:
// - `receipts`: one [Receipt] per package, in input order; a receipt's `Err` is set from the observed
// post-state, not the command's exit code.
// - `err`: non-nil when any receipt failed.
Install(packages []PURL, kwargs map[string]any) (receipts []Receipt, err error)
// Remove converges each package to absent.
//
// Parameters:
// - `packages`: the packages to remove, each carrying its resolved [PURL].
// - `kwargs`: opaque native-installer flags passed through verbatim per manager.
//
// Returns:
// - `receipts`: one [Receipt] per package, in input order.
// - `err`: non-nil when any receipt failed.
Remove(packages []PURL, kwargs map[string]any) (receipts []Receipt, err error)
// Upgrade moves each named package to the latest available version.
//
// Parameters:
// - `packages`: the packages to upgrade, each carrying its resolved [PURL].
// - `kwargs`: opaque native-installer flags passed through verbatim per manager.
//
// Returns:
// - `receipts`: one [Receipt] per package, in input order.
// - `err`: non-nil when any receipt failed.
Upgrade(packages []PURL, kwargs map[string]any) (receipts []Receipt, err error)
// Update forces an immediate index refresh, bypassing the automatic staleness gate.
//
// On a leaf it refreshes that leaf's index now — a no-op for a manager with no local index (a live-store
// manager such as snap / flatpak / winget). On the router it fans out to every leaf.
//
// Returns:
// - `error`: aggregated per-leaf refresh failures; nil when every refresh succeeded or had nothing to do.
Update() error
// Installed reports whether the package identified by `p` is installed.
//
// Parameters:
// - `p`: the package [PURL] to query.
//
// Returns:
// - `bool`: true when the package is installed.
Installed(p PURL) bool
// Version returns the installed version of the package identified by `p`, or empty when it is not installed.
//
// Parameters:
// - `p`: the package [PURL] to query.
//
// Returns:
// - `string`: the installed version, or "" when absent.
Version(p PURL) string
// Available reports whether the package identified by `p` exists in the manager's index.
//
// Parameters:
// - `p`: the package [PURL] to query.
//
// Returns:
// - `bool`: true when the package is available to install.
Available(p PURL) bool
// Search returns up to `limit` packages whose name or description matches `query`.
//
// Parameters:
// - `query`: the search term.
// - `limit`: the maximum number of results; `limit` <= 0 means no limit.
//
// Returns:
// - `[]SearchResult`: the matches, each tagged with the `Manager` that produced it; nil when none match.
Search(query string, limit int) []SearchResult
// Present reports whether the manager's executable is on the PATH.
//
// Alone among the queries this asks about the manager, not a package: it is a per-machine fact, so it
// neither varies by [PURL] nor consults an index. A [Spec] declares its managers from the detected OS and
// distro — "Debian-family, therefore apt" — which is a statement about the platform, not about this
// machine. Present is what closes that gap, and it does so with a PATH lookup: no subprocess, no network.
//
// It answers whether the tool is there, not whether an operation through it will succeed. A present
// manager can still fail to install — a lock, a bad mirror, no privilege — and that failure belongs to
// the operation that hits it, reported where it happens.
//
// Returns:
// - `bool`: true when the executable resolves on the PATH.
Present() bool
}
PackageManager is the Composite package-management contract.
The same surface serves a single leaf driver and the platform's router over many leaves. Routing is by purl: every package reaching a manager is a PURL whose `Type` selects the leaf (the router dispatches; a leaf ignores routing and acts on whatever slice it is handed). The mutating triad — Install / Remove / Upgrade — is best-effort across its slice and returns one Receipt per package; partial failure is normal. Index refresh is automatic and staleness-gated per leaf before index-consuming operations; PackageManager.Update is the manual force-refresh override (the router fans it out to every leaf). The query methods report a single package's observed state and back the veneer's predicates (Installed / Version / Available) and federated search.
type Platform ¶
type Platform interface {
// OS returns the operating system family ("linux", "darwin", "windows").
OS() string
// Arch returns the architecture ("amd64", "arm64", "arm/v7", etc.) per Docker's vocabulary.
Arch() string
// Distro returns the distribution identifier ("ubuntu", "fedora", "macos", "windows", etc.).
Distro() string
// Version returns the OS or distro version string ("22.04", "14.5", "11", etc.). Empty when unknown.
Version() string
// Hostname returns the host's network hostname. Empty when unavailable.
Hostname() string
// DefaultConcurrency returns a reasonable concurrency level for parallel operations — typically 4 × NumCPU.
DefaultConcurrency() int
// DefaultPurlType returns the purl type of the platform's default native manager (e.g. "deb" on Debian).
//
// The veneer uses it to normalize a bare package name into a typed purl.
DefaultPurlType() string
// ResolvePurlType maps a caller-supplied manager prefix — a manager name or a purl type — to the canonical
// purl type, reporting whether the prefix names a known manager on this platform.
ResolvePurlType(prefix string) (string, bool)
// PackageManager returns the platform's Composite router over its leaf drivers.
PackageManager() PackageManager
// ServiceManager returns the service manager for this platform (systemd, launchd, Service Control Manager).
ServiceManager() ServiceManager
}
Platform exposes a target's classification and the package and service managers available on it.
Implementations are immutable; construct via New. Callers receive a Platform from the runtime environment and never construct it directly outside of a named Spec factory + New or Detect + New.
func New ¶
New validates `spec` and returns the immutable Platform it describes.
Validation:
- OS must be set and one of "linux", "darwin", "windows".
- Arch must be in [knownArches]; empty defaults to `runtime.GOARCH` (which must itself be a known arch).
- For OS=="linux", Distro must be in [knownLinuxDistros]; for "darwin" it must be "macos"; for "windows", "windows".
Parameters:
Returns:
- `Platform`: the sealed platform value.
- `error`: a single descriptive error per failing validation.
type Receipt ¶
type Receipt struct {
// Purl is the package the operation acted on; its `Type` identifies the leaf that handled it.
Purl PURL
// PriorVersion is the installed version observed before the operation, or "" when the package was absent.
PriorVersion string
// Version is the installed version observed after the operation, or "" when the package is absent (removed).
Version string
// Err is non-nil when the observed post-state did not reach what the package's [PURL] requested.
Err error
}
Receipt records the outcome of one package operation.
State is observed by re-query, never by screen-scraping command output: a leaf pre-queries the installed version, runs the (idempotent) command, then re-queries — `PriorVersion` and `Version` are those two observations, and `Err` is set when the post-state did not reach what the package's PURL requested. One Receipt is produced per package; the Composite router concatenates the leaves' receipts into one unified result.
type Result ¶
type Result struct {
OK bool // whether the command exited zero
Stdout string // captured standard output, trailing newline trimmed
Stderr string // captured standard error, trailing newline trimmed
Code int // the process exit code (-1 when the command could not be launched)
}
Result represents a command-execution result.
It is returned by a leaf's raw shell-out primitives and by ServiceManager mutators.
type SearchResult ¶
type SearchResult struct {
Name string // the package name
Version string // the available version, when the manager reports one
Description string // a short description, when the manager reports one
Manager string // the purl type of the leaf that produced the hit (e.g. "deb", "brew")
}
SearchResult represents a package found by PackageManager.Search.
Manager records the leaf that produced the hit (the purl type, e.g. "deb", "brew"), so a federated search across the router's leaves yields results that self-identify their source.
type ServiceManager ¶
type ServiceManager interface {
// Exists reports whether a service with the given name is registered.
//
// Parameters:
// - `name`: the service name.
//
// Returns:
// - `bool`: true when the service exists.
Exists(name string) bool
// IsRunning reports whether the named service is currently running.
//
// Parameters:
// - `name`: the service name.
//
// Returns:
// - `bool`: true when the service is running.
IsRunning(name string) bool
// IsEnabled reports whether the named service is enabled to start at boot.
//
// Parameters:
// - `name`: the service name.
//
// Returns:
// - `bool`: true when the service is enabled.
IsEnabled(name string) bool
// Status returns a coarse, human-facing status for the named service.
//
// Parameters:
// - `name`: the service name.
//
// Returns:
// - `string`: the status (e.g. "running", "stopped").
Status(name string) string
// Start starts the named service.
//
// Parameters:
// - `name`: the service name.
//
// Returns:
// - `Result`: the command result.
Start(name string) Result
// Stop stops the named service.
//
// Parameters:
// - `name`: the service name.
//
// Returns:
// - `Result`: the command result.
Stop(name string) Result
// Enable enables the named service to start at boot.
//
// Parameters:
// - `name`: the service name.
//
// Returns:
// - `Result`: the command result.
Enable(name string) Result
// Disable disables the named service from starting at boot.
//
// Parameters:
// - `name`: the service name.
//
// Returns:
// - `Result`: the command result.
Disable(name string) Result
// NeedsSudo reports whether mutating service operations require elevation.
//
// Returns:
// - `bool`: true when elevation is required.
NeedsSudo() bool
}
ServiceManager abstracts service-management operations.
Concrete implementations exist for systemd (Linux), launchd (Darwin), and Service Control Manager (Windows).
type Spec ¶
type Spec struct {
// contains filtered or unexported fields
}
Spec is the mutable builder for a Platform.
Obtain one by cloning a named default (Debian, Fedora, Darwin, Windows, …) or via Detect, chain `With*` to override defaults, then pass it to New. Specs are mutable during the chain (each `With*` mutates the receiver and returns it). The caller should not retain the spec after New; the returned Platform is the durable value. The manager fields are populated by the named factories and are not part of the public `With*` surface.
func AlmaLinux ¶
func AlmaLinux() *Spec
AlmaLinux returns a fresh *Spec for AlmaLinux (dnf default; dnf + flatpak available).
Returns:
- `*Spec`: the fresh, mutable spec.
func CentOSStream ¶
func CentOSStream() *Spec
CentOSStream returns a fresh *Spec for CentOS Stream (dnf default; dnf + flatpak available).
Returns:
- `*Spec`: the fresh, mutable spec.
func Darwin ¶
func Darwin() *Spec
Darwin returns a fresh *Spec for macOS (brew default; brew + port available; launchd services).
Returns:
- `*Spec`: the fresh, mutable spec.
func Debian ¶
func Debian() *Spec
Debian returns a fresh *Spec for Debian (apt default; apt available).
Returns:
- `*Spec`: the fresh, mutable spec.
func Detect ¶
Detect inspects the running host and returns a fresh, mutable *Spec reflecting it.
The spec reflects the host's actual OS, distro, architecture, version, hostname, and managers; seal it into a Platform with New. Detect is the only host-inspecting entry point; the named factories (Debian, Fedora, Darwin, Windows, …) are deterministic and touch nothing on the host. On Linux, Detect reads /etc/os-release for the distro and refines the available-manager set per the running variant (stripping desktop-only managers like flatpak on server installs). On Darwin it runs `sw_vers`; on Windows, `cmd /c ver`.
Returns:
- `*Spec`: the detected host spec.
- `error`: when the host OS is not one of linux / darwin / windows, or when detection fails.
func Fedora ¶
func Fedora() *Spec
Fedora returns a fresh *Spec for Fedora (dnf default; dnf + flatpak available).
Returns:
- `*Spec`: the fresh, mutable spec.
func Mint ¶
func Mint() *Spec
Mint returns a fresh *Spec for Linux Mint (apt default; apt + flatpak available).
Returns:
- `*Spec`: the fresh, mutable spec.
func RHEL ¶
func RHEL() *Spec
RHEL returns a fresh *Spec for Red Hat Enterprise Linux (dnf default; dnf + flatpak available).
Returns:
- `*Spec`: the fresh, mutable spec.
func Rocky ¶
func Rocky() *Spec
Rocky returns a fresh *Spec for Rocky Linux (dnf default; dnf + flatpak available).
Returns:
- `*Spec`: the fresh, mutable spec.
func Ubuntu ¶
func Ubuntu() *Spec
Ubuntu returns a fresh *Spec for Ubuntu (apt default; apt + snap available).
Returns:
- `*Spec`: the fresh, mutable spec.
func Windows ¶
func Windows() *Spec
Windows returns a fresh *Spec for Windows (winget default and only; Service Control Manager services).
Returns:
- `*Spec`: the fresh, mutable spec.
func (*Spec) WithArch ¶
WithArch sets the architecture. Empty defaults to `runtime.GOARCH` at New time.
Parameters:
- `arch`: a [knownArches] value, or "" for the host arch.
Returns:
- `*Spec`: the receiver, for chaining.
func (*Spec) WithDefaultConcurrency ¶
WithDefaultConcurrency sets the suggested concurrency level for parallel operations.
Parameters:
- `n`: the concurrency level.
Returns:
- `*Spec`: the receiver, for chaining.
func (*Spec) WithHostname ¶
WithHostname sets the host's network hostname.
Parameters:
- `hostname`: the hostname.
Returns:
- `*Spec`: the receiver, for chaining.
func (*Spec) WithVersion ¶
WithVersion sets the OS or distro version string ("22.04", "14.5", etc.).
Parameters:
- `version`: the version string.
Returns:
- `*Spec`: the receiver, for chaining.
Source Files
¶
- composite.go
- constructors.go
- cross_distro_managers.go
- cross_distro_managers_linux.go
- darwin_managers.go
- darwin_managers_other.go
- defaults.go
- detect_linux.go
- driver.go
- helpers.go
- helpers_unix.go
- identifier.go
- linux_managers.go
- linux_managers_linux.go
- manager.go
- platform.go
- purl.go
- token.go
- windows_managers.go
- windows_managers_other.go