- New 'windows' job runs unit tests on windows-latest with coverage
- New 'cross-compile' matrix job builds for windows/darwin/freebsd/openbsd
- Integration test file for winget (gated behind integration build tag)
- Windows coverage included in codecov upload
Implements the full snack.Manager interface for winget:
- Install/Remove/Purge/Upgrade via winget CLI
- Search/List/Info/IsInstalled/Version queries
- Source (repository) management via RepoManager
- Version querying via VersionQuerier
- Targeted package upgrades via PackageUpgrader
- Name normalization via NameNormalizer
All commands use --disable-interactivity, --accept-source-agreements,
and --accept-package-agreements for non-interactive operation.
Parser handles winget's fixed-width tabular output by detecting column
positions from the header/separator lines. Includes VT100 escape
sequence stripping and progress line filtering.
Windows-only via build tags; other platforms return
ErrUnsupportedPlatform. Registered in detect_windows.go as the
default Windows package manager.
ports/capabilities_openbsd.go duplicated autoremove, clean, fileList,
and owner already defined in ports_openbsd.go, breaking OpenBSD builds.
detect/detect_other.go build tag didn't exclude windows, conflicting
with detect_windows.go declarations.
The capabilities_linux.go deletion moved VersionQuerier methods
(latestVersion, listUpgrades, upgradeAvailable, versionCmp) to
capabilities.go as receiver methods, but their platform implementations
were not added to flatpak_linux.go, causing build failure on Linux.
Also removes accidentally committed .DS_Store, .crush/, and AGENTS.md.
- Add brew package for Homebrew support on macOS and Linux
- Implement NameNormalizer interface (NormalizeName, ParseArch) for all providers
- Add darwin platform detection with Homebrew as default
- Consolidate capabilities by removing separate *_linux.go/*_other.go files
- Update tests for new capability expectations
- Add comprehensive tests for AUR and brew providers
- Update README with capability matrix and modern Target API usage
💘 Generated with Crush
Assisted-by: AWS Claude Opus 4.5 via Crush <crush@charm.land>
- snap integration test asserted Clean=false, but snap now implements
Cleaner — updated to assert True
- flatpak CI job now installs Flatseal before running integration tests
so Version/List tests have a known installed package
detect package failed to compile on non-Linux/FreeBSD/OpenBSD because
candidates() and allManagers() had no fallback. Added detect_other.go
with empty implementations.
- Fix usage examples to use snack.Targets() and snack.Target
- Replace construction emoji status with actual extras per provider
- Document all interfaces including PackageUpgrader and DryRunner
- Add Options section documenting all functional options
- Add full CLI command reference with examples
- Remove implementation priority (everything is implemented)
Add 740 total tests (up from ~200) covering:
- Compile-time interface compliance for all providers
- GetCapabilities assertions for every provider
- Parse function edge cases: empty, malformed, single-entry, multi-entry
- apt: extract inline parse logic into testable functions (parsePolicyCandidate,
parseUpgradeSimulation, parseHoldList, parseOwner, parseSourcesLine)
- dnf/rpm: edge cases for both dnf4 and dnf5 parsers, normalize/parseArch
- pacman/aur: parseUpgrades, parseGroupPkgSet, capabilities
- apk: parseUpgradeSimulation, parseListLine, SupportsDryRun
- flatpak/snap: semverCmp, stripNonNumeric edge cases
- pkg/ports: all parse functions with thorough edge cases
Every provider now has:
- Interface compliance checks (what it implements AND what it doesn't)
- Capabilities test via snack.GetCapabilities()
- Parse function unit tests with table-driven edge cases
Replace exec.Command git clone/pull with go-git's PlainCloneContext
and Worktree.Pull. Removes git binary dependency — only makepkg and
pacman are needed on the host now.
Native Go implementation using the AUR RPC v5 API for search/info
queries and git+makepkg+pacman for building and installing packages.
Implements:
- Manager (full: Install, Remove, Purge, Upgrade, Update, List, Search,
Info, IsInstalled, Version)
- VersionQuerier (LatestVersion, ListUpgrades, UpgradeAvailable, VersionCmp)
- Cleaner (Autoremove via pacman, Clean build dir)
- PackageUpgrader (UpgradePackages)
Key design decisions:
- No CLI wrapper (paru/yay) — uses AUR RPC API directly + git clone
- Packages are built with makepkg and installed via pacman -U
- Foreign packages (pacman -Qm) are treated as AUR packages for List
- Batch RPC queries (rpcInfoMulti) for efficient upgrade checks
- Configurable build directory and makepkg flags
- Not added to detect.Default() candidates (AUR supplements pacman,
not replaces it) but available via detect.ByName("aur")
- Fix bug in extractURL where multi-token option blocks like
[arch=amd64 signed-by=/path/key.gpg] were not properly skipped,
causing the option value to be returned instead of the URL
- Add comprehensive unit tests for parseList, parseSearch, parseInfo
edge cases (empty input, missing fields, special characters)
- Add unit tests for normalizeName and parseArch covering all
supported Debian architectures and edge cases
- Add unit tests for formatTargets, buildArgs (all option combos),
and extractURL (basic, options, signed-by)
- Coverage: apt package 7.5% -> 17.1%
The ports package was fully implemented but detect_openbsd.go still
returned nil candidates with a stale TODO. Wire up ports.New() so
OpenBSD systems can auto-detect their package manager.
Also adds:
- Unit tests for GetCapabilities with mock managers (base + full)
- Unit tests for Locker mutual exclusion
- Edge case tests for ports parser (empty input, whitespace, fallback)
- Minor dep updates (charmbracelet/ultraviolet, charmbracelet/x)
The tests expected Install("tree") to error because dpkg/rpm need
a .deb/.rpm file path. But "tree" is pre-installed in CI containers,
so the code short-circuits to "unchanged" and returns nil.
Use a non-existent package name instead to exercise the actual
install failure path.
GroupQuerier was an unnecessary indirection — GroupIsInstalled is a group
operation and belongs on Grouper. No v1 stability guarantee, so breaking
the interface is fine.