From a1d13e8a7dbc542423f9775eb28b2d9a70482a03 Mon Sep 17 00:00:00 2001 From: Tai Groot Date: Thu, 5 Mar 2026 23:19:11 +0000 Subject: [PATCH] feat(snap): add Cleaner --- snap/capabilities.go | 18 +++++++++++++++++- snap/snap_linux.go | 42 ++++++++++++++++++++++++++++++++++++++++++ snap/snap_other.go | 8 ++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/snap/capabilities.go b/snap/capabilities.go index 6aba608..3214d2c 100644 --- a/snap/capabilities.go +++ b/snap/capabilities.go @@ -7,7 +7,10 @@ import ( ) // Compile-time interface checks. -var _ snack.VersionQuerier = (*Snap)(nil) +var ( + _ snack.VersionQuerier = (*Snap)(nil) + _ snack.Cleaner = (*Snap)(nil) +) // LatestVersion returns the latest stable version of a snap. func (s *Snap) LatestVersion(ctx context.Context, pkg string) (string, error) { @@ -28,3 +31,16 @@ func (s *Snap) UpgradeAvailable(ctx context.Context, pkg string) (bool, error) { func (s *Snap) VersionCmp(ctx context.Context, ver1, ver2 string) (int, error) { return versionCmp(ctx, ver1, ver2) } + +// Autoremove is a no-op for snap. Snaps are self-contained and do not +// have orphan dependencies. +func (s *Snap) Autoremove(ctx context.Context, opts ...snack.Option) error { + return autoremove(ctx, opts...) +} + +// Clean removes old disabled snap revisions to free disk space. +func (s *Snap) Clean(ctx context.Context) error { + s.Lock() + defer s.Unlock() + return clean(ctx) +} diff --git a/snap/snap_linux.go b/snap/snap_linux.go index 746dd85..8de5e97 100644 --- a/snap/snap_linux.go +++ b/snap/snap_linux.go @@ -232,6 +232,48 @@ func versionCmp(_ context.Context, ver1, ver2 string) (int, error) { return semverCmp(ver1, ver2), nil } +// autoremove is a no-op for snap. Snaps are self-contained and do not +// have orphan dependencies. +func autoremove(_ context.Context, _ ...snack.Option) error { + return nil +} + +// clean removes old disabled snap revisions to free disk space. +// It runs `snap list --all` to find disabled revisions, then removes +// each one with `snap remove --revision= `. +func clean(ctx context.Context) error { + out, err := run(ctx, []string{"list", "--all"}) + if err != nil { + return fmt.Errorf("snap clean: %w", err) + } + // Parse output for disabled revisions + // Header: Name Version Rev Tracking Publisher Notes + // Disabled snaps have "disabled" in the Notes column + lines := strings.Split(out, "\n") + for i, line := range lines { + if i == 0 { // skip header + continue + } + line = strings.TrimSpace(line) + if line == "" { + continue + } + if !strings.Contains(line, "disabled") { + continue + } + fields := strings.Fields(line) + if len(fields) < 3 { + continue + } + name := fields[0] + rev := fields[2] + if _, err := run(ctx, []string{"remove", "--revision=" + rev, name}); err != nil { + return fmt.Errorf("snap clean %s rev %s: %w", name, rev, err) + } + } + return nil +} + func upgradePackages(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.InstallResult, error) { o := snack.ApplyOptions(opts...) var toUpgrade []snack.Target diff --git a/snap/snap_other.go b/snap/snap_other.go index 4bdf614..3831667 100644 --- a/snap/snap_other.go +++ b/snap/snap_other.go @@ -66,6 +66,14 @@ func versionCmp(_ context.Context, _, _ string) (int, error) { return 0, snack.ErrUnsupportedPlatform } +func autoremove(_ context.Context, _ ...snack.Option) error { + return snack.ErrUnsupportedPlatform +} + +func clean(_ context.Context) error { + return snack.ErrUnsupportedPlatform +} + func upgradePackages(_ context.Context, _ []snack.Target, _ ...snack.Option) (snack.InstallResult, error) { return snack.InstallResult{}, snack.ErrUnsupportedPlatform }