Browse Source

Add safety check for package list validation

master
AI Bot 1 week ago committed by Riyyi
parent
commit
5ad29767c9
  1. 3
      README.md
  2. 15
      cmd/declpac/main.go
  3. 11
      pkg/merge/merge.go
  4. 6
      pkg/output/output.go
  5. 13
      pkg/pacman/pacman.go
  6. 19
      pkg/pacman/read/read.go

3
README.md

@ -61,7 +61,8 @@ docker
| Flag | Alias | Description |
|------|-------|-------------|
| `--state` | `-s` | State file to read package list from (can be used multiple times) |
| `--state` | `-s` | State file(s) to read package list from (can be used multiple times) |
| `--nocheck` | | Skip safety check (allow significant package count reductions)
| `--dry-run` | | Preview changes without applying them |
| `--verbose` | `-v` | Enable verbose output |
| `--help` | `-h` | Show help message |

15
cmd/declpac/main.go

@ -18,7 +18,7 @@ import (
type Config struct {
StateFiles []string
NoConfirm bool
NoCheck bool
DryRun bool
Verbose bool
}
@ -36,6 +36,11 @@ func main() {
Usage: "State file(s) to read package list from",
Destination: &cfg.StateFiles,
},
&cli.BoolFlag{
Name: "nocheck",
Usage: "Skip safety check",
Destination: &cfg.NoCheck,
},
&cli.BoolFlag{
Name: "dry-run",
Usage: "Simulate the sync without making changes",
@ -70,7 +75,11 @@ func run(cfg *Config) error {
}
log.Debug("run: packages read (%.2fs)", time.Since(start).Seconds())
merged := merge.Merge(packages)
merged, err := merge.Merge(packages)
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
return err
}
if cfg.DryRun {
result, err := read.DryRun(merged)
@ -89,7 +98,7 @@ func run(cfg *Config) error {
}
defer log.Close()
result, err := pacman.Sync(merged)
result, err := pacman.Sync(merged, cfg.NoCheck)
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
return err

11
pkg/merge/merge.go

@ -1,9 +1,16 @@
package merge
func Merge(packages map[string]bool) []string {
import "errors"
var ErrEmptyList = errors.New("package list is empty")
func Merge(packages map[string]bool) ([]string, error) {
result := make([]string, 0, len(packages))
for name := range packages {
result = append(result, name)
}
return result
if len(result) == 0 {
return nil, ErrEmptyList
}
return result, nil
}

6
pkg/output/output.go

@ -14,13 +14,13 @@ type Result struct {
func Format(r *Result) string {
var b strings.Builder
b.WriteString(fmt.Sprintf("Installed %d packages, removed %d packages", r.Installed, r.Removed))
b.WriteString(fmt.Sprintf("installed %d packages, removed %d packages", r.Installed, r.Removed))
if len(r.ToInstall) > 0 {
b.WriteString("\nWould install: ")
b.WriteString("\nwould install: ")
b.WriteString(strings.Join(r.ToInstall, ", "))
}
if len(r.ToRemove) > 0 {
b.WriteString("\nWould remove: ")
b.WriteString("\nwould remove: ")
b.WriteString(strings.Join(r.ToRemove, ", "))
}
return b.String()

13
pkg/pacman/pacman.go

@ -13,10 +13,21 @@ import (
"github.com/Riyyi/declpac/pkg/pacman/sync"
)
func Sync(packages []string) (*output.Result, error) {
func Sync(packages []string, noCheck bool) (*output.Result, error) {
start := time.Now()
log.Debug("Sync: starting...")
explicitList, err := read.ExplicitList()
if err != nil {
return nil, err
}
explicitCount := len(explicitList)
if !noCheck && len(packages) < explicitCount/2 {
errMsg := "safety check: state packages (%d) less than half of explicitly installed (%d), override with --nocheck"
return nil, fmt.Errorf(errMsg, len(packages), explicitCount)
}
list, err := read.List()
if err != nil {
return nil, err

19
pkg/pacman/read/read.go

@ -35,6 +35,25 @@ func List() ([]string, error) {
return list, nil
}
func ExplicitList() ([]string, error) {
start := time.Now()
log.Debug("ExplicitList: starting...")
cmd := exec.Command("pacman", "-Qqe")
output, err := cmd.Output()
if err != nil {
return nil, err
}
list := strings.Split(strings.TrimSpace(string(output)), "\n")
if len(list) > 0 && list[0] == "" {
list = nil
}
log.Debug("ExplicitList: done (%.2fs)", time.Since(start).Seconds())
return list, nil
}
func ListOrphans() ([]string, error) {
start := time.Now()
log.Debug("ListOrphans: starting...")

Loading…
Cancel
Save