mirror of
https://github.com/gogrlx/snack.git
synced 2026-04-02 05:08:42 -07:00
feat: add per-provider mutex and Target-aware implementations
- Add snack.Locker embed for per-provider mutex serialization - Update all providers (pacman, apk, apt, dpkg) to use []Target with version pinning support (pkg=version syntax) - Add lock/unlock to all mutating operations (Install, Remove, Purge, Upgrade, Update) - Add snack.TargetNames helper and formatTargets per provider - apt: add FromRepo (-t) and Reinstall support - dpkg: use Target.Source for .deb file paths in Install
This commit is contained in:
20
apt/apt.go
20
apt/apt.go
@@ -8,7 +8,9 @@ import (
|
||||
)
|
||||
|
||||
// Apt implements the snack.Manager interface using apt-get and apt-cache.
|
||||
type Apt struct{}
|
||||
type Apt struct {
|
||||
snack.Locker
|
||||
}
|
||||
|
||||
// New returns a new Apt manager.
|
||||
func New() *Apt {
|
||||
@@ -19,27 +21,37 @@ func New() *Apt {
|
||||
func (a *Apt) Name() string { return "apt" }
|
||||
|
||||
// Install one or more packages.
|
||||
func (a *Apt) Install(ctx context.Context, pkgs []string, opts ...snack.Option) error {
|
||||
func (a *Apt) Install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) error {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
return install(ctx, pkgs, opts...)
|
||||
}
|
||||
|
||||
// Remove one or more packages.
|
||||
func (a *Apt) Remove(ctx context.Context, pkgs []string, opts ...snack.Option) error {
|
||||
func (a *Apt) Remove(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) error {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
return remove(ctx, pkgs, opts...)
|
||||
}
|
||||
|
||||
// Purge one or more packages including config files.
|
||||
func (a *Apt) Purge(ctx context.Context, pkgs []string, opts ...snack.Option) error {
|
||||
func (a *Apt) Purge(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) error {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
return purge(ctx, pkgs, opts...)
|
||||
}
|
||||
|
||||
// Upgrade all installed packages.
|
||||
func (a *Apt) Upgrade(ctx context.Context, opts ...snack.Option) error {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
return upgrade(ctx, opts...)
|
||||
}
|
||||
|
||||
// Update refreshes the package index.
|
||||
func (a *Apt) Update(ctx context.Context) error {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
return update(ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,21 @@ func available() bool {
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func buildArgs(command string, pkgs []string, opts ...snack.Option) []string {
|
||||
// formatTargets converts targets to apt CLI arguments.
|
||||
// apt uses "pkg=version" for version pinning.
|
||||
func formatTargets(targets []snack.Target) []string {
|
||||
args := make([]string, 0, len(targets))
|
||||
for _, t := range targets {
|
||||
if t.Version != "" {
|
||||
args = append(args, t.Name+"="+t.Version)
|
||||
} else {
|
||||
args = append(args, t.Name)
|
||||
}
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func buildArgs(command string, pkgs []snack.Target, opts ...snack.Option) []string {
|
||||
o := snack.ApplyOptions(opts...)
|
||||
var args []string
|
||||
if o.Sudo {
|
||||
@@ -30,11 +44,17 @@ func buildArgs(command string, pkgs []string, opts ...snack.Option) []string {
|
||||
if o.DryRun {
|
||||
args = append(args, "--dry-run")
|
||||
}
|
||||
args = append(args, pkgs...)
|
||||
if o.FromRepo != "" {
|
||||
args = append(args, "-t", o.FromRepo)
|
||||
}
|
||||
if o.Reinstall && command == "install" {
|
||||
args = append(args, "--reinstall")
|
||||
}
|
||||
args = append(args, formatTargets(pkgs)...)
|
||||
return args
|
||||
}
|
||||
|
||||
func runAptGet(ctx context.Context, command string, pkgs []string, opts ...snack.Option) error {
|
||||
func runAptGet(ctx context.Context, command string, pkgs []snack.Target, opts ...snack.Option) error {
|
||||
args := buildArgs(command, pkgs, opts...)
|
||||
var cmd *exec.Cmd
|
||||
if args[0] == "sudo" {
|
||||
@@ -57,15 +77,15 @@ func runAptGet(ctx context.Context, command string, pkgs []string, opts ...snack
|
||||
return nil
|
||||
}
|
||||
|
||||
func install(ctx context.Context, pkgs []string, opts ...snack.Option) error {
|
||||
func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) error {
|
||||
return runAptGet(ctx, "install", pkgs, opts...)
|
||||
}
|
||||
|
||||
func remove(ctx context.Context, pkgs []string, opts ...snack.Option) error {
|
||||
func remove(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) error {
|
||||
return runAptGet(ctx, "remove", pkgs, opts...)
|
||||
}
|
||||
|
||||
func purge(ctx context.Context, pkgs []string, opts ...snack.Option) error {
|
||||
func purge(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) error {
|
||||
return runAptGet(ctx, "purge", pkgs, opts...)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,15 +10,15 @@ import (
|
||||
|
||||
func available() bool { return false }
|
||||
|
||||
func install(_ context.Context, _ []string, _ ...snack.Option) error {
|
||||
func install(_ context.Context, _ []snack.Target, _ ...snack.Option) error {
|
||||
return snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func remove(_ context.Context, _ []string, _ ...snack.Option) error {
|
||||
func remove(_ context.Context, _ []snack.Target, _ ...snack.Option) error {
|
||||
return snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func purge(_ context.Context, _ []string, _ ...snack.Option) error {
|
||||
func purge(_ context.Context, _ []snack.Target, _ ...snack.Option) error {
|
||||
return snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user