Add DryRunner interface and DryRun capability for dry-run support detection

Co-authored-by: taigrr <8261498+taigrr@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-02-28 06:22:26 +00:00
parent 434c367687
commit 9f943e9097
7 changed files with 35 additions and 0 deletions

View File

@@ -11,8 +11,12 @@ var (
_ snack.VersionQuerier = (*Apk)(nil)
_ snack.Cleaner = (*Apk)(nil)
_ snack.FileOwner = (*Apk)(nil)
_ snack.DryRunner = (*Apk)(nil)
)
// SupportsDryRun reports that apk honors [snack.WithDryRun] via --simulate.
func (a *Apk) SupportsDryRun() bool { return true }
// LatestVersion returns the latest available version from configured repositories.
func (a *Apk) LatestVersion(ctx context.Context, pkg string) (string, error) {
return latestVersion(ctx, pkg)

View File

@@ -196,6 +196,9 @@ func (a *Apt) ParseArch(name string) (string, string) {
return parseArch(name)
}
// SupportsDryRun reports that apt honors [snack.WithDryRun] via --dry-run.
func (a *Apt) SupportsDryRun() bool { return true }
// Compile-time interface checks.
var (
_ snack.Manager = (*Apt)(nil)
@@ -206,4 +209,5 @@ var (
_ snack.RepoManager = (*Apt)(nil)
_ snack.KeyManager = (*Apt)(nil)
_ snack.NameNormalizer = (*Apt)(nil)
_ snack.DryRunner = (*Apt)(nil)
)

View File

@@ -12,6 +12,7 @@ type Capabilities struct {
KeyManagement bool
Groups bool
NameNormalize bool
DryRun bool
}
// GetCapabilities probes a Manager for all optional interface support.
@@ -24,6 +25,7 @@ func GetCapabilities(m Manager) Capabilities {
_, km := m.(KeyManager)
_, g := m.(Grouper)
_, nn := m.(NameNormalizer)
_, dr := m.(DryRunner)
return Capabilities{
VersionQuery: vq,
Hold: h,
@@ -33,5 +35,6 @@ func GetCapabilities(m Manager) Capabilities {
KeyManagement: km,
Groups: g,
NameNormalize: nn,
DryRun: dr,
}
}

View File

@@ -16,8 +16,12 @@ var (
_ snack.KeyManager = (*DNF)(nil)
_ snack.Grouper = (*DNF)(nil)
_ snack.NameNormalizer = (*DNF)(nil)
_ snack.DryRunner = (*DNF)(nil)
)
// SupportsDryRun reports that dnf honors [snack.WithDryRun] via --setopt=tsflags=test.
func (d *DNF) SupportsDryRun() bool { return true }
// LatestVersion returns the latest available version from configured repositories.
func (d *DNF) LatestVersion(ctx context.Context, pkg string) (string, error) {
return latestVersion(ctx, pkg, d.v5)

View File

@@ -12,12 +12,16 @@ var (
_ snack.Cleaner = (*Pacman)(nil)
_ snack.FileOwner = (*Pacman)(nil)
_ snack.Grouper = (*Pacman)(nil)
_ snack.DryRunner = (*Pacman)(nil)
)
// NOTE: snack.Holder is not implemented for pacman. While pacman supports
// IgnorePkg in /etc/pacman.conf, there is no clean CLI command to hold/unhold
// packages. pacman-contrib provides some tooling but it's not standard.
// SupportsDryRun reports that pacman honors [snack.WithDryRun] via --print.
func (p *Pacman) SupportsDryRun() bool { return true }
// LatestVersion returns the latest available version from configured repositories.
func (p *Pacman) LatestVersion(ctx context.Context, pkg string) (string, error) {
return latestVersion(ctx, pkg)

View File

@@ -199,3 +199,18 @@ type NameNormalizer interface {
// Returns the name without arch and the arch string.
ParseArch(name string) (string, string)
}
// DryRunner reports whether a Manager backend natively supports dry-run mode.
// Backends that implement this interface honor [WithDryRun] in Install, Remove,
// Purge, and Upgrade and pass the appropriate flag to the underlying CLI
// (e.g. apt-get --dry-run, apk --simulate, dnf --setopt=tsflags=test,
// pacman --print).
//
// Backends that do NOT implement this interface (snap, flatpak, rpm, ports)
// silently ignore [WithDryRun].
//
// Supported by: apt, apk, dnf, pacman.
type DryRunner interface {
// SupportsDryRun reports whether this backend honors [WithDryRun].
SupportsDryRun() bool
}

View File

@@ -91,6 +91,7 @@ func TestGetCapabilities_NilSafe(t *testing.T) {
assert.False(t, caps.KeyManagement)
assert.False(t, caps.Groups)
assert.False(t, caps.NameNormalize)
assert.False(t, caps.DryRun)
}
func TestErrors(t *testing.T) {