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.
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
- linux_managers.go
- linux_managers_linux.go
- manager.go
- platform.go
- purl.go
- token.go
- windows_managers.go
- windows_managers_other.go