feat(snap): add Cleaner

This commit is contained in:
2026-03-05 23:19:11 +00:00
parent 4a711f0187
commit 6ba3d75258
3 changed files with 67 additions and 1 deletions

View File

@@ -7,7 +7,10 @@ import (
) )
// Compile-time interface checks. // 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. // LatestVersion returns the latest stable version of a snap.
func (s *Snap) LatestVersion(ctx context.Context, pkg string) (string, error) { 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) { func (s *Snap) VersionCmp(ctx context.Context, ver1, ver2 string) (int, error) {
return versionCmp(ctx, ver1, ver2) 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)
}

View File

@@ -232,6 +232,48 @@ func versionCmp(_ context.Context, ver1, ver2 string) (int, error) {
return semverCmp(ver1, ver2), nil 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=<rev> <name>`.
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) { func upgradePackages(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.InstallResult, error) {
o := snack.ApplyOptions(opts...) o := snack.ApplyOptions(opts...)
var toUpgrade []snack.Target var toUpgrade []snack.Target

View File

@@ -66,6 +66,14 @@ func versionCmp(_ context.Context, _, _ string) (int, error) {
return 0, snack.ErrUnsupportedPlatform 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) { func upgradePackages(_ context.Context, _ []snack.Target, _ ...snack.Option) (snack.InstallResult, error) {
return snack.InstallResult{}, snack.ErrUnsupportedPlatform return snack.InstallResult{}, snack.ErrUnsupportedPlatform
} }