mirror of
https://github.com/gogrlx/snack.git
synced 2026-04-02 05:08:42 -07:00
Add optional interfaces that providers can implement beyond the base Manager. grlx can type-assert to check support at runtime: - VersionQuerier: LatestVersion, ListUpgrades, UpgradeAvailable, VersionCmp - Holder: Hold, Unhold, ListHeld (version pinning) - Cleaner: Autoremove, Clean (orphan/cache cleanup) - FileOwner: FileList, Owner (file-to-package mapping) - RepoManager: ListRepos, AddRepo, RemoveRepo - KeyManager: AddKey, RemoveKey, ListKeys (GPG signing keys) - Grouper: GroupList, GroupInfo, GroupInstall - NameNormalizer: NormalizeName, ParseArch Also adds GetCapabilities() helper, Repository type, and updated README.
142 lines
4.0 KiB
Markdown
142 lines
4.0 KiB
Markdown
# snack 🍿
|
|
|
|
Idiomatic Go wrappers for system package managers.
|
|
|
|
[](https://opensource.org/licenses/0BSD)
|
|
[](https://pkg.go.dev/github.com/gogrlx/snack)
|
|
|
|
**snack** provides thin, context-aware Go bindings for system package managers. Think [`taigrr/systemctl`](https://github.com/taigrr/systemctl) but for package management.
|
|
|
|
Part of the [grlx](https://github.com/gogrlx/grlx) ecosystem.
|
|
|
|
## Supported Package Managers
|
|
|
|
| Package | Manager | Platform | Status |
|
|
|---------|---------|----------|--------|
|
|
| `pacman` | pacman | Arch Linux | 🚧 |
|
|
| `aur` | AUR (makepkg) | Arch Linux | 🚧 |
|
|
| `apk` | apk-tools | Alpine Linux | 🚧 |
|
|
| `apt` | APT (apt-get/apt-cache) | Debian/Ubuntu | 🚧 |
|
|
| `dpkg` | dpkg | Debian/Ubuntu | 🚧 |
|
|
| `dnf` | DNF | Fedora/RHEL | 🚧 |
|
|
| `rpm` | RPM | Fedora/RHEL | 🚧 |
|
|
| `flatpak` | Flatpak | Cross-distro | 🚧 |
|
|
| `snap` | snapd | Cross-distro | 🚧 |
|
|
| `pkg` | pkg(8) | FreeBSD | 🚧 |
|
|
| `ports` | ports/packages | OpenBSD | 🚧 |
|
|
| `detect` | Auto-detection | All | 🚧 |
|
|
|
|
## Install
|
|
|
|
```bash
|
|
go get github.com/gogrlx/snack
|
|
```
|
|
|
|
## Usage
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
|
|
"github.com/gogrlx/snack"
|
|
"github.com/gogrlx/snack/apt"
|
|
)
|
|
|
|
func main() {
|
|
ctx := context.Background()
|
|
mgr := apt.New()
|
|
|
|
// Install a package
|
|
err := mgr.Install(ctx, []string{"nginx"}, snack.WithSudo(), snack.WithAssumeYes())
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Check if installed
|
|
installed, err := mgr.IsInstalled(ctx, "nginx")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
fmt.Println("nginx installed:", installed)
|
|
}
|
|
```
|
|
|
|
### Auto-detection
|
|
|
|
```go
|
|
import "github.com/gogrlx/snack/detect"
|
|
|
|
mgr, err := detect.Default()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
fmt.Println("Detected:", mgr.Name())
|
|
```
|
|
|
|
## Interfaces
|
|
|
|
snack uses a layered interface design. Every provider implements `Manager` (the base). Extended capabilities are optional — use type assertions to check support:
|
|
|
|
```go
|
|
// Base — every provider
|
|
snack.Manager // Install, Remove, Purge, Upgrade, Update, List, Search, Info, IsInstalled, Version
|
|
|
|
// Optional capabilities — type-assert to check
|
|
snack.VersionQuerier // LatestVersion, ListUpgrades, UpgradeAvailable, VersionCmp
|
|
snack.Holder // Hold, Unhold, ListHeld (version pinning)
|
|
snack.Cleaner // Autoremove, Clean (orphan/cache cleanup)
|
|
snack.FileOwner // FileList, Owner (file-to-package queries)
|
|
snack.RepoManager // ListRepos, AddRepo, RemoveRepo
|
|
snack.KeyManager // AddKey, RemoveKey, ListKeys (GPG keys)
|
|
snack.Grouper // GroupList, GroupInfo, GroupInstall
|
|
snack.NameNormalizer // NormalizeName, ParseArch
|
|
```
|
|
|
|
Check capabilities at runtime:
|
|
|
|
```go
|
|
caps := snack.GetCapabilities(mgr)
|
|
if caps.Hold {
|
|
mgr.(snack.Holder).Hold(ctx, []string{"nginx"})
|
|
}
|
|
```
|
|
|
|
## Design
|
|
|
|
- **Thin CLI wrappers** — each sub-package wraps a package manager's CLI tools. No FFI, no library bindings.
|
|
- **Common interface** — all managers implement `snack.Manager`, making them interchangeable.
|
|
- **Capability interfaces** — extended features via type assertion, so providers aren't forced to stub unsupported operations.
|
|
- **Per-provider mutex** — each provider serializes mutating operations independently; apt + snap can run in parallel.
|
|
- **Context-aware** — all operations accept `context.Context` for cancellation and timeouts.
|
|
- **Platform-safe** — build tags ensure packages compile everywhere but only run where appropriate.
|
|
- **No root assumption** — use `snack.WithSudo()` when elevated privileges are needed.
|
|
|
|
## Implementation Priority
|
|
|
|
1. pacman + AUR (Arch Linux)
|
|
2. apk (Alpine Linux)
|
|
3. apt + dpkg (Debian/Ubuntu)
|
|
4. dnf + rpm (Fedora/RHEL)
|
|
5. flatpak + snap (cross-distro)
|
|
6. pkg + ports (BSD)
|
|
|
|
## CLI
|
|
|
|
A companion CLI tool is planned for direct terminal usage:
|
|
|
|
```bash
|
|
snack install nginx
|
|
snack remove nginx
|
|
snack search redis
|
|
snack list
|
|
snack upgrade
|
|
```
|
|
|
|
## License
|
|
|
|
0BSD — see [LICENSE](LICENSE).
|