Browse Source

Add OpenSpec change for pkg modularization refactor

master
AI Bot 4 days ago committed by Riyyi
parent
commit
9aeedb39b8
  1. 2
      openspec/changes/refactor-modularize-pkg/.openspec.yaml
  2. 141
      openspec/changes/refactor-modularize-pkg/design.md
  3. 30
      openspec/changes/refactor-modularize-pkg/proposal.md
  4. 15
      openspec/changes/refactor-modularize-pkg/specs/scope/scope.md
  5. 38
      openspec/changes/refactor-modularize-pkg/tasks.md

2
openspec/changes/refactor-modularize-pkg/.openspec.yaml

@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-04-14

141
openspec/changes/refactor-modularize-pkg/design.md

@ -0,0 +1,141 @@
# Design: Refactor pkg Into Modular Packages
## New Structure
```
pkg/
├── pacman/ # write operations only
│ └── pacman.go
├── fetch/ # package resolution (NEW)
│ └── fetch.go
├── validation/ # DB freshness (existing, expand)
│ └── validation.go
├── output/ # (unchanged)
│ └── output.go
├── merge/ # (unchanged)
│ └── merge.go
└── input/ # (unchanged)
└── input.go
```
## Package Responsibilities
### pkg/fetch (NEW)
```
type Fetcher struct {
handle dyalpm.Handle
localDB dyalpm.Database
syncDBs []dyalpm.Database
aurCache map[string]AURPackage
}
func New() *Fetcher
func (f *Fetcher) Close() error
func (f *Fetcher) Resolve(packages []string) (map[string]*PackageInfo, error)
func (f *Fetcher) ListOrphans() ([]string, error)
```
Extracted from `pacman.go`:
- `buildLocalPkgMap()`
- `checkSyncDBs()`
- `resolvePackages()`
- AUR cache (`ensureAURCache()`, `fetchAURInfo()`)
### pkg/pacman (REFACTORED)
```
func Sync(packages []string) (*output.Result, error)
func DryRun(packages []string) (*output.Result, error)
func MarkAsExplicit(packages []string) error
func MarkAllAsDeps() error
func CleanupOrphans() (int, error)
```
Write actions only:
- `Sync()` - calls `Fetcher` for resolution, then pacman commands
- `DryRun()` - calls `Fetcher.Resolve()` + `ListOrphans()`
- `MarkAsExplicit()`, `MarkAllAsDeps()`
- `CleanupOrphans()` - calls `ListOrphans()` then removes
### pkg/validation (REFACTORED)
```
func CheckDBFreshness() error
```
Keep as-is: checks lock file age, auto-synces if stale.
Remove from `pacman.go`:
- `IsDBFresh()` - replaced by `CheckDBFreshness()`
- `SyncDB()` - called by validation when stale
### Orphan Deduplication
```go
// In fetch/fetch.go
func (f *Fetcher) ListOrphans() ([]string, error) {
cmd := exec.Command("pacman", "-Qdtq")
// ...
}
// In pacman/pacman.go
func CleanupOrphans() (int, error) {
orphans, err := fetcher.ListOrphans() // reuse
if err != nil || len(orphans) == 0 {
return 0, nil
}
// ... remove
}
func DryRun(...) (*output.Result, error) {
orphans, err := fetcher.ListOrphans() // reuse
// ...
}
```
## Data Structures Move to fetch
```go
// In fetch/fetch.go
type PackageInfo struct {
Name string
InAUR bool
Exists bool
Installed bool
AURInfo *AURPackage
syncPkg dyalpm.Package
}
type AURResponse struct {
Results []AURPackage `json:"results"`
}
type AURPackage struct {
Name string `json:"Name"`
PackageBase string `json:"PackageBase"`
Version string `json:"Version"`
URL string `json:"URL"`
}
```
## Import Changes
`pkg/pacman/fetch.go` will need:
- `github.com/Jguer/dyalpm`
- `github.com/Riyyi/declpac/pkg/output`
`pkg/pacman/pacman.go` will need:
- `github.com/Riyyi/declpac/pkg/fetch`
- `github.com/Riyyi/declpac/pkg/output`
## Dependencies to Add
- New import: `pkg/fetch` in `pacman` package
## No Changes To
- CLI entry points
- `output.Result` struct
- `input.ReadPackages()`
- `merge.Merge()`

30
openspec/changes/refactor-modularize-pkg/proposal.md

@ -0,0 +1,30 @@
# Proposal: Refactor pkg Into Modular Packages
## Summary
Split monolithic `pkg/pacman/pacman.go` into focused packages: `fetch` (package resolution), `validation` (DB checks), and keep `pacman` for write actions only. Also deduplicate orphan detection logic.
## Motivation
`pacman.go` is 645 lines doing too much:
- Package resolution (local + sync DBs + AUR)
- DB freshness checks
- Pacman write operations (sync, mark, clean)
- Orphan listing/cleanup
This violates single responsibility. Hard to test, reason about, or reuse. Also has duplication:
- `validation.CheckDBFreshness()` and `pacman.IsDBFresh()` both check DB freshness
- `listOrphans()` and `CleanupOrphans()` duplicate orphan detection
## Scope
- Extract package resolution to new `pkg/fetch/`
- Move DB freshness to `pkg/validation/` (keep `CheckDBFreshness()`)
- Keep only write actions in `pkg/pacman/`
- Deduplicate orphan logic: one function for listing, reuse in cleanup and dry-run
## Out of Scope
- No new features
- No API changes to CLI
- No changes to `pkg/output/`, `pkg/merge/`, `pkg/input/`

15
openspec/changes/refactor-modularize-pkg/specs/scope/scope.md

@ -0,0 +1,15 @@
# Scope
## In Scope
- Extract package resolution from pacman.go to pkg/fetch
- Deduplicate orphan listing
- Keep pacman write operations in pacman package
- Maintain existing CLI API
## Out of Scope
- New features
- New package management backends (e.g., libalpm alternatives)
- Config file changes
- State file format changes

38
openspec/changes/refactor-modularize-pkg/tasks.md

@ -0,0 +1,38 @@
# Tasks: Refactor pkg Into Modular Packages
## Phase 1: Create pkg/fetch
- [ ] 1.1 Create `pkg/fetch/fetch.go`
- [ ] 1.2 Move `AURResponse`, `AURPackage`, `PackageInfo` structs to fetch
- [ ] 1.3 Move `buildLocalPkgMap()` to fetch as `Fetcher.buildLocalPkgMap()`
- [ ] 1.4 Move `checkSyncDBs()` to fetch as `Fetcher.checkSyncDBs()`
- [ ] 1.5 Move `resolvePackages()` to fetch as `Fetcher.Resolve()`
- [ ] 1.6 Move AUR cache methods (`ensureAURCache`, `fetchAURInfo`) to fetch
- [ ] 1.7 Add `New()` and `Close()` to Fetcher
- [ ] 1.8 Add `ListOrphans()` to Fetcher
## Phase 2: Refactor pkg/pacman
- [ ] 2.1 Remove from pacman.go (now in fetch):
- `buildLocalPkgMap()`
- `checkSyncDBs()`
- `resolvePackages()`
- `ensureAURCache()`
- `fetchAURInfo()`
- `AURResponse`, `AURPackage`, `PackageInfo` structs
- [ ] 2.2 Remove `IsDBFresh()` and `SyncDB()` (use validation instead)
- [ ] 2.3 Update imports in pacman.go to include fetch package
- [ ] 2.4 Update `Sync()` to use `fetch.Fetcher` for resolution
- [ ] 2.5 Update `DryRun()` to call `fetcher.ListOrphans()` instead of duplicate call
- [ ] 2.6 Update `CleanupOrphans()` to call `fetcher.ListOrphans()` instead of duplicate call
## Phase 3: Clean Up Validation
- [ ] 3.1 Keep `validation.CheckDBFreshness()` as-is
- [ ] 3.2 Remove any remaining DB freshness duplication
## Phase 4: Verify
- [ ] 4.1 Run tests (if any exist)
- [ ] 4.2 Build: `go build ./...`
- [ ] 4.3 Verify CLI still works: test dry-run, sync, orphan cleanup
Loading…
Cancel
Save