Fix Reinstall, version-pinned, error propagation, and DryRun bugs in Install/Remove pre-filter

Co-authored-by: taigrr <8261498+taigrr@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-02-28 06:59:51 +00:00
parent 3d6baf3314
commit a3e4827e5e
10 changed files with 182 additions and 36 deletions

View File

@@ -67,10 +67,18 @@ func formatTargets(targets []snack.Target) []string {
}
func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.InstallResult, error) {
o := snack.ApplyOptions(opts...)
var toInstall []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.Reinstall || t.Version != "" || o.DryRun {
toInstall = append(toInstall, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.InstallResult{}, err
}
if ok {
unchanged = append(unchanged, t.Name)
} else {
@@ -92,10 +100,18 @@ func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (sn
}
func remove(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.RemoveResult, error) {
o := snack.ApplyOptions(opts...)
var toRemove []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.DryRun {
toRemove = append(toRemove, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.RemoveResult{}, err
}
if !ok {
unchanged = append(unchanged, t.Name)
} else {

View File

@@ -78,10 +78,18 @@ func runAptGet(ctx context.Context, command string, pkgs []snack.Target, opts ..
}
func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.InstallResult, error) {
o := snack.ApplyOptions(opts...)
var toInstall []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.Reinstall || t.Version != "" || o.DryRun {
toInstall = append(toInstall, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.InstallResult{}, err
}
if ok {
unchanged = append(unchanged, t.Name)
} else {
@@ -102,10 +110,18 @@ func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (sn
}
func remove(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.RemoveResult, error) {
o := snack.ApplyOptions(opts...)
var toRemove []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.DryRun {
toRemove = append(toRemove, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.RemoveResult{}, err
}
if !ok {
unchanged = append(unchanged, t.Name)
} else {

View File

@@ -90,17 +90,24 @@ func formatTargets(targets []snack.Target) []string {
}
func install(ctx context.Context, v5 bool, pkgs []snack.Target, opts ...snack.Option) (snack.InstallResult, error) {
o := snack.ApplyOptions(opts...)
var toInstall []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name, v5)
if o.Reinstall || t.Version != "" || o.DryRun {
toInstall = append(toInstall, t)
continue
}
ok, err := isInstalled(ctx, t.Name, v5)
if err != nil {
return snack.InstallResult{}, err
}
if ok {
unchanged = append(unchanged, t.Name)
} else {
toInstall = append(toInstall, t)
}
}
o := snack.ApplyOptions(opts...)
if len(toInstall) > 0 {
base := []string{"install", "-y"}
if o.Refresh {
@@ -132,17 +139,24 @@ func install(ctx context.Context, v5 bool, pkgs []snack.Target, opts ...snack.Op
}
func remove(ctx context.Context, v5 bool, pkgs []snack.Target, opts ...snack.Option) (snack.RemoveResult, error) {
o := snack.ApplyOptions(opts...)
var toRemove []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name, v5)
if o.DryRun {
toRemove = append(toRemove, t)
continue
}
ok, err := isInstalled(ctx, t.Name, v5)
if err != nil {
return snack.RemoveResult{}, err
}
if !ok {
unchanged = append(unchanged, t.Name)
} else {
toRemove = append(toRemove, t)
}
}
o := snack.ApplyOptions(opts...)
if len(toRemove) > 0 {
args := append([]string{"remove", "-y"}, snack.TargetNames(toRemove)...)
if _, err := run(ctx, args, o); err != nil {

View File

@@ -18,17 +18,24 @@ func available() bool {
}
func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.InstallResult, error) {
o := snack.ApplyOptions(opts...)
var toInstall []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.Reinstall || t.Version != "" || o.DryRun {
toInstall = append(toInstall, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.InstallResult{}, err
}
if ok {
unchanged = append(unchanged, t.Name)
} else {
toInstall = append(toInstall, t)
}
}
o := snack.ApplyOptions(opts...)
if len(toInstall) > 0 {
var args []string
if o.Sudo {
@@ -65,17 +72,24 @@ func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (sn
}
func remove(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.RemoveResult, error) {
o := snack.ApplyOptions(opts...)
var toRemove []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.DryRun {
toRemove = append(toRemove, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.RemoveResult{}, err
}
if !ok {
unchanged = append(unchanged, t.Name)
} else {
toRemove = append(toRemove, t)
}
}
o := snack.ApplyOptions(opts...)
if len(toRemove) > 0 {
var args []string
if o.Sudo {

View File

@@ -34,11 +34,18 @@ func run(ctx context.Context, args []string) (string, error) {
}
func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.InstallResult, error) {
_ = snack.ApplyOptions(opts...)
o := snack.ApplyOptions(opts...)
var toInstall []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.Reinstall || t.Version != "" || o.DryRun {
toInstall = append(toInstall, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.InstallResult{}, err
}
if ok {
unchanged = append(unchanged, t.Name)
} else {
@@ -63,11 +70,19 @@ func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (sn
return snack.InstallResult{Installed: installed, Unchanged: unchanged}, nil
}
func remove(ctx context.Context, pkgs []snack.Target, _ ...snack.Option) (snack.RemoveResult, error) {
func remove(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.RemoveResult, error) {
o := snack.ApplyOptions(opts...)
var toRemove []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.DryRun {
toRemove = append(toRemove, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.RemoveResult{}, err
}
if !ok {
unchanged = append(unchanged, t.Name)
} else {

View File

@@ -73,17 +73,24 @@ func formatTargets(targets []snack.Target) []string {
}
func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.InstallResult, error) {
o := snack.ApplyOptions(opts...)
var toInstall []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.Reinstall || t.Version != "" || o.DryRun {
toInstall = append(toInstall, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.InstallResult{}, err
}
if ok {
unchanged = append(unchanged, t.Name)
} else {
toInstall = append(toInstall, t)
}
}
o := snack.ApplyOptions(opts...)
if len(toInstall) > 0 {
base := []string{"-S", "--noconfirm"}
if o.Refresh {
@@ -103,17 +110,24 @@ func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (sn
}
func remove(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.RemoveResult, error) {
o := snack.ApplyOptions(opts...)
var toRemove []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.DryRun {
toRemove = append(toRemove, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.RemoveResult{}, err
}
if !ok {
unchanged = append(unchanged, t.Name)
} else {
toRemove = append(toRemove, t)
}
}
o := snack.ApplyOptions(opts...)
if len(toRemove) > 0 {
args := append([]string{"-R", "--noconfirm"}, snack.TargetNames(toRemove)...)
if _, err := run(ctx, args, o); err != nil {

View File

@@ -55,17 +55,24 @@ func formatTargets(targets []snack.Target) []string {
}
func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.InstallResult, error) {
o := snack.ApplyOptions(opts...)
var toInstall []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.Reinstall || t.Version != "" || o.DryRun {
toInstall = append(toInstall, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.InstallResult{}, err
}
if ok {
unchanged = append(unchanged, t.Name)
} else {
toInstall = append(toInstall, t)
}
}
o := snack.ApplyOptions(opts...)
if len(toInstall) > 0 {
args := append([]string{"install", "-y"}, formatTargets(toInstall)...)
if _, err := run(ctx, args, o); err != nil {
@@ -81,17 +88,24 @@ func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (sn
}
func remove(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.RemoveResult, error) {
o := snack.ApplyOptions(opts...)
var toRemove []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.DryRun {
toRemove = append(toRemove, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.RemoveResult{}, err
}
if !ok {
unchanged = append(unchanged, t.Name)
} else {
toRemove = append(toRemove, t)
}
}
o := snack.ApplyOptions(opts...)
if len(toRemove) > 0 {
args := append([]string{"delete", "-y"}, snack.TargetNames(toRemove)...)
if _, err := run(ctx, args, o); err != nil {

View File

@@ -43,17 +43,24 @@ func runCmd(ctx context.Context, name string, args []string, opts snack.Options)
}
func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.InstallResult, error) {
o := snack.ApplyOptions(opts...)
var toInstall []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.Reinstall || t.Version != "" || o.DryRun {
toInstall = append(toInstall, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.InstallResult{}, err
}
if ok {
unchanged = append(unchanged, t.Name)
} else {
toInstall = append(toInstall, t)
}
}
o := snack.ApplyOptions(opts...)
if len(toInstall) > 0 {
if _, err := runCmd(ctx, "pkg_add", snack.TargetNames(toInstall), o); err != nil {
return snack.InstallResult{}, err
@@ -68,17 +75,24 @@ func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (sn
}
func remove(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.RemoveResult, error) {
o := snack.ApplyOptions(opts...)
var toRemove []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.DryRun {
toRemove = append(toRemove, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.RemoveResult{}, err
}
if !ok {
unchanged = append(unchanged, t.Name)
} else {
toRemove = append(toRemove, t)
}
}
o := snack.ApplyOptions(opts...)
if len(toRemove) > 0 {
if _, err := runCmd(ctx, "pkg_delete", snack.TargetNames(toRemove), o); err != nil {
return snack.RemoveResult{}, err

View File

@@ -68,17 +68,24 @@ func formatSources(targets []snack.Target) []string {
}
func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.InstallResult, error) {
o := snack.ApplyOptions(opts...)
var toInstall []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.Reinstall || t.Version != "" || o.DryRun {
toInstall = append(toInstall, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.InstallResult{}, err
}
if ok {
unchanged = append(unchanged, t.Name)
} else {
toInstall = append(toInstall, t)
}
}
o := snack.ApplyOptions(opts...)
if len(toInstall) > 0 {
args := append([]string{"-i"}, formatSources(toInstall)...)
if _, err := runWithSudo(ctx, args, o.Sudo); err != nil {
@@ -94,17 +101,24 @@ func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (sn
}
func remove(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.RemoveResult, error) {
o := snack.ApplyOptions(opts...)
var toRemove []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.DryRun {
toRemove = append(toRemove, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.RemoveResult{}, err
}
if !ok {
unchanged = append(unchanged, t.Name)
} else {
toRemove = append(toRemove, t)
}
}
o := snack.ApplyOptions(opts...)
if len(toRemove) > 0 {
args := append([]string{"-e"}, snack.TargetNames(toRemove)...)
if _, err := runWithSudo(ctx, args, o.Sudo); err != nil {

View File

@@ -38,11 +38,18 @@ func run(ctx context.Context, args []string) (string, error) {
}
func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.InstallResult, error) {
_ = snack.ApplyOptions(opts...)
o := snack.ApplyOptions(opts...)
var toInstall []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.Reinstall || t.Version != "" || o.DryRun {
toInstall = append(toInstall, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.InstallResult{}, err
}
if ok {
unchanged = append(unchanged, t.Name)
} else {
@@ -71,11 +78,19 @@ func install(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (sn
return snack.InstallResult{Installed: installed, Unchanged: unchanged}, nil
}
func remove(ctx context.Context, pkgs []snack.Target, _ ...snack.Option) (snack.RemoveResult, error) {
func remove(ctx context.Context, pkgs []snack.Target, opts ...snack.Option) (snack.RemoveResult, error) {
o := snack.ApplyOptions(opts...)
var toRemove []snack.Target
var unchanged []string
for _, t := range pkgs {
ok, _ := isInstalled(ctx, t.Name)
if o.DryRun {
toRemove = append(toRemove, t)
continue
}
ok, err := isInstalled(ctx, t.Name)
if err != nil {
return snack.RemoveResult{}, err
}
if !ok {
unchanged = append(unchanged, t.Name)
} else {